Skip to content
← All posts
012 min read

How to Send Email in Node.js with TypeScript in 2026: Nodemailer vs Resend vs AWS SES

  • backend-development
  • aws
  • email-marketing
Send Email in Node.js with TypeScript: 2026 Guide — by Chirag Mehta
Send Email in Node.js with TypeScript: 2026 Guide

My Nodemailer post from 2022 is still one of my most-read articles, so people clearly still need this. But the options have changed. Today you have three solid choices, and the right one depends on your app.

Quick comparison

Nodemailer vs. Resend vs. AWS SES
Nodemailer vs. Resend vs. AWS SES
  • Nodemailer: an SMTP client library. You need an email provider (any SMTP server). Setup takes minutes. Best when you already have an SMTP server.
  • Resend: an email API, no provider needed. Setup takes minutes. Best for fast setup and React templates.
  • AWS SES: an email API, no provider needed. Setup takes longer (domain verification, leaving the sandbox). Best for high volume on AWS.

Option 1: Nodemailer

Nodemailer sends through any SMTP server: Gmail, Outlook, your host, or even SES’s SMTP interface.

npm install nodemailer
npm install -D @types/nodemailer
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: 587,
secure: false, // STARTTLS on 587
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
export async function sendWithNodemailer(to: string, subject: string, html: string) {
const info = await transporter.sendMail({
from: '"My App" <no-reply@myapp.com>',
to,
subject,
html,
});
return info.messageId;
}

Call await transporter.verify() once on startup to catch bad credentials early.

Option 2: Resend

Resend is an email API. No SMTP settings, just an API key.

npm install resend
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);
export async function sendWithResend(to: string, subject: string, html: string) {
const { data, error } = await resend.emails.send({
from: "My App <no-reply@myapp.com>",
to: [to],
subject,
html,
});
if (error) throw new Error(error.message);
return data?.id;
}

Note that Resend returns { data, error } instead of throwing, so always check error (Resend docs).

Option 3: AWS SES

If you’re already on AWS, SES is built for volume. Use the v3 SDK:

npm install @aws-sdk/client-sesv2
import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
const ses = new SESv2Client({ region: "us-east-1" });
export async function sendWithSes(to: string, subject: string, html: string) {
const res = await ses.send(
new SendEmailCommand({
FromEmailAddress: "no-reply@myapp.com",
Destination: { ToAddresses: [to] },
Content: {
Simple: {
Subject: { Data: subject },
Body: { Html: { Data: html } },
},
},
})
);
return res.MessageId;
}

New SES accounts start in a sandbox where you can only send to verified addresses. Request production access before you launch.

Make switching easy

Switching providers is a one-line change
Switching providers is a one-line change

Whatever you pick, hide it behind one function. Then changing providers later is a one-line change.

type SendEmail = (to: string, subject: string, html: string) => Promise<string | undefined>;
export const sendEmail: SendEmail =
process.env.EMAIL_PROVIDER === "ses" ? sendWithSes : sendWithResend;

Don’t skip deliverability

With any option, set up SPF, DKIM and DMARC records for your sending domain. Without them, Gmail and Outlook are likely to send your emails to spam, no matter which library you use.

Which should you use?

Which should you use?
Which should you use?
  • Side project or startup: Resend. Fastest to set up, nice developer experience.
  • Existing SMTP server or company mailbox: Nodemailer.
  • High volume and already on AWS: SES.

In the next posts I’ll cover Gmail with Nodemailer (app passwords and OAuth2) and templated emails with React Email.

Author card for Chirag Mehta, Full-Stack Developer specializing in React, Next.js and Node.js. Links: github.com/chiragmehta900, linkedin.com/in/chiragmehta900, medium.com/@chiragmehta900
Chirag Mehta

Originally published on Medium

Clap, comment or follow along there

Read on Medium →