How to send an email using nodemailer
By Flavio Copes
Learn how to send an email from Node.js using nodemailer, from creating an SMTP transporter to defining the message options and sending your first email.
To send an email from Node.js with nodemailer, you create a transporter pointing at an SMTP server, define the message, and call sendMail().
Nodemailer is the standard library for this job. Node has no built-in way to send email, and talking SMTP by hand is not something you want to do. Nodemailer handles the protocol, the authentication, and the message encoding for you.
You need SMTP credentials from an email provider. Services like Amazon SES, Postmark or Resend give you a host, a username and a password when you sign up.
First install it:
npm install nodemailer
Then import it in your Node script or app:
import nodemailer from 'nodemailer'
Create the transporter
Initialize a transporter object that we’ll use later to send the email. It holds the connection settings for your SMTP server:
const transporter = nodemailer.createTransport({
host: 'smtp.yoursmtpserver.com',
port: 465,
secure: true,
auth: {
user: 'smtp_user',
pass: 'smtp_pass',
},
})
⚠️ NOTE: you need to fill those values with real SMTP server credentials
A note on ports: secure: true is for port 465, which uses TLS from the start. If your provider gives you port 587, set secure: false. Nodemailer will then upgrade the connection with STARTTLS. Mixing these up is the most common reason the connection fails or hangs.
Define and send the message
Now create an options object with the details of the email you want to send:
const options = {
from: '[email protected]',
to: '[email protected]',
subject: 'Hi!',
html: '<p>Hello</p>',
}
You can use text instead of html for a plain text body, or include both.
Finally call the sendMail() method on the transporter object, passing options and a callback that will be executed when it’s finished:
transporter.sendMail(options, (err, info) => {
if (err) {
console.log(err)
} else {
console.log('EMAIL SENT', info.messageId)
}
})
This also accepts a promise-based syntax:
const info = await transporter.sendMail(options)
console.log(info.messageId)
The info object contains the message id assigned by the server, useful for logging.
Keep credentials out of the code
Don’t hardcode the SMTP password in your source. Put it in an environment variable:
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
It’s easy to forget a hardcoded password and push it to a public repo.
One last tip: if your emails end up in spam, the problem is usually your domain’s DNS setup. I made a tool to generate and explain SPF, DKIM and DMARC records.
Related posts about node: