Sending email from your Node.js app is surprisingly straightforward with Nodemailer, but getting the SMTP configuration just right can feel like deciphering ancient hieroglyphs.
Let’s see Nodemailer in action. Imagine you want to send a welcome email when a new user signs up.
const nodemailer = require('nodemailer');
// Create a Nodemailer transporter using SMTP
const transporter = nodemailer.createTransport({
host: 'smtp.example.com', // Your SMTP server hostname
port: 587, // Common port for TLS/STARTTLS
secure: false, // Use 'true' if port is 465 (SSL/TLS)
auth: {
user: 'your_email@example.com', // Your email address
pass: 'your_email_password' // Your email password or app-specific password
}
});
// Define email options
const mailOptions = {
from: '"Your App Name" <noreply@yourdomain.com>', // Sender address
to: 'recipient@example.com', // List of receivers
subject: 'Welcome to Our App!', // Subject line
html: '<b>Hello world!</b><br>Thank you for signing up.' // HTML body
};
// Send mail
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
});
This code snippet sets up a transporter object, which is Nodemailer’s interface to your mail server. The createTransport function takes a configuration object that tells Nodemailer how to connect to your SMTP server. The host, port, secure, and auth properties are the key players here.
The host is the address of your mail server (e.g., smtp.gmail.com, smtp.office365.com). The port is the communication channel, with 587 being the most common for encrypted connections using STARTTLS, and 465 typically used for direct SSL/TLS. secure: false is used with STARTTLS on port 587, while secure: true is for direct SSL/TLS on port 465. The auth object contains your credentials: user is your email address, and pass is your password or, more securely, an app-specific password if your provider supports it.
Once the transporter is ready, sendMail takes your message details – sender, recipient(s), subject, and body (either plain text or HTML) – and dispatches it.
The real magic lies in understanding the nuances of different email providers and their security protocols. For instance, Gmail requires you to enable "Less secure app access" (though an app-specific password is far better) and often uses port 465 with secure: true or port 587 with secure: false and STARTTLS. Outlook/Office 365 is similar, often preferring port 587. Many transactional email services like SendGrid or Mailgun provide their own SMTP credentials, abstracting away the complexities of major providers.
Here’s a practical example with Gmail:
const transporter = nodemailer.createTransport({
service: 'gmail', // Use built-in service name
auth: {
user: 'your_gmail_address@gmail.com',
pass: 'your_gmail_app_password' // IMPORTANT: Use an app password!
}
});
Notice the service: 'gmail' shorthand. Nodemailer has built-in configurations for popular services. When using an app-specific password, you’ll typically generate this from your Google Account security settings under "App passwords." This is crucial because using your main Google account password directly with nodemailer.createTransport might fail due to Google’s security policies.
When configuring for Office 365, you might see something like this:
const transporter = nodemailer.createTransport({
host: 'smtp.office365.com',
port: 587,
secure: false, // STARTTLS
auth: {
user: 'your_office365_email@yourdomain.com',
pass: 'your_office365_password'
}
});
Here, host and port are explicit, and secure: false indicates the use of STARTTLS, a common authentication method for Office 365 on port 587.
A common pitfall is incorrectly setting the secure option. If you’re using port 587 with STARTTLS, secure should be false. If you’re using port 465 for direct SSL/TLS, secure should be true. Mismatching these will lead to connection errors or authentication failures.
Another detail to consider is the from address. For services like Gmail, the from address often needs to match the user in your auth object, or at least be an alias you’ve configured within that account. If you try to send from an address that isn’t recognized by your SMTP server as belonging to your authenticated user, the send will likely fail.
The most surprising thing about Nodemailer’s SMTP configuration is that the secure option doesn’t directly imply the use of SSL/TLS. Instead, secure: false signifies that the connection will attempt to upgrade to TLS using the STARTTLS command after establishing an initial unencrypted connection, which is the standard for port 587. Conversely, secure: true means the connection is established directly over SSL/TLS from the outset, typically on port 465. This distinction is vital for correctly configuring your transporter.
The next step after mastering SMTP configuration is often dealing with rate limits imposed by email providers or exploring more robust solutions like dedicated transactional email services.