NodeMailer Tutorial: Send Emails in Node.js

OpenJavaScript 0

Last updated: January 25, 2023.

You can send emails in Node.js with the help of the NodeMailer package.

Table of contents

Installation

Since NodeMailer isn’t a core module, you’ll first need to install it first.

To do this via npm after creating a new Node project with default settings (Windows PowerShell example):

cd C:\root\to\your\project-folder
npm init --y
npm i nodemailer 

Basic example

Now, you can send an email to someone in the code format below.

The example is based upon the sending of an email from a fictional gmail account.

If you want to test this example using your own gmail account, note you need to generate an ‘app password’ for your Google account (see security settings).

const nodemailer = require("nodemailer");
// Import NodeMailer (after npm install)

async function main() {
// Async function enables allows handling of promises with await

  // First, define send settings by creating a new transporter: 
  let transporter = nodemailer.createTransport({
    host: "smtp.gmail.com", // SMTP server address (usually mail.your-domain.com)
    port: 465, // Port for SMTP (usually 465)
    secure: true, // Usually true if connecting to port 465
    auth: {
      user: "***-example-person@gmail.com", // Your email address
      pass: "your-password", // Password (for gmail, your app password)
      // ⚠️ For better security, use environment variables set on the server for these values when deploying
    },
  });
  
  // Define and send message inside transporter.sendEmail() and await info about send from promise:
  let info = await transporter.sendMail({
    from: '"You" <***-example-person@gmail.com>',
    to: "****.bram@****.com",
    subject: "Testing, testing, 123",
    html: `
    <h1>Hello there</h1>
    <p>Isn't NodeMailer useful?</p>
    `,
  });

  console.log(info.messageId); // Random ID generated after successful send (optional)
}

main()
.catch(err => console.log(err));

To multiple recipients

To send an email to multiple email addresses, define these in an array and set this as the value of to inside the sendMail({ }) object.

On info, it now makes sense to log both info.accepted and info.rejected, which return an array of recipients for which the email was sent successfully and unsuccessfully, respectively.

const nodemailer = require("nodemailer");

const maillist = [
  '****.bram@****.com',
  '****.shah@****.com',
  '****.styles@****.com',
];
// Defines recipients

async function main() {

  let transporter = nodemailer.createTransport({
    host: "smtp.gmail.com",
    port: 465,
    secure: true,
    auth: {
      user: "***-example-person@gmail.com",
      pass: "your-password",
      // ⚠️ Use environment variables set on the server for these values when deploying
    },
  });

  let info = await transporter.sendMail({
    from: '"You" <***-example-person@gmail.com>',
    to: maillist, // Mails to array of recipients
    subject: "Testing, testing, 123",
    html: `
    <h1>Hello there</h1>
    <p>Isn't NodeMailer useful?</p>
    `,
  });

  console.log(info.messageId);
  console.log(info.accepted); // Array of emails that were successful
  console.log(info.rejected); // Array of unsuccessful emails
}

main()
.catch(err => console.log(err));

Note that the catch() method after calling the main function only runs if the mail was not successfully sent to any recipients.

Attachments and images

To add an attachment, add an attachments property when constructing the mail that includes a filename and path.

If you want to embed an image in the body of the email, use a cid (content ID) with a unique email-like value. This URL exists in the email itself only.

const nodemailer = require("nodemailer");

async function main() {

  let transporter = nodemailer.createTransport({
    host: "smtp.gmail.com",
    port: 465,
    secure: true,
    auth: {
      user: "***-example-person@gmail.com",
      pass: "your-password",
      // ⚠️ Use environment variables set on the server for these values when deploying
    },
  });

  let info = await transporter.sendMail({
    from: '"You" <***-example-person@gmail.com>',
    to: "****.bram@****.com",
    subject: "Image test",
    html: `
    <h1>Hello world</h1>
    <p>Here's an image for you</p>
    <img src="cid:unique@gmail.com>"/>'
    `, // Embedded image links to content ID
    attachments: [{
      filename: 'image.png',
      path: './img1.jpg',
      cid: 'unique@gmail.com' // Sets content ID
    }]
  });

  console.log(info.messageId);
}

main()
.catch(err => console.log(err));

Troubleshooting

If you are testing on your local machine, your antivirus software may be intercepting your attempt to contact the mail server.

To prevent this without disabling your antivirus, try adding the following property to in the transport configuration object:

tls: {
    rejectUnauthorized: false,
  },

It is not a good idea to use this in production, however, as your mail request could be intercepted by a malicious actor.

Related links