Gmail API decoding messages in Javascript

后端 未结 7 957
暖寄归人
暖寄归人 2020-12-30 11:07

I am having serious problems decoding the message body of the emails I get using the Gmail API. I want to grab the message content and put the content in a div. I am using a

相关标签:
7条回答
  • 2020-12-30 11:32

    Use atob to decode the messages in JavaScript (see ref). For accessing your message payload, 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");
    

    referenced from my 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% properly, the comments by @cgenco on this answer below may apply to you. In that case, do

    var html = atob(part.body.data.replace(/-/g, '+').replace(/_/g, '/'));
    
    0 讨论(0)
  • 2020-12-30 11:33

    Thank @ento 's answer. I explain more why you need to replace '-' and '_' character to '+' and '/' before decode.

    Wiki Base64 Variants summary table shows:

    • RFC 4648 section 4: base64 (standard): use '+' and '/'
    • RFC 4648 section 5: base64url (URL-safe and filename-safe standard): use '-' and '_'

    In short, Gmail API use base64url (urlsafe) format('-' and '_'), But JavaScript atob function or other JavaScript libraries use base64 (standard) format('+' and '/').

    For Gmail API, the document says body use base64url format, see below links:

    • string/bytes type
    • MessagePartBody
    • RAW

    For Web atob/btoa standards, see below links:

    • The algorithm used by atob() and btoa() is specified in RFC 4648, section 4
    • 8.3 Base64 utility methods
    • Forgiving base64
    0 讨论(0)
  • 2020-12-30 11:34

    For a prototype app I'm writing, the following code is working 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 points are not explicitly documented and could be wrong:

    1. The users.messages: get API returns "parsed body content" by default. This data seems to be always encoded in UTF-8 and Base64, regardless of the Content-Type and Content-Transfer-Encoding header.

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

    2. The mapping table of the Base64 encoding varies among various implementations. Gmail API uses - and _ as the last two characters of the table, as defined by RFC 4648's "URL and Filename safe Alphabet"1.

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


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

    0 讨论(0)
  • 2020-12-30 11:35

    I can easily decode using another tool at https://simplycalc.com/base64-decode.php

    In JS: https://www.npmjs.com/package/base64url

    In Python 3:

    import base64
    base64.urlsafe_b64decode(coded_string)
    
    0 讨论(0)
  • 2020-12-30 11:40

    I was also annoyed by this point. I discovered a solution through looking at an extension for VSCode. The solution is really simple:

    const body = response.data.payload.body; // the base64 encoded body of a message
     body = Buffer.alloc(
            body.data.length,
            body.data,
            "base64"
          ).toString();  // the decoded message
    

    It worked for me as I was using gmail.users.messages.get() call of Gmail API.

    0 讨论(0)
  • 2020-12-30 11:42

    Here is the solution: Gmail API - "Users.messages: get" method has in response message.payload.body.data parted base64 data, it's separated by "-" symbol. It's not entire base64 encoded text, it's parts of base64 text. You have to try to decode every single part of this or make one mono string by unite and replace "-" symbol. After this you can easily decode it to human text. You can manually check every part here https://www.base64decode.org

    0 讨论(0)
提交回复
热议问题