Security News
Node.js EOL Versions CVE Dubbed the "Worst CVE of the Year" by Security Experts
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
nodemailer
Advanced tools
Nodemailer is a module for Node.js applications to allow easy email sending. It supports various transport methods and has a simple setup process for sending emails.
Send Emails
This feature allows you to send emails using Nodemailer. The code sample shows how to set up a transporter using Gmail, define mail options, and send an email.
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'your.email@example.com',
pass: 'yourpassword'
}
});
let mailOptions = {
from: 'your.email@example.com',
to: 'recipient@example.com',
subject: 'Test Email Subject',
text: 'Hello world?',
html: '<b>Hello world?</b>'
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
HTML Email Content
Nodemailer allows you to send HTML content in your emails. The code sample demonstrates how to send an email with HTML content.
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
// transport configuration
});
let mailOptions = {
from: 'your.email@example.com',
to: 'recipient@example.com',
subject: 'HTML Email',
html: '<h1>Welcome</h1><p>That was easy!</p>'
};
transporter.sendMail(mailOptions, function(error, info){
// callback
});
Attachments
Nodemailer supports sending attachments in emails. The code sample shows how to attach a file to an email.
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
// transport configuration
});
let mailOptions = {
from: 'your.email@example.com',
to: 'recipient@example.com',
subject: 'Attachment',
text: 'Please find the attachment.',
attachments: [
{
filename: 'file.txt',
path: '/path/to/file.txt'
}
]
};
transporter.sendMail(mailOptions, function(error, info){
// callback
});
Custom Transport Methods
Nodemailer allows the use of custom transport methods for sending emails. The code sample illustrates how to use a custom transport plugin.
const nodemailer = require('nodemailer');
const customTransport = require('my-custom-transport');
let transporter = nodemailer.createTransport(customTransport({
// custom transport options
}));
// send mail with defined transport object
transporter.sendMail({
// mail options
}, function(error, info){
// callback
});
A simple Node.js module for Mailgun. Mailgun-js is designed to work with the Mailgun API for sending, receiving, and tracking emails. It's similar to Nodemailer in functionality but is specifically tailored for Mailgun's service.
The official Node.js client library for interacting with the Postmark API. This package is intended for sending emails through Postmark's transactional email service. Unlike Nodemailer, which is more generic, Postmark is focused on providing a robust service for transactional emails.
Amazon Web Services SDK for JavaScript in Node.js. It includes support for SES (Simple Email Service), which can be used to send emails. While Nodemailer is a standalone package for email, aws-sdk is a comprehensive cloud services SDK that includes email sending capabilities among many other AWS services.
Send e-mails from Node.js – easy as cake!
Do not upgrade Nodemailer from 0.7 or lower to 1.0 as there are breaking changes. You can continue to use the 0.7 branch as long as you like. See the documentation for 0.7 here.
See the migration guide from 0.7 to 1.0 in the 1.0 release blog post.
If you want to support with Bitcoins, then my wallet address is 15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM
This is a complete example to send an e-mail with plaintext and HTML body
var nodemailer = require('nodemailer');
// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'gmail.user@gmail.com',
pass: 'userpass'
}
});
// NB! No need to recreate the transporter object. You can use
// the same transporter object for all e-mails
// setup e-mail data with unicode symbols
var mailOptions = {
from: 'Fred Foo ✔ <foo@blurdybloop.com>', // sender address
to: 'bar@blurdybloop.com, baz@blurdybloop.com', // list of receivers
subject: 'Hello ✔', // Subject line
text: 'Hello world ✔', // plaintext body
html: '<b>Hello world ✔</b>' // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
console.log(error);
}else{
console.log('Message sent: ' + info.response);
}
});
See nodemailer-smtp-transport for SMTP configuration options and nodemailer-wellknown for preconfigured service names (example uses 'gmail').
When using default SMTP transport, then you do not need to define transport type explicitly (even though you can), just provide the SMTP options and that's it. For anything else, see the docs of the particular transport mechanism.
Nodemailer 0.x is quite large and includes a ton of stuff that is not needed for most users. Sometimes it causes problems, for example when a feature that you do not even use requires some dependency to be installed that throws in your environment. If you only use SMTP to send e-mails you do not need the SES code and vice versa. The goal is achieved with a plugin system where you can install and load only these plugins that you actually require.
Version 1.0 is a total rewrite from the ground up and relying heavily on Streams2. This allows you to reliably send messages with gigabyte attachments even through a slow network connection without CPU or memory penalties. You probably never need it but it makes using smaller attachments more reliable as well.
Install with npm
npm install nodemailer
To send e-mails you need a transporter object
var transporter = nodemailer.createTransport(transport)
Where
You have to create the transporter object only once. If you already have a transporter object you can use it to send mail as much as you like.
In this case all e-mails are sent directly to the recipients MX server (using port 25)
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport();
transporter.sendMail({
from: 'sender@address',
to: 'receiver@address',
subject: 'hello',
text: 'hello world!'
});
Using direct transport is not reliable as outgoing port 25 used is often blocked by default. Additionally mail sent from dynamic addresses is often flagged as spam. You should really consider using a SMTP provider.
See SMTP configuration options here
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'sender@gmail.com',
pass: 'password'
}
});
transporter.sendMail({
from: 'sender@address',
to: 'receiver@address',
subject: 'hello',
text: 'hello world!'
});
Default SMTP transport is not suitable for large volume of e-mails as a new SMTP connection is established for every mail sent. Use nodemailer-smtp-pool if you need to send a large amout of e-mails.
See Available Transports for known transport plugins but there might be non listed polugins as well.
The following example uses nodemailer-ses-transport (Amazon SES).
var nodemailer = require('nodemailer');
var ses = require('nodemailer-ses-transport');
var transporter = nodemailer.createTransport(ses({
accessKeyId: 'AWSACCESSKEY',
secretAccessKey: 'AWS/Secret/key'
}));
transporter.sendMail({
from: 'sender@address',
to: 'receiver@address',
subject: 'hello',
text: 'hello world!'
});
Built in
Install as dependencies
Once you have a transporter object you can send mail
transporter.sendMail(data, callback)
Where
If the message includes several recipients then the message is considered sent if at least one recipient is accepted
The following are the possible fields of an e-mail message:
'sender@server.com'
or formatted 'Sender Name <sender@server.com>'
, see here for detailsAll text fields (e-mail addresses, plaintext body, html body) use UTF-8 as the encoding. Attachments are streamed as binary.
Attachment object consists of the following properties:
filename
propertyAttachments can be added as many as you want.
var mailOptions = {
...
attachments: [
{ // utf-8 string as an attachment
filename: 'text1.txt',
content: 'hello world!'
},
{ // binary buffer as an attachment
filename: 'text2.txt',
content: new Buffer('hello world!','utf-8')
},
{ // file on disk as an attachment
filename: 'text3.txt',
path: '/path/to/file.txt' // stream this file
},
{ // filename and content type is derived from path
path: '/path/to/file.txt'
},
{ // stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
},
{ // define custom content type for the attachment
filename: 'text.bin',
content: 'hello world!',
contentType: 'text/plain'
},
{ // use URL as an attachment
filename: 'license.txt',
path: 'https://raw.github.com/andris9/Nodemailer/master/LICENSE'
}
]
}
In addition to text and HTML, any kind of data can be inserted as an alternative content of the main body - for example a word processing document with the same text as in the HTML field. It is the job of the e-mail client to select and show the best fitting alternative to the reader. Usually this field is used for calendar events and such.
Alternative objects use the same options as attachment objects. The difference between an attachment and an alternative is the fact that attachments are placed into multipart/mixed or multipart/related parts of the message white alternatives are placed into multipart/alternative part.
Usage example:
var mailOptions = {
...
html: '<b>Hello world!</b>',
alternatives: [
{
contentType: 'text/x-web-markdown',
content: '**Hello world!**'
}
]
}
Alternatives can be added as many as you want.
All the e-mail addresses can be plain e-mail addresses
foobar@blurdybloop.com
or with formatted name (includes unicode support)
"Ноде Майлер" <foobar@blurdybloop.com>
or as an address object
{
name: 'Ноде Майлер',
address: 'foobar@blurdybloop.com'
}
To, Cc and Bcc fields accept comma separated list of e-mails or an array of e-mails or an array of comma separated list of e-mails - use it as you like. Formatting can be mixed.
...,
to: 'foobar@blurdybloop.com, "Ноде Майлер" <bar@blurdybloop.com>, "Name, User" <baz@blurdybloop.com>',
cc: ['foobar@blurdybloop.com', '"Ноде Майлер" <bar@blurdybloop.com>, "Name, User" <baz@blurdybloop.com>']
...
You can even use unicode domains, these are automatically converted to punycode
'"Unicode Domain" <info@müriaad-polüteism.info>'
SMTP envelope is usually auto generated from from
, to
, cc
and bcc
fields but
if for some reason you want to specify it yourself, you can do it with envelope
property.
envelope
is an object with the following params: from
, to
, cc
and bcc
just like
with regular mail options. You can also use the regular address format, unicode domains etc.
mailOptions = {
...,
from: 'mailer@kreata.ee',
to: 'daemon@kreata.ee',
envelope: {
from: 'Daemon <deamon@kreata.ee>',
to: 'mailer@kreata.ee, Mailer <mailer2@kreata.ee>'
}
}
Not all transports can use the
envelope
object, for example SES ignores it and uses the data from the From:, To: etc. headers.
Attachments can be used as embedded images in the HTML body. To use this feature, you need to set additional property of the attachment - cid
(unique identifier of the file) which is a reference to the attachment file. The same cid
value must be used as the image URL in HTML (using cid:
as the URL protocol, see example below).
NB! the cid value should be as unique as possible!
var mailOptions = {
...
html: 'Embedded image: <img src="cid:unique@kreata.ee"/>',
attachments: [{
filename: 'image.png',
path: '/path/to/file',
cid: 'unique@kreata.ee' //same cid value as in the html img src
}]
}
There are 3 stages a plugin can hook to
html
content, add new headers etc. Example: nodemailer-markdown that allows you to use markdown
source instead of text
and html
.'compile' and 'stream' plugins can be attached with use(plugin)
method
transporter.use(step, pluginFunc)
Where
createTransport
All plugins (including transports) get two arguments, the mail object and a callback function.
Mail object that is passed to the plugin function as the first argument is an object with the following properties:
sendMail
methodCompile step plugins get only the mail.data
object but not mail.message
in the mail
argument of the plugin function. If you need to access the mail.message
as well use 'stream' step instead.
This is really straightforward, your plugin can modify the mail.data
object at will and once everything is finished run the callback function. If the callback gets an error object as an argument, then the process is terminated and the error is returned to the sendMail
callback.
Example
The following plugin checks if text
value is set and if not converts html
value to text
by removing all html tags.
transporter.use('compile', function(mail, callback){
if(!mail.text && mail.html){
mail.text = mail.html.replace(/<[^>]*>/g, ' ');
}
callback();
});
See plugin-compile.js for a working example.
Streaming step is invoked once the message structure is built and ready to be streamed to the transport. Plugin function still gets mail.data
but it is included just for the reference, modifying it should not change anything (unless the transport requires something from the mail.data
, for example mail.data.envelope
).
You can modify the mail.message
object as you like, the message is not yet streaming anything (message starts streaming when the transport calls mail.message.createReadStream()
).
In most cases you might be interested in the message.transform() method for applying transform streams to the raw message.
Example
The following plugin replaces all tabs with spaces in the raw message.
var transformer = new (require('stream').Transform)();
transformer._transform = function(chunk, encoding, done) {
// replace all tabs with spaces in the stream chunk
for(var i = 0; i < chunk.length; i++){
if(chunk[i] === 0x09){
chunk[i] = 0x20;
}
}
this.push(chunk);
done();
};
transporter.use('stream', function(mail, callback){
// apply output transformer to the raw message stream
mail.message.transform(transformer);
callback();
});
See plugin-stream.js for a working example.
Transports are objects that have a method send
and properies name
and version
. Additionally, if the transport object is an Event Emitter, 'log' events are piped through Nodemailer. A transport object is passed to the nodemailer.createTransport(transport)
method to create the transporter object.
transport.name
This is the name of the transport object. For example 'SMTP' or 'SES' etc.
transport.name = require('package.json').name;
transport.version
This should be the transport module version. For example '0.1.0'.
transport.version = require('package.json').version;
transport.send(mail, callback)
This is the method that actually sends out e-mails. The method is basically the same as 'stream' plugin functions. It gets two arguments: mail
and a callback. To start streaming the message, create the stream with mail.message.createReadStream()
Callback function should return an info
object as the second arugment. This info object should contain messageId
value with the Message-Id header (without the surrounding < > brackets)
The following example pipes the raw stream to the console.
transport.send = function(mail, callback){
var input = mail.message.createReadStream();
var messageId = (mail.message.getHeader('message-id') || '').replace(/[<>\s]/g, '');
input.pipe(process.stdout);
input.on('end', function() {
callback(null, {
messageId: messageId
});
});
};
transport.close(args*)
If your transport needs to be closed explicitly, you can implement a close
method.
This is purely optional feature and only makes sense in special contexts (eg. closing a SMTP pool).
Once you have a transport object, you can create a mail transporter out of it.
var nodemailer = require('nodemailer');
var transport = require('some-transport-method');
var transporter = nodemailer.createTransport(transport);
transporter.sendMail({mail data});
See minimal-transport.js for a working example.
Nodemailer is licensed under MIT license. Basically you can do whatever you want to with it
The Nodemailer logo was designed by Sven Kristjansen.
v1.0.3 2014-07-16
Fixed a bug where Nodemailer crashed if the message content type was multipart/related
FAQs
Easy as cake e-mail sending from your Node.js applications
The npm package nodemailer receives a total of 3,334,428 weekly downloads. As such, nodemailer popularity was classified as popular.
We found that nodemailer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.