How to pass inline images from Class GmailMessage's getAttachments to Class MailApp's sendEmail?

226 views Asked by At

I'd like to pull inline images using GmailMessage's getAttachments and then send them via Class MailApp's sendEmail.

The problem is the former returns an array of Blob attachments, while the latter expects a JavaScript object containing a mapping from image key (String) to image data Blob.

Sample code - the tricky part is {..., inlineImages: attachments, ...}:

function test() {
  var firstThread = GmailApp.getTrashThreads(0,1)[0];
  var message = firstThread.getMessages()[0];
  var from = message.getHeader('From');
  var attachments = message.getAttachments({includeAttachments: false});
  var obj = {htmlBody: message.getBody(), inlineImages: attachments, noReply: false, replyTo: message.getFrom(), name: from};
  MailApp.sendEmail("[email protected]", 'Testing', '', obj);
}

Sample EML message (note the text/html usage of <img src="cid:key"):

MIME-Version: 1.0
Date: Thu, 22 Jul 2021 23:06:23 +0300
Message-ID: <[email protected]>
Subject: Testing
From: Me <[email protected]>
To: Someone <[email protected]>
Content-Type: multipart/related; boundary="0000000000004aee5205c7bbd26b"

--0000000000004aee5205c7bbd26b
Content-Type: multipart/alternative; boundary="0000000000004aee5005c7bbd26a"

--0000000000004aee5005c7bbd26a
Content-Type: text/plain; charset="UTF-8"

This is an inline image:
[image: image.png]
And here's another:
[image: image.png]
Thanks!

--0000000000004aee5005c7bbd26a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">This is an inline=C2=A0image:<div><div dir=3D"ltr" class=
=3D"gmail_signature" data-smartmail=3D"gmail_signature"><div dir=3D"ltr"></=
div></div></div><div><img src=3D"cid:ii_krfchaks0" alt=3D"image.png" width=
=3D"117" height=3D"118"><br></div><div>And here&#39;s another:</div><div><i=
mg src=3D"cid:ii_krfchlll1" alt=3D"image.png" width=3D"41" height=3D"47"><b=
r></div><div>Thanks!</div></div>

--0000000000004aee5005c7bbd26a--
--0000000000004aee5205c7bbd26b
Content-Type: image/png; name="image.png"
Content-Disposition: attachment; filename="image.png"
Content-Transfer-Encoding: base64
X-Attachment-Id: ii_krfchaks0
Content-ID: <ii_krfchaks0>


--0000000000004aee5205c7bbd26b
Content-Type: image/png; name="image.png"
Content-Disposition: attachment; filename="image.png"
Content-Transfer-Encoding: base64
X-Attachment-Id: ii_krfchlll1
Content-ID: <ii_krfchlll1>


--0000000000004aee5205c7bbd26b--
2

There are 2 answers

1
LWC On BEST ANSWER

Turns out Google Apps Script supports matchAll, which means it can be pulled off like this:

function test() {
  var firstThread = GmailApp.getTrashThreads(0,1)[0];
  var message = firstThread.getMessages()[0];
  var from = message.getHeader('From');
  var attachments = message.getAttachments({includeAttachments: false}), inline_images = {};
  var regex = new RegExp('<img src="cid:(.*?)"', 'ig');
  var i=-1, matches = message.getBody().matchAll(regex)
  for (const match of matches) {
        i++;
        inline_images[match[1]] = attachments[i].copyBlob();
  }
  var obj = {htmlBody: message.getBody(), inlineImages: attachments, noReply: false, replyTo: message.getFrom(), name: from};
  MailApp.sendEmail("[email protected]", 'Testing', '', obj);
}
3
NightEye On

As per Cooper's comment, you need to iterate through the array. Then generate a string that contains the tags with unique keys. See code below.

Code:

function test() {
  var firstThread = GmailApp.getTrashThreads(0,1)[0];
  var message = firstThread.getMessages()[0];
  var from = message.getHeader('From');
  var attachments = message.getAttachments();
  // contains key - blob pair
  var images = {};
  // contains the string built up containing usage of inlineImages
  var imageString = ''; 
  // used for assigning unique name per attachment
  var index = 1; 

  for (attachment of attachments) {
    // create unique name per attachment
    var key = 'image' + index;
    // assign blob of each attachment to the unique key
    images[key] = attachment.copyBlob();
    // generate string containing the inline image tag
    imageString += key + " attachment <img src='cid:" + key + "'><br>";   
    index++;
  }

  MailApp.sendEmail({
    to: "[email protected]",
    subject: "Testing",
    // appended the string generated to the original body
    htmlBody: message.getBody() + imageString,
    // images obj assigned to inlineImages
    inlineImages: images,
    noReply: false, 
    replyTo: message.getFrom(), 
    name: from
  });
}

Trashed message:

trash

Sent mail:

sent

Reference: