2

In an HTTP request one can specify most parameters multiple times, HTTP supports this out of the box. But how can this be done when using Class UrlFetchApp of Google Apps Script?

I am trying to send mail using Mailgun API and want to attach multiple attachments. Here's what Mailgun API says about this:

Note that you can specify most parameters multiple times, HTTP supports this out of the box. This makes sense for parameters like cc, to or attachment.

Here are some other similar questions related to other languages or platforms but none of these help:

Here's my code that works for a single attachment. Note that the function mailgun() takes exact same arguments as GmailApp.sendEmail() for consistency purposes:

function mailgun(recipient, subject, body, options){

var params = {
  "method":"POST",
  "headers": {
    "Authorization" : "Basic " + Utilities.base64Encode('api:key-goes-here')
  },
  "payload": {
    "to": recipient,
    "subject": subject,
    "text": body,
    "html": options.htmlBody
  },
  "muteHttpExceptions": true,
};

if(options.hasOwnProperty("bcc"))
  params.payload.bcc = options.bcc;

if(options.hasOwnProperty("cc"))
  params.payload.cc = options.cc;

if(options.hasOwnProperty("replyTo"))
  params.payload['h:Reply-To'] = options.replyTo;

if(options.hasOwnProperty("name")){
  params.payload.from = options.name + ' <' + options.from + '>';
} else {
  params.payload.from = options.from;
}

if(options.hasOwnProperty("attachments")){
  params.payload.attachment = options.attachments[0];
}

var response = UrlFetchApp.fetch('https://api.mailgun.net/v3/domain.com/messages', params);
var responseCode = response.getResponseCode();
var responseObj = JSON.parse(response.getContentText());

if(responseCode != 200) return 'Mailgun error: '+responseObj.message;  

return true;

}

If I use this code, the mail goes through but without attachments:

if(options.hasOwnProperty("attachments")){
  params.payload.attachment = [options.attachments[0],
                               options.attachments[1]
                              ];
}

The Mailgun API says 'You can post multiple attachment values'. This is a little misleading, as essentially they mean that 'you can specify attachment parameter multiple times' to send multiple attachments.

As payload is an object this is not possible using UrlFetchApp and I guess the only way is to manually build the multipart payload without relying on auto-generation of UrlFetchApp.

This is the Curl request that works. Need to emulate this using urlFetch:

curl -s --user 'api:key-goes-here' \
https://api.mailgun.net/v3/domain.com/messages \
-F from='Support <support@domain.com>' \
-F to=example@domain.com \
-F subject='Hello' \
-F text='Testing some Mailgun awesomness!' \
-F attachment='@image.png' \
-F attachment='@license.txt' \
Community
  • 1
  • 1
Akshay Raje
  • 852
  • 9
  • 20
  • Please add your code showing a successful test send with 1 attachment. – Peter Feb 03 '17 at 04:36
  • @PeterHerrmann I have edited my question with my current code that works only for the first attachment – Akshay Raje Feb 03 '17 at 06:51
  • The curl example is perfect. Please edit your Urlfetch example and replace it with a reproducible hardcoded (simplified) version showing a pass (1 attachment) and fail (2 attachment). – Peter Feb 05 '17 at 23:15
  • I posted a more broad version of this questions here- http://stackoverflow.com/questions/42050972/urlfetchapp-how-to-simulate-multipart-curl-request-that-has-multiple-params-wit unfortunately it's down voted as being duplicate. You may want to refer to the link for more details. – Akshay Raje Feb 06 '17 at 09:31
  • @AkshayRaje did you figure out a solution for this? – Jack Brown Apr 15 '20 at 05:03
  • @JackBrown now that I am re-looking at this, you can use FormData (https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl-params) and pass an array to it (https://stackoverflow.com/questions/16104078/appending-array-to-formdata-and-send-via-ajax/28434829#28434829). Hope this helps! – Akshay Raje Apr 15 '20 at 13:19
  • @akshay_raje thanks for the reply. Unfortunately, I did try them and only one attachment goes through when I pass two keys with the same name and none goes through if I pass an array of file blobs to the key attachment. But if you more suggestions, I am all ears! – Jack Brown Apr 15 '20 at 14:21

1 Answers1

0

I have a similar problem and I and solve it by manually encode the payload object into a string by applying the following function:

function jsonToUrlencoded(obj) {
  var str = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (Array.isArray(obj[key])) {
        for (var i=0;i<obj[key].length;i++) {
          str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key][i]));
        }
      } else {
        str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
      }
    }
  }
  return str.join("&");
}

I used the code for an http request as in the following example:

  var payload={
    user_ID:2,
    action:'editpost',
    originalaction:'editpost',
    post_author:2,
    post_type:'post',
    original_post_status:'auto-draft',
    'post_category[]':[1,4,32]
  };
  options={
    method:'post',
    headers:cookies,
    payload:jsonToUrlencoded(payload),
  };
  var response = UrlFetchApp.fetch(url,options);
  • what the structure of your `obj` ? I am trying to make it work... – Radek Aug 24 '21 at 09:43
  • It is a JSON object. – Fabio Lucchini Aug 24 '21 at 11:24
  • could you paste its structure? I created my own question. Maybe your answer answers this one too. https://stackoverflow.com/q/68905786/250422 – Radek Aug 24 '21 at 11:28
  • one more question. The code you provided is encoding attachments or the whole payload? Could provide all code related? So my question is whether the `obj` is object of payload or object of attachments. Could you give me code how you define attachments? – Radek Aug 27 '21 at 07:12
  • I paste the http request structure in the answer. In my case, I used an object of strings, integers and array of integers, but I never tested it with attachments. – Fabio Lucchini Aug 27 '21 at 15:40