How to Setup Nodemailer in a Node.js Express Project
31 Views
When I started building real-world Node.js projects, one of the first backend features I struggled with was email integration. Contact forms, OTP verification, forgot password systems, and order confirmation emails all required a proper email setup, but initially, configuring SMTP and handling authentication errors felt confusing. After trying different solutions, I found Nodemailer to be one of the easiest and most reliable packages for sending emails in Node.js applications. I have personally used Nodemailer in authentication systems, portfolio contact forms, admin dashboards, and eCommerce projects. In this article, I’ll share how I usually set up Nodemailer in a Node.js Express project, including common mistakes beginners face and the exact approach I use in my own projects.
What is Nodemailer?
Nodemailer is a popular Node.js package used to send emails from your backend application. It supports:
- Gmail SMTP
- Outlook SMTP
- Custom SMTP servers
- HTML email templates
- Attachments
- OTP and verification emails
- Email authentication
Nodemailer is lightweight, easy to configure, and widely used in production applications.
It supports all SMTP Servers like the most popular email providers: Resend, AhaSend, UnoSend, Mailtrap, etc
Read More: Top 10 Free Email Providers in 2026 for Developers & Small Websites
Why I Prefer Nodemailer in My Projects
- I have tested multiple email solutions over time, but Nodemailer remains my go-to option for small to medium-sized projects because: Setup is simple and beginner-friendly
- Works perfectly with Express.js
- Supports Gmail and custom SMTP
- Easy to send HTML emails
- Great for OTP and authentication systems
- Lightweight and production-ready
One thing I personally like about Nodemailer is that it gives full control over email formatting and backend logic without requiring heavy third-party SDKs.
If you want to create a Secure OTP Email System without Nodemailer, this article is perfect for you: Building Secure OTP Email System
Prerequisites
Before starting, make sure you have:
- Node.js installed
- Express.js project setup
- Gmail account or SMTP credentials
- Basic knowledge of JavaScript and Express
Step 1: Create Node.js Express
If you already have an Express project, you can skip this step. Create a new project:
bash
mkdir nodemailer-tutorial
cd nodemailer-tutorial
Initialize Node.js:
bash
npm install express
Install Express:
bash
npm install express
Create server.js:
import express from 'express'
const app = express()
app.get("/", (req, res) => {
res.send("Server Running")
})
app.listen(3000, () => {
console.log("Server running on port 3000")
})
Run the server:
bash
node server.js
Step 2: Install Nodemailer
Install the Nodemailer package:
bash
npm install nodemailer
Step 3: Enable Gmail App Password
If you are using Gmail SMTP, you should use an App Password instead of your normal Gmail password. Steps:
- Open your Google Account
- Enable 2-Step Verification
- Go to App Passwords
- Generate a new app password
- Copy the generated password You will use this password inside the Nodemailer configuration.
If you don't want to add a Google App Password, you can use your custom SMTP server or other mail service providers like Resend, AhaSend, Brevo, etc.
Step 4: Create Email Transporter
Create a new file named mailer.js.
import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "your-email@gmail.com",
pass: "your-app-password",
},
})
export default transporter
Step 5: Send Email Using Nodemailer
Update your server.js file:
import express from 'express'
import transporter from './mailer'
const app = express()
app.get("/send-email", async (req, res) => {
try {
const info = await transporter.sendMail({
from: '"My App" <your-email@gmail.com>',
to: "example@gmail.com",
subject: "Welcome Email",
text: "Hello from Nodemailer",
html: "<h2>Hello from Nodemailer</h2>",
const express = require("express")
const transporter = require("./mailer")
const app = express()
app.get("/send-email", async (req, res) => {
try {
const info = await transporter.sendMail({
from: '"My App" <your-email@gmail.com>',
to: "example@gmail.com",
subject: "Welcome Email",
text: "Hello from Nodemailer",
html: "<h2>Hello from Nodemailer</h2>",
})
res.send({
success: true,
message: "Email sent successfully",
info,
})
} catch (error) {
console.log(error)
res.status(500).send({
success: false,
message: "Failed to send email",
})
}
})
app.listen(3000, () => {
console.log("Server running on port 3000")
}) })
res.send({
success: true,
message: "Email sent successfully",
info,
})
} catch (error) {
console.log(error)
res.status(500).send({
success: false,
message: "Failed to send email",
})
}
})
app.listen(3000, () => {
console.log("Server running on port 3000")
})
Now open:
http://localhost:3000/send-email
If everything is configured correctly, the email will be sent successfully.
If you want to store the email data in a database and search for the best database, then this article is for you: 10 Best Free Postgres Databases
Step 6: Use Environment Variables (Recommended)
Never store email credentials directly inside source code.
Install dotenv:
npm install dotenv
Create .env file:
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
Update mailer.js:
import dontenv from 'dotenv'
import nodemailder from 'nodemailder'
dontenv.config()
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
})
export default transporter
Step 7: Send Dynamic Emails
You can also send dynamic emails from forms.
Example:
app.post("/contact", async (req, res) => {
const { name, email, message } = req.body
try {
await transporter.sendMail({
from: email,
to: process.env.EMAIL_USER,
subject: `Message from ${name}`,
html: `
<h2>Contact Form</h2>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Message:</strong> ${message}</p>
`,
})
res.send("Message sent successfully")
} catch (error) {
res.status(500).send("Failed to send message")
}
})
Best Practices for Nodemailer
- Always use environment variables
- Validate email addresses before sending
- Use HTML templates for professional emails
- Avoid sending spam emails
- Use queue systems for bulk emails
- Add proper error handling
- Use transactional email services in production
Production Email Services
For production applications, consider using:
- SendGrid
- Mailgun
- Amazon SES
- Brevo
- Postmark
- Resend
These services provide:
- Better email delivery
- Analytics
- Email templates
- Queue handling
- Spam protection
- High scalability
Conclusion
Nodemailer is one of the easiest and most powerful ways to send emails in a Node.js Express application. With just a few steps, you can integrate email functionality into your project for authentication, notifications, contact forms, and transactional emails.
Using environment variables, proper SMTP configuration, and production email services can help you build secure and scalable email systems.
If you are building modern web applications with Node.js and Express, learning Nodemailer is an essential backend development skill.
FAQs
Is Nodemailer free?
Yes, Nodemailer is completely free and open-source.
Can I use Nodemailer with Gmail?
Yes, Gmail SMTP works perfectly with Nodemailer.
Is Nodemailer good for production?
Yes, but for large-scale production apps, using services like SendGrid or Amazon SES is recommended.
Can I send HTML emails using Nodemailer?
Yes, Nodemailer fully supports HTML email templates.
Can Nodemailer send attachments?
Yes, you can send files, PDFs, images, and other attachments using Nodemailer.

Farindra Bhandari
farindrabahadurbhandari@gmail.comPassionate full-stack developer building modern web applications with React, Node.js, and PostgreSQL. I Like to share my knowledge, experience through blogging and open-source contributions.



