How to Send Emails for Free Using Nodemailer and Gmail SMTP

Sending emails for marketing campaigns, OTP verification, or customer support can sometimes be expensive. If you're looking for a way to send emails without spending a dime, you're in the right place.
In this tutorial, we'll walk through exactly how to set up free email sending using Nodemailer as our SMTP client and Gmail as our mail provider. That said, the core concepts apply to any SMTP client or email provider of your choice.
Understanding the Basics: Key Email Terminology
Before we write a single line of code, let's get familiar with a few terms you'll encounter when working with email infrastructure.
What is SMTP?
SMTP stands for Simple Mail Transfer Protocol. Think of it as the shared language that mail clients and mail servers use to communicate. Just like two people need a common language to understand each other, a mail client and mail server need SMTP to exchange messages.
We won't go deep into the internals of the protocol, but there are a handful of key concepts worth understanding.
SMTP Host
The SMTP host is the email server responsible for sending, receiving, and relaying outgoing emails between the sender and recipient. For Gmail, this is smtp.gmail.com.
SMTP Port
The SMTP port is the specific entry point on a server where the SMTP protocol operates. Different ports serve different purposes:
| Port | Protocol | Description |
|---|---|---|
| 587 | STARTTLS | Upgrades a plain-text connection to an encrypted one over the same port. Recommended for most use cases. |
| 465 | SSL/TLS | Sends email over a fully encrypted connection from the start. |
| 25 | None | The original, unencrypted SMTP port. |
| 2525 | STARTTLS | An unofficial backup port, useful when 587 is blocked. |
SMTP User
Your SMTP username is simply your email address (e.g., you@gmail.com). It's used to authenticate your application with the mail server.
SMTP Password
Your SMTP password is used alongside your username for authentication. For Gmail, this won't be your regular account password. We'll cover exactly what to use in the setup section below.
Setting Up Gmail for SMTP Authentication
Gmail doesn't allow you to authenticate with your regular account password when sending emails programmatically. Instead, you'll need to generate an App Password, which is a separate credential specifically for your application.
Step 1: Enable Two-Factor Authentication
Before you can create an App Password, 2FA must be active on your Google account.
Go to your Google Account Security Settings
Under "How you sign in to Google", enable 2-Step Verification
Step 2: Generate an App Password
Visit Google App Passwords
Enter your preferred app name
Click Create and copy the password. You'll only see it once.
⚠️ Keep this password safe. Store it in your
.envfile and never commit it to version control.
Installing Nodemailer
Install Nodemailer via npm:
npm install nodemailer
Configuring Environment Variables
Create a .env file in your project root and add the following:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
Note on ports: Use port
465withSMTP_SECURE=truefor SSL/TLS. Use port587withSMTP_SECURE=falsefor STARTTLS.
Creating the Nodemailer Transporter
The transporter is the core object in Nodemailer. It manages the connection to your email provider and handles sending messages.
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: process.env.SMTP_SECURE === "true", // true for port 465, false for 587
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
Sending an Email
With your transporter configured, sending an email is straightforward:
await transporter.sendMail({
from: `"Your Name" <${process.env.SMTP_USER}>`,
to: "recipient@example.com",
subject: "Hello from Nodemailer!",
text: "This is a plain text email.",
html: "<p>This is an <strong>HTML</strong> email.</p>",
});
That's it. You're now sending emails for free using Gmail's SMTP server.
Putting It All Together
Here's a complete, reusable sendEmail utility function:
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: process.env.SMTP_SECURE === "true",
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
export async function sendEmail({ to, subject, text, html }) {
return await transporter.sendMail({
from: `"My App" <${process.env.SMTP_USER}>`,
to,
subject,
text,
html,
});
}
Conclusion
In this guide, we covered:
The core SMTP concepts you need to know (host, port, credentials)
How to set up Gmail with an App Password for secure programmatic access
How to configure Nodemailer and send your first email
Gmail's free SMTP tier is a great starting point for low-to-medium volume sending. As your application scales, you may want to explore dedicated transactional email services like Resend, Mailgun, or SendGrid. For getting started without spending anything, though, this setup is hard to beat.
Happy sending!