Search code examples
node.jsgoogle-apigmail-apigoogle-api-nodejs-clientgoogle-apis-explorer

gmail with multiple attachments not working


When mail is sent with multiple attachments using gmail api, mail is not going properly. Attachments are not going in mail, instead some code is going in mail. I am using node js and request-promise module for achieving this.

I have tried sending attachments by setting boundaries on attachments. Here is the piece of code that I have written.

let user = await db.model('User').findOne({ _id: userId });
    let from = user.crmOptions.email;
    let mailString = '';
    for (let i in req.files) {
      mailString += '--boundary_mail1\n' + ','
      mailString += `Content-Type: ${req.files[i].mimetype}\n` + ','
      mailString += `Content-Disposition: attachment; filename="${req.files[i].filename}"\n` + ','
      mailString += "Content-Transfer-Encoding: base64\n\n" + ','
      mailString += `${fs.readFileSync(req.files[i].path).toString('base64')}` + ',' + '\n'
      if (i !== req.files.length - 1)
      mailString += ','
    }    
    let raw = [
      'MIME-Version: 1.0\n',
      "to: ", req.body.to, "\n",
      "from: ", from, "\n",
      "cc: ", req.body.cc ? req.body.cc : '', "\n",
      "bcc: ", req.body.bcc ? req.body.bcc : '', "\n",
      "subject: ", req.body.subject ? req.body.subject : '', "\n",
      "Content-Type: multipart/mixed; boundary=boundary_mail1\n\n",

      "--boundary_mail1\n",
      "Content-Type: multipart/alternative; boundary=boundary_mail2\n\n",

      "--boundary_mail2\n",
      "Content-Type: text/html; charset=UTF-8\n",
      "Content-Transfer-Encoding: quoted-printable\n\n",
      req.body.message = req.body.message ? req.body.message : '', "\n\n",
      "--boundary_mail2--\n",
      mailString,
      '--boundary_mail1--',
    ].join('');
    const id = 'me';
    let options = {
      url: "https://www.googleapis.com/upload/gmail/v1/users/" + id + "/messages/send?uploadType=multipart",
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${user.crmOptions.access_token}`,
        'Content-Type': 'message/rfc822'
      },
      body: raw
    };

await request(options).then(async body => {
  console.log("Body: ", body);
}).catch(err => {
  console.log("Error: ", err);
})

I want email to be delivered with multiple attachments. But I am not able to send mail with single attachment also. Could anyone help me resolve the issue.


Solution

  • I found out issue guys. Just removed unwanted commas and its working. here is the modified code.

    let user = await db.model('User').findOne({ _id: userId });
        let from = user.crmOptions.email;
        let mailString = '';
        for (let i in req.files) {
          mailString += '--boundary_mail1\n'
          mailString += `Content-Type: ${req.files[i].mimetype}\n`
          mailString += `Content-Disposition: attachment; filename="${req.files[i].filename}"\n`
          mailString += "Content-Transfer-Encoding: base64\n\n"
          mailString += `${fs.readFileSync(req.files[i].path).toString('base64')}` + '\n'
        }
        let raw = [
          'MIME-Version: 1.0\n',
          "to: ", req.body.to, "\n",
          "from: ", from, "\n",
          "cc: ", req.body.cc ? req.body.cc : '', "\n",
          "bcc: ", req.body.bcc ? req.body.bcc : '', "\n",
          "subject: ", req.body.subject ? req.body.subject : '', "\n",
          "Content-Type: multipart/mixed; boundary=boundary_mail1\n\n",
    
          "--boundary_mail1\n",
          "Content-Type: multipart/alternative; boundary=boundary_mail2\n\n",
    
          "--boundary_mail2\n",
          "Content-Type: text/html; charset=UTF-8\n",
          "Content-Transfer-Encoding: quoted-printable\n\n",
          req.body.message = req.body.message ? req.body.message : '', "\n\n",
          "--boundary_mail2--\n",
          mailString,
          '--boundary_mail1--',
        ].join('');
        const id = 'me';
        let options = {
          url: "https://www.googleapis.com/upload/gmail/v1/users/" + id + "/messages/send?uploadType=multipart",
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${user.crmOptions.access_token}`,
            'Content-Type': 'message/rfc822'
          },
          body: raw
        };
    await request(options).then(async body => {
      console.log("Body: ", body);
    }).catch(err => {
      console.log("Error: ", err);
    })