Nodemailer
Send emails from Node.js - easy as cake!
Nodemailer is the most popular email sending library for Node.js. It makes sending emails straightforward and secure, with zero runtime dependencies to manage.
npm install nodemailer
EmailEngine is a self-hosted email gateway that provides REST API access to IMAP and SMTP accounts, webhooks for mailbox changes, and advanced features like OAuth2, delayed delivery, open and click tracking, bounce detection, and more.
Why Nodemailer?
- Zero runtime dependencies - everything you need is included in a single, well-maintained package.
- Security focused - designed to avoid remote code execution vulnerabilities that have affected other Node.js email libraries.
- Full Unicode support - send messages with any characters, including emoji.
- Cross-platform - works identically on Linux, macOS, and Windows with no native addons required (ideal for cloud environments like Azure).
- HTML and plain-text emails - send rich HTML emails with automatic plain-text fallbacks.
- Attachments and embedded images - easily include files and inline images in your messages.
- Built-in TLS/STARTTLS encryption - secure connections are handled automatically.
- Multiple transports - send via SMTP, Sendmail, Amazon SES, streams, and more.
- DKIM signing and OAuth2 authentication - enterprise-ready email authentication.
- Proxy support - route email through proxies for restricted network environments.
- Plugin API - extend functionality with custom plugins for advanced message processing.
- Ethereal.email integration - generate test accounts instantly for local development and testing.
Requirements
- Node.js v6.0.0 or later (examples using async/await require Node.js v8.0.0 or later).
No additional system libraries, services, or build tools are needed.
Quick start
Sending an email with Nodemailer involves three simple steps:
- Create a transporter - Configure your SMTP server or another supported transport method.
- Compose your message - Define the sender, recipient(s), subject, and content.
- Send the email - Call
transporter.sendMail()with your message options.
Create a transporter
A transporter is an object that handles the connection to your email service and sends messages on your behalf. You create one transporter and reuse it for all your emails.
const nodemailer = require("nodemailer");
// Create a transporter using SMTP
const transporter = nodemailer.createTransport({
host: "smtp.example.com",
port: 587,
secure: false, // use STARTTLS (upgrade connection to TLS after connecting)
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
The createTransport(transport[, defaults]) function returns a reusable transporter instance.
| Parameter | Type / Description |
|---|---|
| transport | Object, String, or Plugin. Pass a configuration object (as shown above), a connection URL (for example, "smtp://user:pass@smtp.example.com:587"), or an already-configured transport plugin. |
| defaults | Object (optional). Default values that are automatically merged into every message sent through this transporter. Useful for setting a consistent from address or custom headers. |
Create the transporter once when your application starts and reuse it for all emails. Creating a new transporter for each message wastes resources because each transporter opens network connections and may perform authentication.
Other transport types
- SMTP - see the SMTP guide for the full list of configuration options.
- SES - send via Amazon Simple Email Service using the SES transport.
- Sendmail - pipe messages to the local sendmail binary using the sendmail transport.
- Stream/JSON - generate RFC 822 messages as streams or JSON for testing using the stream transport.
- Plugins - Nodemailer can send emails through any transport that implements the
send(mail, callback)interface. See the transport plugin documentation for details.
Verify the connection (optional)
Before sending emails, you can verify that Nodemailer can connect to your SMTP server. This is useful for catching configuration errors early.
try {
await transporter.verify();
console.log("Server is ready to take our messages");
} catch (err) {
console.error("Verification failed:", err);
}
Send a message
Once you have a transporter, send an email by calling transporter.sendMail(message[, callback]).
try {
const info = await transporter.sendMail({
from: '"Example Team" <team@example.com>', // sender address
to: "alice@example.com, bob@example.com", // list of recipients
subject: "Hello", // subject line
text: "Hello world?", // plain text body
html: "<b>Hello world?</b>", // HTML body
});
console.log("Message sent: %s", info.messageId);
// Preview URL is only available when using an Ethereal test account
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
} catch (err) {
console.error("Error while sending mail:", err);
}
Parameters
| Parameter | Description |
|---|---|
| message | An object containing the email content and headers. See Message configuration for details. |
| callback | (optional) A function with signature (err, info) => {}. If omitted, sendMail returns a Promise. |
Response object
The info object returned on success contains:
| Property | Description |
|---|---|
messageId | The Message-ID header value assigned to the email. |
envelope | An object containing the SMTP envelope addresses (from and to). |
accepted | An array of recipient addresses that the server accepted. |
rejected | An array of recipient addresses that the server rejected. |
rejectedErrors | An array of error objects for each rejected recipient, with details about the rejection reason. |
pending | With the direct transport: addresses that received a temporary failure. |
response | The final response string received from the SMTP server. |
When a message has multiple recipients, it is considered sent as long as at least one recipient address was accepted by the server. Check the rejected array to see which addresses failed.
Error handling
try {
const info = await transporter.sendMail(message);
console.log("Message sent:", info.messageId);
if (info.rejected.length > 0) {
console.warn("Some recipients were rejected:", info.rejected);
}
} catch (err) {
switch (err.code) {
case "ECONNECTION":
case "ETIMEDOUT":
console.error("Network error - retry later:", err.message);
break;
case "EAUTH":
console.error("Authentication failed:", err.message);
break;
case "EENVELOPE":
console.error("Invalid recipients:", err.rejected);
break;
default:
console.error("Send failed:", err.message);
}
}
See the Error reference for a complete list of error codes.
Transporter events
The transporter emits events you can listen for:
| Event | Description |
|---|---|
idle | Emitted when a pooled transporter has capacity to accept more messages. |
error | Emitted when a transport-level error occurs (for example, a connection failure). |
token | Emitted when a new OAuth2 access token is generated. Useful for persisting tokens. |
// Listen for OAuth2 token updates
transporter.on("token", (token) => {
console.log("New access token for %s:", token.user, token.accessToken);
});
Source and License
Nodemailer is open source software, licensed under the MIT No Attribution (MIT-0) license. This means you can use it freely in any project without attribution requirements. Browse the source code on GitHub.
Made with love by Andris Reinman. Logo by Sven Kristjansen.