Google Apps Script doPost image object empty

53 views Asked by At

I have a deployed Web App on a generic Google account I wish to work as a mail server for automation projects. It works well but I can't get inlineImages objects to carry over the POST request. The image object always comes through empty. Can someone explain what's up and whether there's a way to carry images over a POST request to include (inline) in emails for use with a GAS Web App like this one?

Server code (simplified):

function doPost(e) {
  const data = JSON.parse(e.postData.contents);
  const { apikey, recipient, subject, body, images } = data;

  console.log(images) // Always outputs {'img_map: {}}

  MailApp.sendEmail(recipient, subject, "", {name: "TSL mail server", htmlBody: body, inlineImages: images});
  return ContentService.createTextOutput('Email sent successfully.');
}

Client code:

// DriveApp.getFiles()
function myPost() {
  const map = DriveApp.getFileById(MYFILE_ID).getAs('image/png');
  const postData = {
    'apikey': APIKEY,
    'recipient': '[email protected]',
    'subject': 'Testing GAS mail server',
    'body': '<h1>Hello, Mail World!</h1><img src="cid:img_map"/>',
    'images': {'img_map': map}
  };
  var options = {
    'method' : 'POST',
    'payload' : JSON.stringify(postData),
    'headers': { Authorization: `Bearer ${ScriptApp.getOAuthToken()}` },
    'muteHttpExceptions': true
  };
  const response = UrlFetchApp.fetch(MAIL_ENDPOINT, options);
  console.log(response.getResponseCode());
  console.log(response.getContentText());
}
1

There are 1 answers

1
Tanaike On BEST ANSWER

I believe your goal is as follows.

  • You want to request from the function myPost to doPost. The value of MAIL_ENDPOINT is the Web Apps URL of doPost.
  • You have already been able to request to doPost using your myPost while the value of images is not correctly sent.

In this case, how about the following modification? In this modification, the image file is sent as base64 data. The modified script is as follows.

doPost

function doPost(e) {
  const data = JSON.parse(e.postData.contents);
  let { apikey, recipient, subject, body, images } = data;
  images = { img_map: Utilities.newBlob(Utilities.base64Decode(images.img_map), 'image/png') };

  console.log(images) // Always outputs {'img_map: {}}

  MailApp.sendEmail(recipient, subject, "", { name: "TSL mail server", htmlBody: body, inlineImages: images });
  return ContentService.createTextOutput('Email sent successfully.');
}

myPost

function myPost() {
  const map = Utilities.base64Encode(DriveApp.getFileById(MYFILE_ID).getAs('image/png').getBytes());
  const postData = {
    'apikey': APIKEY,
    'recipient': '[email protected]',
    'subject': 'Testing GAS mail server',
    'body': '<h1>Hello, Mail World!</h1><img src="cid:img_map"/>',
    'images': { 'img_map': map }
  };
  var options = {
    'method': 'POST',
    'payload': JSON.stringify(postData),
    'headers': { Authorization: `Bearer ${ScriptApp.getOAuthToken()}` },
    'muteHttpExceptions': true
  };
  const response = UrlFetchApp.fetch(MAIL_ENDPOINT, options);
  console.log(response.getResponseCode());
  console.log(response.getContentText());
}
  • When this modified script is used and myPost is run, the values of postData are sent to doPost. And, at doPost, the image file is decoded from base64 data and used with inlineImages.

Note:

  • In this modification, it supposes that the variables of MYFILE_ID, APIKEY, and MAIL_ENDPOINT have already been declared elsewhere and those values are valid values. Please be careful about this.

  • When you modify the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.

  • You can see the details of this in my report "Redeploying Web Apps without Changing URL of Web Apps for new IDE (Author: me)".

References: