Decoding Gmail API Messages in Javascript

I'm having serious problems decrypting the body of the messages I receive using the Gmail API. I want to capture the contents of a message and put the contents in a div. I use a base64 decoder, which, as I know, will not decode emails encoded differently, but I'm not sure how to check emails to decide which decoder to use - emails that say they are utf encoded -8, base64 successfully decoded, but not be a utf-8 decoder.

I have been studying email decryption for several days, and I found out that I am a bit out of my league here. I used to not do much work with email encoding. Here is the code I use to receive emails:

gapi.client.load('gmail', 'v1', function() { var request = gapi.client.gmail.users.messages.list({ labelIds: ['INBOX'] }); request.execute(function(resp) { document.getElementById('email-announcement').innerHTML = '<i>Hello! I am reading your <b>inbox</b> emails.</i><br><br>------<br>'; var content = document.getElementById("message-list"); if (resp.messages == null) { content.innerHTML = "<b>Your inbox is empty.</b>"; } else { var encodings = 0; content.innerHTML = ""; angular.forEach(resp.messages, function(message) { var email = gapi.client.gmail.users.messages.get({ 'id': message.id }); email.execute(function(stuff) { if (stuff.payload == null) { console.log("Payload null: " + message.id); } var header = ""; var sender = ""; angular.forEach(stuff.payload.headers, function(item) { if (item.name == "Subject") { header = item.value; } if (item.name == "From") { sender = item.value; } }) try { var contents = ""; if (stuff.payload.parts == null) { contents = base64.decode(stuff.payload.body.data); } else { contents = base64.decode(stuff.payload.parts[0].body.data); } content.innerHTML += '<b>Subject: ' + header + '</b><br>'; content.innerHTML += '<b>From: ' + sender + '</b><br>'; content.innerHTML += contents + "<br><br>"; } catch (err) { console.log("Encoding error: " + encodings++); } }) }) } }); }); 

I did some checking and debugging, so console.log and some other things that are only for testing remained. However, you can see here what I'm trying to do.

What is the best way to decode email messages that I extract from the Gmail API? Should I try to put emails in <script> with the charset and type attributes matching the contents of the email encoding? I believe that I remember that charset only works with the src attribute, which I would not have. Any suggestions?

+8
javascript email character-encoding decoding gmail-api
source share
4 answers

For the prototype application I'm writing, the following code works for me:

 var base64 = require('js-base64').Base64; // js-base64 is working fine for me. var bodyData = message.payload.body.data; // Simplified code: you'd need to check for multipart. base64.decode(bodyData.replace(/-/g, '+').replace(/_/g, '/')); // If you're going to use a different library other than js-base64, // you may need to replace some characters before passing it to the decoder. 

Caution: these items are not documented and may be incorrect:

  • users.messages: get API returns the default value for parsed body content. This data is always encoded in UTF-8 and Base64 regardless of the Content-Type and Content-Transfer-Encoding headers.

    For example, in my code there was no problem parsing an email with these headers: Content-Type: text/plain; charset=ISO-2022-JP Content-Type: text/plain; charset=ISO-2022-JP , Content-Transfer-Encoding: 7bit .

  • Base64 encoding mapping table varies between different implementations . The Gmail API uses - and _ as the last two characters of a table, as defined by RFC 4648 "URL and Safe File Alphabet" 1 .

    Check if your Base64 library uses a different mapping table. If so, replace those characters with those that your library accepts before passing the body to the decoder.


1 There is one supporting line in the documentation: the "raw" format returns "body content as a base64url encoded string". (Thanks Eric!)

+14
source share

Use atob to decode messages in JavaScript (see ref ). To access the payload of your message, you can write a function:

 var extractField = function(json, fieldName) { return json.payload.headers.filter(function(header) { return header.name === fieldName; })[0].value; }; var date = extractField(response, "Date"); var subject = extractField(response, "Subject"); 

referring to the previous SO question and

 var part = message.parts.filter(function(part) { return part.mimeType == 'text/html'; }); var html = atob(part.body.data); 

If the above does not decode 100% correctly, @cgenco's comments on this answer below may apply to you. In this case, do

 var html = atob(part.body.data.replace(/-/g, '+').replace(/_/g, '/')); 
+3
source share

Here is the solution: Gmail API - the "Users.messages: get" method has in response message.payload.body.data detailed base64 data separated by a "-" character. This is not all base64 encoded text; these are parts of base64 text. You should try to decode every single part of it or make one mono line by combining and replace the "-" character. After that, you can easily decode it into human text. You can manually check each part here https://www.base64decode.org

+1
source share

Please use a websafe decoder to decode gmail letters and attachments. I got blank pages when I used only base64decoder, should have used this: https://www.npmjs.com/package/urlsafe-base64

0
source share

All Articles