1

I'm building a Chrome extension that works with Gmail API and i need to send emails with local files (using their local file path) as attachments. I saw that with Gmail API, attachments need to be base64 encoded and then you can send them as a POST request. So i tried this:

// Here i convert the file to base64
const fileToBase64 = (filename, filepath) => {
  return new Promise(resolve => {
    var file = new File([filename], filepath);
    var reader = new FileReader();
    // Read file content on file loaded event
    reader.onload = function(event) {
      resolve(event.target.result);
    };

    // Convert data to base64 
    reader.readAsDataURL(file);
  });
};

//Here i trigger the event, get the auth token and create the mail
    $('#test').on('click', function(){
      chrome.identity.getAuthToken({interactive: true}, function(token) {
        console.log(token);
        fileToBase64("pic4.jpg", "C:\Users\Davide\Downloads\pic4.jpg").then(result => {
          console.log(result);

          var splittedResult = result.split('base64,')[1];
          var mail = [
            'Content-Type: multipart/mixed; boundary="foo_bar_baz"\r\n',
            'MIME-Version: 1.0\r\n',
            'From: address1@gmail.com\r\n',
            'To: address2@gmail.com\r\n',
            'Subject: Subject Text\r\n\r\n',

            '--foo_bar_baz\r\n',
            'Content-Type: text/plain; charset="UTF-8"\r\n',
            'MIME-Version: 1.0\r\n',
            'Content-Transfer-Encoding: 7bit\r\n\r\n',

            'The actual message text goes here\r\n\r\n',

            '--foo_bar_baz\r\n',
            'Content-Type: image/jpeg\r\n',
            'MIME-Version: 1.0\r\n',
            'Content-Transfer-Encoding: base64\r\n',
            'Content-Disposition: attachment; filename="pic4.jpg"\r\n\r\n',

            //base64 splitted result of previous function
            splittedResult, '\r\n\r\n',

            '--foo_bar_baz--'
          ].join('');

          // Here i send the mail
          $.ajax({
            type: "POST",
            url: "https://www.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=multipart",
            contentType: "message/rfc822",
            beforeSend: function(xhr, settings) {
              xhr.setRequestHeader('Authorization','Bearer '+ token );
            },
            data: mail
          }); 

        });

Result: i receive a mail at the destination address ( i receive also a copy to the source address, idk why) but the mail contains an empty attachment with the filename i've chosen (pic4.jpg) (cannot open it).

Here's an image

It seems the error to be in the base64 encoding from the absolute path, is there a way to fix or another way to do this?

Davidebug
  • 53
  • 7
  • https://stackoverflow.com/questions/31784167/gmail-api-for-sending-email-with-attachment – Diodeus - James MacFarlane Jul 16 '19 at 20:39
  • @Diodeus-JamesMacFarlane Tried to split the base64 url but it's not working, same result.. – Davidebug Jul 17 '19 at 13:34
  • This is the information provided in the FileReader documentation: The blob's result cannot be directly decoded as Base64 without first removing the Data-URL declaration preceding the Base64-encoded data. To retrieve only the Base64 encoded string, first remove data:*/*;base64, from the result. https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL – ziganotschka Jul 17 '19 at 15:20
  • @ziganotschka Already tried, splitted the string from "base64, " and nothing changed.. Tried also to add a relative path to the image but it's not working. – Davidebug Jul 17 '19 at 15:33
  • The main difference I see between your code and the answer Diodeus mentioned in his comment is that you use the method readAsDataURL(). Don't know if you can locate your file in such a way that you can use the method toDataURL() instead - as in the other case, to see if it works. – ziganotschka Jul 17 '19 at 15:43
  • @ziganotschka i'm pretty sure the error is not there: toDataURL() is a specific Canvas function and works only with images; readAsDataURL() works with every file you place in. I Think the error is in the File constructor, i don't know if i can enter the absolute path this way i do. – Davidebug Jul 17 '19 at 16:21
  • Yes, this is what I was thinking - maybe if you upload the file somewhere (for a test) and try to retrieve it by URL- you can see if this is what causes you the error. – ziganotschka Jul 17 '19 at 16:39
  • 1
    @ziganotschka Yup, the error is there: i've made an Input file form with HTML and everything works. I should now find a way to create the File from a local path without using the input form (probably not possible for security reasons) or another way to upload the entire attachment. – Davidebug Jul 17 '19 at 16:49

1 Answers1

0

You can open a file from a local path with XMLHttpRequest().open() in order to pass it to reader.readAsDataURL().

See this example.

ziganotschka
  • 25,866
  • 2
  • 16
  • 33