Where to find body of email depending of mimeType

Solution 1:

I think it will make sense if you think of the payload as a part in of itself. Let's say I send a message with just a subject and a plain message text:

From: [email protected]
To: [email protected]
Subject: Example Subject

This is the plain text message

This will result in the following parsed message:

{
 "id": "154ecb53c10b74d8",
 "threadId": "154ecb53c10b74d8",
 "labelIds": [
  "INBOX",
  "SENT"
 ],
 "snippet": "This is the plain text message",
 "historyId": "38877",
 "internalDate": "1464260181000",
 "payload": {
  "partId": "",
  "mimeType": "text/plain",
  "filename": "",
  "headers": [
   ...
  ],
  "body": {
   "size": 31,
   "data": "VGhpcyBpcyB0aGUgcGxhaW4gdGV4dCBtZXNzYWdlCg=="
  }
 },
 "sizeEstimate": 355
}

If I send a message with a plain text part, a html part and an image, it will look like this when parsed:

{
 "id": "154ed5ccaa12f3df",
 "threadId": "154ed5ccaa12f3df",
 "labelIds": [
  "SENT",
  "INBOX",
  "IMPORTANT"
 ],
 "snippet": "This is a plain/html message with an image.",
 "historyId": "841379",
 "internalDate": "1464271162000",
 "payload": {
  "mimeType": "multipart/mixed",
  "filename": "",
  "headers": [
     ...
  ],
  "body": {
   "size": 0
  },
  "parts": [
   {
    "mimeType": "multipart/alternative",
    "filename": "",
    "headers": [
     {
      "name": "Content-Type",
      "value": "multipart/alternative; boundary=089e0122896c7c80d80533bf3205"
     }
    ],
    "body": {
     "size": 0
    },
    "parts": [
     {
      "partId": "0.0",
      "mimeType": "text/plain",
      "filename": "",
      "headers": [
       {
        "name": "Content-Type",
        "value": "text/plain; charset=UTF-8"
       }
      ],
      "body": {
       "size": 47,
       "data": "VGhpcyBpcyBhIHBsYWluL2h0bWwgKm1lc3NhZ2UqIHdpdGggYW4gaW1hZ2UuDQo="
      }
     },
     {
      "partId": "0.1",
      "mimeType": "text/html",
      "filename": "",
      "headers": [
       {
        "name": "Content-Type",
        "value": "text/html; charset=UTF-8"
       }
      ],
      "body": {
       "size": 73,
       "data": "PGRpdiBkaXI9Imx0ciI-VGhpcyBpcyBhIHBsYWluL2h0bWwgPGI-bWVzc2FnZTwvYj4gd2l0aCBhbiBpbWFnZS48L2Rpdj4NCg=="
      }
     }
    ]
   },
   {
    "partId": "1",
    "mimeType": "image/png",
    "filename": "smile.png",
    "headers": [
       ...
    ],
    "body": {
     "attachmentId": "ANGjdJ-OrSy7VAYL-UbRyNtmySbZLlV-fV43zJF0_neNGZ8yKugsZAxb32eSb-CrbYIhF9NvjGwBVEjSkRrUWoCS7aDpgoQnt9WR7f2sa17qVEyOg_JVSbrGrunirvQw2dY-SxxB3Y0JP3aYDHSBXpNO6fFCByVFWQDw1et5Mh9di7bGO4AWOLKFVe_Yb2RmdDwuazGXGb8zA88TTMaiEPIacPTNiVtBrIWG0EKGxHBhep9j8ujyWeCS5P9X80dBHvBNj4T9XjUwcrN6FvwegRewRMM9cBupY7jQESR7915OcbhCNyi5l64x6vVh1ZU",
     "size": 2002
    }
   }
  ]
 },
 "sizeEstimate": 3077
}

You will see it's just the RFC822-message parsed to JSON. If you just traverse the parts, and treat the payload as a part itself, you will find what you are looking for.

var parts = [response.payload];

while (parts.length) {
  var part = parts.shift();
  if (part.parts) {
    parts = parts.concat(part.parts);
  }

  if(part.mimeType === 'text/html') {
    var decodedPart = decodeURIComponent(escape(atob(part.body.data.replace(/\-/g, '+').replace(/\_/g, '/'))));
    console.log(decodedPart);
  }
}

Solution 2:

There are many MIME types that can be returned, here are a few:

  • text/plain: the message body only in plain text
  • text/html: the message body only in HTML
  • multipart/alternative: will contain two parts that are alternatives for each othe, for example:
    • a text/plain part for the message body in plain text
    • a text/html part for the message body in html
  • multipart/mixed: will contain many unrelated parts which can be:
    • multipart/alternative as above, or text/plain or text/html as above
    • application/octet-stream, or other application/* for application specific mime types for attachments
    • image/png ot other image/* for images, which could be embedded in the message.

The definitive reference for all this is RFC 2046 https://www.ietf.org/rfc/rfc2046.txt (you might want to also see 2044 and 2045)

To answer your question, build a tree of the message, and look either for:

  • the first text/plain or text/html part (either in the message body or in a multipart/mixed)
  • the first text/plain or text/html inside of a multipart/alternative, which may be part of a multipart mixed.

An example of a complex message:

  • multipart/mixed

    • multipart/alternative
      • text/plain <- message body in plain text
      • text/html <- message body in HTML
    • application/zip <- a zip file attachment
  • -