How to Send Automated Emails Using Node.js and SMTP
Automated email is an important feature of modern web applications. Businesses use it to send account verification messages, password reset instructions, order confirmations, appointment reminders, invoices, newsletters, and other customer notifications. Sending these messages automatically improves communication, reduces manual work, and helps applications respond quickly to user activities.
Node.js provides a flexible environment for building email automation systems. Developers can connect Node.js applications to an SMTP server and send messages whenever specific events occur. For example, an application can automatically email a customer after registration, notify an administrator when a new order arrives, or remind a user about an upcoming appointment.
One of the most popular libraries for this purpose is Nodemailer. It simplifies SMTP communication and supports HTML messages, plain-text content, attachments, authentication, and secure connections.
This guide explains how to send automated emails using Node.js and SMTP, including installation, configuration, practical code examples, error handling, and production recommendations.
What Is SMTP and How Does It Work?
SMTP stands for Simple Mail Transfer Protocol. It is the standard communication protocol used to send email messages between mail servers.
When an application sends an email, it needs a way to communicate with an email delivery service. SMTP provides that communication mechanism.
For example, suppose someone creates an account on an online learning platform. The application may need to send a verification email containing a link that confirms the user’s address.
The process generally follows these steps:
- The user submits the registration form.
- The Node.js application receives the information.
- The application creates a verification message.
- Nodemailer connects to the configured SMTP server.
- The SMTP server authenticates the application.
- The message is submitted for delivery.
- The receiving email system processes the message.
- The user receives the verification email if the message is successfully delivered.
SMTP does not determine what the email should contain. That responsibility belongs to the application. Node.js generates the message, while the SMTP server handles the email transmission process.
SMTP is supported by many email hosting companies and delivery providers. This makes it possible to change email providers without completely rewriting the application’s email functionality.
Why Use Node.js for Automated Email Sending?
Node.js is widely used for web applications, APIs, real-time systems, and backend services. Its event-driven architecture makes it suitable for applications that need to communicate with external services, including SMTP servers.
There are several reasons developers choose Node.js for email automation.
Flexible integration: Node.js applications can connect email functionality to registration systems, payment processing, customer databases, booking platforms, and other business services.
Reusable email services: Developers can create a central email module and use it across different parts of an application.
Support for automation: Emails can be triggered by user actions, database events, scheduled jobs, or background processes.
HTML email support: Applications can send professionally formatted messages containing branding, links, buttons, and other HTML elements.
Large package ecosystem: Libraries such as Nodemailer make it easier to implement email delivery without manually handling SMTP communication.
For businesses building web applications with Node.js, automated email can become part of the application’s core communication infrastructure.
Step 1: Install Node.js and Create a Project
Before implementing SMTP email sending, make sure Node.js and npm are installed.
Node.js provides the runtime environment, while npm is used to install application dependencies.
Open a terminal and check the installed versions:
node -v
npm -v
If Node.js is not installed, download it from the official website:
Next, create a project directory:
mkdir node-smtp-email
cd node-smtp-email
Initialize the project:
npm init -y
This command creates a package.json file containing the project’s basic configuration.
The next step is installing Nodemailer.
Step 2: Install Nodemailer
Nodemailer is a Node.js library that simplifies email creation and delivery. It supports SMTP, message formatting, attachments, TLS encryption, and other email-related features.
Install it with npm:
npm install nodemailer
For this tutorial, we will also use the dotenv package to load SMTP credentials from an environment file:
npm install dotenv
The project now has the basic dependencies needed to send emails.
A simple project structure might look like this:
node-smtp-email/
│
├── node_modules/
├── .env
├── .gitignore
├── package.json
├── email.js
└── server.js
The email.js file will contain the reusable email functionality, while server.js will demonstrate how to trigger an automated email.
Step 3: Obtain Your SMTP Server Credentials
Before connecting Nodemailer to an SMTP server, obtain the connection information from your email hosting company or email delivery provider.
Most SMTP providers supply the following details:
| Setting | Example |
|---|---|
| SMTP Host | smtp.example.com |
| SMTP Port | 587 |
| Username | [email protected] |
| Password | Your SMTP password |
| Encryption | STARTTLS |
| Sender Address | [email protected] |
These are illustrative values. Replace them with the actual settings supplied by your email provider.
Two commonly used SMTP connection configurations are:
Port 587: Usually uses STARTTLS. The connection begins without immediate TLS encryption and is upgraded when the server supports it.
Port 465: Uses implicit TLS, meaning the connection is encrypted from the beginning.
For port 587, Nodemailer typically uses:
port: 587,
secure: false
For port 465, use:
port: 465,
secure: true
Using secure: false with port 587 does not automatically mean that the final connection is unencrypted. Nodemailer can upgrade the connection using STARTTLS when the server supports it.
Always use the connection settings recommended by your provider.
Step 4: Store SMTP Credentials Securely
SMTP usernames and passwords should not be written directly into application source code.
Hardcoding credentials creates security risks, especially when developers upload projects to public repositories or share source files with other people.
A better approach is to use environment variables.
Create a .env file in the project directory:
SMTP_HOST=smtp.example.com
SMTP_PORT=587
[email protected]
SMTP_PASS=your_smtp_password
MAIL_FROM="Example Company <[email protected]>"
The values above are examples. Replace them with your real SMTP configuration.
Next, create a .gitignore file:
node_modules/
.env
This prevents the environment file from being included in normal Git commits.
Environment variables allow the application to retrieve credentials without placing them directly in the source code.
Node.js also provides built-in support for loading environment files through its command-line options in supported versions. This tutorial uses dotenv for compatibility with common project setups.
Step 5: Configure Nodemailer to Connect to SMTP
Now create an email.js file.
This file will configure the SMTP transporter, which is responsible for establishing the connection and sending email messages.
Add the following code:
require("dotenv").config();
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: Number(process.env.SMTP_PORT) === 465,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
module.exports = transporter;
The code imports Nodemailer and loads the environment variables.
The createTransport() method creates a reusable SMTP transporter.
Here is what the main settings mean:
host: The hostname of the SMTP server.port: The SMTP connection port.secure: Determines whether TLS is used immediately.auth.user: The SMTP username.auth.pass: The SMTP password or provider-issued credential.
The application can now use this transporter whenever it needs to send an email.
It is important to create the transporter once and reuse it rather than creating a new one for every message. Reusing it reduces unnecessary connection setup and authentication overhead.
Step 6: Send Your First Email Using Node.js
After configuring the SMTP transporter, create a basic email message.
Create a file named server.js:
const transporter = require("./email");
async function sendEmail() {
try {
const info = await transporter.sendMail({
from: process.env.MAIL_FROM,
to: "[email protected]",
subject: "Welcome to Our Platform",
text: "Thank you for registering with us.",
html: `
<h2>Welcome to Our Platform!</h2>
<p>Thank you for creating an account.</p>
<p>We are pleased to have you with us.</p>
`
});
console.log("Email submitted successfully:", info.messageId);
} catch (error) {
console.error("Email sending failed:", error);
}
}
sendEmail();
Replace [email protected] with a valid recipient address.
Run the application:
node server.js
If the SMTP configuration is correct and the server accepts the message, Nodemailer returns information about the submission, including a message ID.
The sendMail() method accepts several message properties:
from: The sender’s email address.to: The recipient’s email address.subject: The email subject.text: The plain-text message.html: The HTML version of the message.
Providing both HTML and plain-text content is recommended. Email clients that cannot display HTML can use the text alternative.
One important distinction is that successful submission to the SMTP server does not guarantee that the recipient’s inbox received the message. The receiving server may still reject, filter, or defer it.
Step 7: Create a Reusable Email Function
Most applications need to send different types of messages. Creating a separate SMTP configuration for every email would make the code unnecessarily complicated.
A better approach is to create a reusable function that accepts the recipient, subject, and message content.
Update email.js:
require("dotenv").config();
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: Number(process.env.SMTP_PORT) === 465,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
async function sendEmail({ to, subject, text, html }) {
try {
const info = await transporter.sendMail({
from: process.env.MAIL_FROM,
to,
subject,
text,
html
});
return {
success: true,
messageId: info.messageId
};
} catch (error) {
console.error("SMTP Error:", error);
return {
success: false,
error: error.message
};
}
}
module.exports = sendEmail;
Now any part of the application can import and use the same email function.
For example:
const sendEmail = require("./email");
async function welcomeCustomer() {
const result = await sendEmail({
to: "[email protected]",
subject: "Welcome to Our Website",
text: "Thank you for joining our website.",
html: `
<h2>Welcome!</h2>
<p>Your account has been created successfully.</p>
`
});
console.log(result);
}
welcomeCustomer();
This approach makes email delivery easier to maintain and allows developers to standardize how messages are sent.
Step 8: Automate Emails Based on User Actions
The real benefit of automated email sending comes from connecting it to application events.
Instead of manually running an email script, developers can call the email function whenever a particular action occurs.
For example, consider a website registration system.
When a new user creates an account, the application can automatically send a welcome email.
A simplified example looks like this:
const sendEmail = require("./email");
async function registerUser(user) {
// Save the new user to the database here.
await sendEmail({
to: user.email,
subject: "Your Account Has Been Created",
text: "Welcome! Your registration was successful.",
html: `
<h2>Welcome, ${user.name}!</h2>
<p>Your account has been created successfully.</p>
<p>You can now sign in to your account.</p>
`
});
return {
success: true,
message: "Registration completed."
};
}
This example assumes the application has already validated the registration details and saved the user.
In a production application, user-provided information must also be safely escaped before inserting it into HTML. Otherwise, malicious content could be interpreted as HTML in the recipient’s email client.
Other events that can trigger automated emails include:
- New account registration.
- Password reset requests.
- Successful payments.
- Failed payment notifications.
- Order confirmations.
- Appointment bookings.
- Subscription renewals.
- New customer inquiries.
- Account security alerts.
This event-driven approach allows the application to communicate with users automatically.
Step 9: Send HTML Emails With Professional Formatting
Plain-text emails are useful for simple notifications, but many businesses prefer branded HTML messages.
HTML emails can contain company logos, headings, buttons, tables, and structured information.
For example, an order confirmation email might contain:
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Order Confirmation</title>
</head>
<body style="font-family: Arial, sans-serif;">
<div style="max-width:600px;margin:auto;">
<h2>Thank You for Your Order!</h2>
<p>Hello John,</p>
<p>Your order has been received successfully.</p>
<p><strong>Order Number:</strong> #10245</p>
<p><strong>Total:</strong> $85.00</p>
<a href="https://example.com/orders/10245"
style="background:#2563eb;color:white;
padding:12px 20px;text-decoration:none;
display:inline-block;">
View Your Order
</a>
<p>Thank you for shopping with us.</p>
</div>
</body>
</html>
`;
The HTML can then be passed to the reusable sendEmail() function.
When designing email templates, use simple layouts, readable typography, and responsive formatting. Some email clients support only a limited selection of CSS features, so test templates in different email environments.
Step 10: Send Automated Emails With Attachments
Some applications need to send files alongside email messages.
Examples include:
- PDF invoices.
- Order receipts.
- Registration documents.
- Course certificates.
- Business proposals.
- Appointment confirmations.
Nodemailer supports attachments through its attachments property.
Here is an example:
const transporter = require("./email");
async function sendInvoice() {
const info = await transporter.sendMail({
from: process.env.MAIL_FROM,
to: "[email protected]",
subject: "Your Invoice",
text: "Please find your invoice attached.",
attachments: [
{
filename: "invoice.pdf",
path: "./documents/invoice.pdf"
}
]
});
console.log("Invoice email submitted:", info.messageId);
}
sendInvoice();
The filename property specifies the name recipients see, while path points to the file on the server.
Applications should validate file paths and attachment permissions carefully. Do not allow untrusted users to supply arbitrary server file paths, because this could expose sensitive files.
For larger files, consider storage services and secure download links rather than attaching everything directly to an email.
Step 11: Verify the SMTP Connection
Before using an SMTP configuration in a production application, it is useful to test whether the connection works.
Nodemailer provides a verify() method.
For example:
const transporter = require("./email");
async function verifySMTP() {
try {
await transporter.verify();
console.log("SMTP connection is ready.");
} catch (error) {
console.error("SMTP verification failed:", error);
}
}
verifySMTP();
This checks whether the application can resolve and connect to the SMTP server, establish the required TLS connection, and authenticate.
It does not guarantee that every message will be accepted. Sender permissions, recipient addresses, provider policies, and delivery restrictions are still relevant.
Running this test during deployment or application startup can help detect configuration problems early.
Step 12: Handle Email Errors Properly
Email automation can fail for several reasons.
The SMTP server may be unavailable, authentication credentials may be incorrect, the application may experience a network problem, or the provider may reject a message because of sending limits.
A production system should not assume every email will be sent successfully.
Useful error-handling practices include:
Log failures: Record the relevant error information, message identifier, and application event. Avoid logging passwords, authentication tokens, or unnecessary personal information.
Retry temporary failures: Some connection problems and temporary SMTP responses can be resolved by retrying after a delay.
Avoid unlimited retries: Repeated attempts can create unnecessary load or cause duplicate messages. Use a limited retry policy with increasing delays.
Monitor delivery status: Track accepted messages, provider responses, bounces, and complaints when the provider supports these capabilities.
Protect critical workflows: A failed welcome email should not necessarily cancel a successful registration. Store the email task so it can be retried independently.
For important applications, email delivery should be treated as a separate background process rather than something that must always finish before the main user request can succeed.
Step 13: Send Multiple Emails Efficiently
Sending a small number of emails is straightforward, but applications may eventually need to process hundreds or thousands of messages.
Opening a new SMTP connection for every email creates unnecessary overhead.
Nodemailer supports connection pooling, which allows multiple messages to share a set of reusable SMTP connections.
A pooled transporter can be configured like this:
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: 465,
secure: true,
pool: true,
maxConnections: 5,
maxMessages: 100,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});
The pool option enables connection reuse. maxConnections controls the maximum number of simultaneous connections, while maxMessages controls how many messages can use a connection before it is replaced.
The actual limits should match the SMTP provider’s policies.
For larger campaigns, use a background job queue instead of loading thousands of messages into application memory. The queue can process messages gradually, manage retries, and prevent the application from exceeding provider limits.
Also, avoid placing large recipient lists in the to field when messages are intended to be private. For individual notifications, send separate messages or use an appropriate provider-supported campaign system.
Step 14: Improve Email Deliverability
Sending an email successfully does not guarantee that it will reach the inbox. Deliverability depends on several technical and operational factors.
Agencies and businesses should pay attention to the following:
SPF: Sender Policy Framework identifies which servers are authorized to send email for a domain.
DKIM: DomainKeys Identified Mail adds a cryptographic signature that helps receiving systems verify message authenticity.
DMARC: Domain-based Message Authentication, Reporting, and Conformance defines how receiving systems should handle messages that fail authentication checks and provides reporting capabilities.
Other important practices include using a consistent sender identity, maintaining clean mailing lists, avoiding misleading subject lines, and processing unsubscribe requests.
For bulk marketing campaigns, use a dedicated email marketing or delivery service that supports consent management, bounce processing, unsubscribe handling, and campaign monitoring.
Transactional email and promotional email should also be treated as different communication categories. Password resets and order confirmations should not automatically become marketing messages.
Best Practices for Production Email Automation
A reliable email system needs more than a working SMTP connection.
The following recommendations help developers build applications that can handle real-world email requirements.
Use a reusable email module: Keep SMTP configuration and message-sending logic in one place.
Keep credentials private: Store SMTP credentials in protected environment variables or a secrets-management service.
Use TLS: Follow the SMTP provider’s recommended secure connection settings. Do not disable certificate verification to work around production connection errors.
Validate recipient addresses: Check user input before creating email tasks.
Use email templates: Maintain separate templates for welcome messages, invoices, verification links, and other common communications.
Implement background queues: Process non-urgent emails outside the main application request.
Prevent duplicate messages: Use unique event identifiers or idempotency controls to avoid sending the same notification multiple times when an operation is retried.
Monitor performance: Track sending failures, queue delays, provider responses, and delivery-related events.
Respect privacy and consent: Follow applicable email marketing laws and data protection requirements.
Test before deployment: Send test messages to different email providers and inspect both HTML and plain-text versions.
Conclusion
Sending automated emails using Node.js and SMTP is a practical way to improve communication in web applications. With Nodemailer, developers can connect to an SMTP server, configure authentication, send HTML messages, attach files, and trigger notifications whenever important application events occur.
The basic implementation involves installing Nodemailer, storing SMTP credentials securely, creating a reusable transporter, and calling sendMail() whenever an email needs to be sent.
For production applications, developers should go further by implementing error handling, connection pooling, background queues, delivery monitoring, and proper email authentication.
The most important principle is to build email automation as a reliable application service rather than a collection of isolated scripts. A well-designed system can support account notifications, customer communication, order processing, appointment reminders, and other business workflows while remaining secure and maintainable as the application grows.
SEO Publishing Details
SEO Title: How to Send Automated Emails Using Node.js and SMTP
Meta Description: Learn how to send automated emails using Node.js and SMTP with Nodemailer. Explore setup, authentication, HTML emails, attachments, error handling, and automation.
Suggested URL Slug: send-automated-emails-nodejs-smtp
Primary Keyword: Send automated emails using Node.js and SMTP
Related Keywords:
- Node.js SMTP email sending
- Nodemailer tutorial
- Send email using Node.js
- Node.js email automation
- SMTP configuration in Node.js
- Automated email notifications
- Nodemailer SMTP integration
- Send HTML emails with Node.js
- Node.js transactional email
Technical references: The implementation follows Nodemailer’s official documentation for SMTP transport, authentication, TLS, verification, and connection pooling, along with the official Node.js environment-variable documentation.