Search code examples
javascriptnode.jstypescriptnodemailer

Nodemailer attachments are empty


I'm trying to attach some files to the email I'm sending via NodeMailer. Checking the sent email, the attached files are empty (i.e. 0 bytes). If I download the attachments, I end up with empty text files. What am I missing?

Here is my code:

 const nodemailer = require('nodemailer')

 const lessSecureAuth = {
  user: "sender@email.com",
  pass: "password123"
 }
 const transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: lessSecureAuth
 });

 const mailOptions = {
      from: 'sender@email.com',
      to: 'recipient@email.com',
      subject: 'Email Subject',
      html: `
          <h3>Hello World!</h3>
          <p>
              the quick brown fox jumps over the lazy dog
          </p>
      `,
      attachments: [
        {
          filename: 'attachFileTest.docx',
          filePath: '../uploads/attachFileTest.docx',
          contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        },
        {
          filename: 'attachFileTest.pdf',
          filePath: '../uploads/attachFileTest.pdf',
          contentType: 'application/pdf'
        },
        {
          filename: 'attachImageTest.png',
          filePath: '../uploads/attachImageTest.png',
          contentType: 'image/png'
        }
      ]
  };

  transporter.sendMail(mailOptions, function(error, info){
    if (error) {
      console.log("[ ERR ]", error);
    } else {
      console.log('Email sent: ' + info.response);
    }
  });

NodeJS: v12.16.1

nodemailer: v6.6.0

Edit#1

As suggested by @Apoorva Chikara enter image description here


Solution

  • After doing some digging in the docs and other stackoverflow posts, I found the answer:

    Using the absolute path instead of a relative path to the file to be attached, along with using the attachment.path property instead of the attachment.filePath property did the trick.

    Basically, changing this:

     {
       filename: 'attachFileTest.pdf',
       filePath: '../uploads/attachFileTest.pdf',
       contentType: 'application/pdf'
     },
    

    to this:

     {
      path: __dirname + '/../uploads/attachFileTest.pdf' // string concatination
      // path: `${__dirname}/../uploads/attachFileTest.pdf` // or string interpolation (ES6)
     }
    

    Both attachment.filename and attachment.contentType are unnecessary in this case, since according to the docs:

    { // filename and content type is derived from path
      path: '/path/to/file.txt'
    }