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: [email protected]\r\n',
            'To: [email protected]\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?

8
  • stackoverflow.com/questions/31784167/… Commented Jul 16, 2019 at 20:39
  • @Diodeus-JamesMacFarlane Tried to split the base64 url but it's not working, same result.. Commented Jul 17, 2019 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. developer.mozilla.org/en-US/docs/Web/API/FileReader/… Commented Jul 17, 2019 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. Commented Jul 17, 2019 at 15:33
  • 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. Commented Jul 17, 2019 at 16:49

1 Answer 1

0

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

See this example.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.