Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send mail with attachment (PDF) using Gmail API

Problem

All the data is sent in text format rather than as PDF as an attachment.

My Code

var boundary = "__myapp__", nl = "\n";
// var attach = data.toString("base64");
var fileName = "abc.pdf";
var attach = new Buffer(fs.readFileSync("./" + fileName)).toString("base64");

var str = ["Content-Type: text/plain; charset=\"UTF-8\"\n",
    "MIME-Version: 1.0\n",
    "Content-Transfer-Encoding: 7bit\n",
    "to: ", to, "\n",
    "subject: ", subject, "\n\n",
    "Content-Type: multipart/alternate; boundary=" + boundary + nl,
    "--" + boundary,
    "Content-Type: text/plain; charset=UTF-8",
    "Content-Transfer-Encoding: 7bit" + nl,
    message + nl,
    "--" + boundary,
    "--" + boundary,
    "Content-Type: Application/pdf; name=myPdf.pdf",
    'Content-Disposition: attachment; filename=myPdf.pdf',
    "Content-Transfer-Encoding: base64" + nl,
    attach,
    "--" + boundary + "--"
].join('');

var encodedMail = new Buffer(str).toString("base64")
    .replace(/\+/g, '-')
    .replace(/\//g, '_');

resolve(encodedMail);


A part of mail is as below

Content-Type: multipart/alternate; boundary=myapp --_myapp_Content-Type: text/plain; charset=UTF-8Content-Transfer-Encoding: 7bit test message --myapp--_myapp_Content-Type: Application/pdf; name=myPdf.pdfContent-Disposition: attachment; filename=myPdf.pdfContent-Transfer-Encoding: base64 JVBERi0xLjMgCiXi48/TIAoxIDAgb2JqIAo8PCAKL1R5cGUgL0NhdGFsb2cgCi9QYWdlcyAyIDAgUiAKL1BhZ2VNb2RlIC9Vc2VOb25lIAovVmlld2VyUHJlZmVyZW5jZXMgPDwgCi9GaXRXaW5kb3cgdHJ1ZSAKL1BhZ2VMYXlvdXQgL1NpbmdsZVBhZ2UgCi9Ob25GdWxsU2NyZWVuUGFnZU1vZGUgL1VzZU5vbmUgCj4+IAo+PiAKZW5kb2JqIAo1IDAgb2JqIAo8PCAKL0xlbmd0aCAyNjQzIAovRmlsdGVyIFsgL0ZsYXRlRGVjb2RlIF0gCj4+IApzdHJlYW0KeJzdGWtT48jxu3+FMYMkY8uep2bGkgADBrwseHntLYv3kspe9iqpbFK5fMjfT89LkuUH3H5J1UEVNZru6e7pdw94hEUXw2+K3UpxMpLdr9872G7/9qtf3F92JMVdynGXYJ7xLsmY4N3f/tr5qfPPDu2+A7z/WhSSZRUO1YQYnIcOHilFu82///lq0RlhxKMLjA3yX+x+pqp91tyXZPO+wiLsU9HYJzzDFQPpAUIL6gT97tZWin+AnFKxzH199+ssQIywTBkAIURx92EgVBEWQG4dznCc...more texts...at last...==--myapp--


What I think is that there might be some issue with the template of sending the mail with attachment.

Can anyone provide help here?
Thanks

like image 875
ANURAG GUPTA Avatar asked Mar 11 '26 11:03

ANURAG GUPTA


1 Answers

I was able to attach a PDF file by using a proper message structure. It's really important to set the correct mimeTypes and the boundaries.

This reference (https://stackoverflow.com/a/50540373/13664358) pointed out by @Tanaike helped a lot!

Here is the whole function to send an email with a PDF attachment:

const subject = 'My Subject';
const utf8Subject = `=?utf-8?B?${Buffer.from(subject).toString('base64')}?=`;

var fileName = "mypdf.pdf";
var attach = new Buffer.from(fs.readFileSync("./" + fileName)).toString("base64");

var emailBody = 'My Email Message';

var messageParts = [
    "MIME-Version: 1.0",
    'From: Teste <[email protected]>',
    'To: Teste <[email protected]>',
    `Subject: ${utf8Subject}`,
    "Content-Type: multipart/mixed; boundary=012boundary01",
    '',
    "--012boundary01",
    "Content-Type: multipart/alternative; boundary=012boundary02",
    '',
    "--012boundary02",
    "Content-type: text/html; charset=UTF-8", 
    "Content-Transfer-Encoding: quoted-printable",
    '',
    emailBody,
    '',
    "--012boundary02--",
    "--012boundary01",
    "Content-Type: Application/pdf; name=mypdf.pdf",
    'Content-Disposition: attachment; filename=mypdf.pdf',
    "Content-Transfer-Encoding: base64",
    '',
    attach,
    "--012boundary01--",
]

const message = messageParts.join('\n');

// The body needs to be base64url encoded.
const encodedMessage = Buffer.from(message)
  .toString('base64')
  .replace(/\+/g, '-')
  .replace(/\//g, '_')
  .replace(/=+$/, '');

const gmail = google.gmail({version: 'v1', auth});
gmail.users.messages.send({
  userId: 'me',
  requestBody: {
      raw: encodedMessage
  }
}, (err, res) => {
  if (err) return console.log('The API returned an error: ' + err);
});

Note: The code above uses google apis for nodejs (https://www.npmjs.com/package/googleapis)

For multiples PDFs, we can add them between --012boundary02-- and --012boundary01-- as follows:

"--012boundary02",
"Content-type: text/html; charset=UTF-8", 
"Content-Transfer-Encoding: quoted-printable",
'',
emailBody,
'',
"--012boundary02--",
"--012boundary01",
"Content-Type: Application/pdf; name=mypdf.pdf",
'Content-Disposition: attachment; filename=mypdf.pdf',
"Content-Transfer-Encoding: base64",
'',
attach,
"--012boundary01",
"Content-Type: Application/pdf; name=mypdf2.pdf",
'Content-Disposition: attachment; filename=mypdf2.pdf',
"Content-Transfer-Encoding: base64",
'',
attach2,
"--012boundary01",
"Content-Type: Application/pdf; name=mypdf3.pdf",
'Content-Disposition: attachment; filename=mypdf3.pdf',
"Content-Transfer-Encoding: base64",
'',
attach3,
"--012boundary01--",
like image 177
Esdras Vitor Avatar answered Mar 13 '26 03:03

Esdras Vitor