Best Email Libraries for Node.js in 2026
TL;DR
Nodemailer for SMTP/self-hosted; Resend for modern API-based sending; React Email for beautiful templates. Nodemailer (~5M weekly downloads) is the battle-tested SMTP library — works with any mail server. Resend (~300K downloads, fast-growing) is an API-first service with a clean SDK. React Email (~600K downloads) is a template system that works with any sender. The modern stack in 2026: React Email + Resend.
Key Takeaways
- Nodemailer: ~5M weekly downloads — SMTP/self-hosted, works with Gmail, SendGrid, SES
- Resend: ~300K downloads — API-first, React-native, $0 free tier (3K emails/mo)
- React Email: ~600K downloads — cross-client templates using React components
- nodemailer + SES — cheapest for high volume ($0.10/1K emails)
- Resend + React Email — best DX for startups in 2026
Nodemailer (SMTP, Universal)
// Nodemailer — SMTP setup with various providers
import nodemailer from 'nodemailer';
// Gmail (for development/low volume)
const gmailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.GMAIL_USER,
pass: process.env.GMAIL_APP_PASSWORD, // App Password (not account password)
},
});
// Amazon SES (for production, cheapest at scale)
const sesTransport = nodemailer.createTransport({
host: 'email-smtp.us-east-1.amazonaws.com',
port: 587,
secure: false,
auth: {
user: process.env.SES_ACCESS_KEY_ID,
pass: process.env.SES_SECRET_ACCESS_KEY,
},
});
// SendGrid (API as SMTP)
const sendgridTransport = nodemailer.createTransport({
host: 'smtp.sendgrid.net',
port: 587,
auth: {
user: 'apikey',
pass: process.env.SENDGRID_API_KEY,
},
});
// Nodemailer — sending email
const transporter = nodemailer.createTransport({ /* config */ });
// Verify connection
await transporter.verify();
// Send with HTML
const info = await transporter.sendMail({
from: '"Acme Team" <noreply@acme.com>',
to: 'user@example.com',
subject: 'Welcome to Acme!',
text: 'Welcome to Acme! Your account is ready.',
html: `
<div style="font-family: sans-serif; max-width: 600px;">
<h1>Welcome to Acme!</h1>
<p>Your account is ready. <a href="https://acme.com/login">Log in now</a>.</p>
</div>
`,
// Attachments
attachments: [
{
filename: 'invoice.pdf',
path: '/tmp/invoice.pdf',
contentType: 'application/pdf',
},
],
});
console.log('Message sent:', info.messageId);
// Nodemailer — with DKIM signing (required for good deliverability)
const transporter = nodemailer.createTransport({
host: 'smtp.example.com',
port: 587,
auth: { user: '...', pass: '...' },
dkim: {
domainName: 'acme.com',
keySelector: 'default',
privateKey: process.env.DKIM_PRIVATE_KEY,
},
});
Best for: Self-hosted email, full control over SMTP provider, existing mail server infrastructure.
Resend (Modern API)
// Resend — API-first, developer-friendly
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
// Simple send
const { data, error } = await resend.emails.send({
from: 'Acme <noreply@acme.com>',
to: ['user@example.com'],
subject: 'Welcome to Acme!',
html: '<h1>Welcome!</h1>',
});
if (error) {
console.error('Failed to send:', error);
return;
}
console.log('Sent:', data?.id);
// Resend + React Email — modern email templating
import { Resend } from 'resend';
import WelcomeEmail from '@/emails/WelcomeEmail'; // React Email component
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'Acme <noreply@acme.com>',
to: user.email,
subject: 'Welcome to Acme!',
react: <WelcomeEmail name={user.name} />, // Render React → HTML automatically
});
// Resend — batch sending
await resend.batch.send([
{
from: 'noreply@acme.com',
to: 'alice@example.com',
subject: 'Your report is ready',
html: '<p>Hi Alice...</p>',
},
{
from: 'noreply@acme.com',
to: 'bob@example.com',
subject: 'Your report is ready',
html: '<p>Hi Bob...</p>',
},
]);
Best for: Startups and modern apps. 3K free emails/month, no SMTP config, built-in analytics.
React Email (Templates)
// React Email — cross-client email components
import {
Html, Head, Body, Container, Section,
Text, Button, Img, Link, Hr, Preview,
} from '@react-email/components';
interface WelcomeEmailProps {
name: string;
loginUrl: string;
}
export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Preview>Welcome to Acme — your account is ready</Preview>
<Body style={{ backgroundColor: '#f6f9fc', fontFamily: 'sans-serif' }}>
<Container style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<Img
src="https://acme.com/logo.png"
width={120}
height={40}
alt="Acme"
/>
<Section>
<Text style={{ fontSize: '24px', fontWeight: 'bold' }}>
Welcome, {name}!
</Text>
<Text style={{ color: '#666', lineHeight: '1.6' }}>
Your account is ready. Click below to get started.
</Text>
<Button
href={loginUrl}
style={{
backgroundColor: '#3B82F6',
color: '#fff',
padding: '12px 24px',
borderRadius: '6px',
textDecoration: 'none',
}}
>
Log in to your account
</Button>
</Section>
<Hr />
<Text style={{ fontSize: '12px', color: '#999' }}>
Acme Inc, 123 Main St, San Francisco, CA
{' · '}
<Link href="{{unsubscribe_url}}">Unsubscribe</Link>
</Text>
</Container>
</Body>
</Html>
);
}
// React Email — preview server
// Run: npx react-email dev --dir emails --port 3001
// Opens a preview of all your email templates in browser
// renderAsync — render to HTML string
import { render } from '@react-email/render';
import WelcomeEmail from './WelcomeEmail';
const html = await render(<WelcomeEmail name="Alice" loginUrl="https://acme.com" />);
const text = await render(<WelcomeEmail name="Alice" loginUrl="https://acme.com" />, {
plainText: true,
});
// Use with any sender:
await nodemailer.sendMail({ html, text, /* ... */ });
await resend.emails.send({ html, /* ... */ });
// React Email — works with all major senders
import { render } from '@react-email/render';
// Nodemailer
transporter.sendMail({ html: await render(<WelcomeEmail />) });
// Resend (native react prop)
resend.emails.send({ react: <WelcomeEmail /> });
// SendGrid
sgMail.send({ html: await render(<WelcomeEmail />) });
// AWS SES
ses.sendEmail({ Message: { Body: { Html: { Data: await render(<WelcomeEmail />) } } } });
Best for: Any project that needs beautiful, maintainable email templates. Framework-agnostic.
Pricing at Scale
| Service | Free Tier | $10/mo | $100/mo |
|---|---|---|---|
| Resend | 3K/mo | 50K/mo | 500K/mo |
| SendGrid | 100/day | 100K/mo | 1.5M/mo |
| Mailgun | 1K/mo (trial) | 50K/mo | 500K/mo |
| Postmark | 100/mo | ~50K/mo | ~600K/mo |
| AWS SES (self) | — | ~100K/mo | ~1M/mo |
| Self-hosted | Unlimited* | Unlimited* | Unlimited* |
*Self-hosted costs infrastructure + deliverability management. Nodemailer + VPS + Postfix is possible but requires SPF/DKIM/DMARC setup and IP reputation management.
When to Choose
| Scenario | Pick |
|---|---|
| New app, fast setup | Resend + React Email |
| Need beautiful templates | React Email (pairs with any sender) |
| Full SMTP control, self-hosted | Nodemailer |
| High volume (millions), cost-sensitive | Nodemailer + SES |
| Already on AWS | aws-sdk SES (direct) or Nodemailer + SES |
| Need transactional + marketing | SendGrid (both products) |
| Open source alternative | nodemailer-sendmail (local MTA) |
Compare email library package health on PkgPulse.
See the live comparison
View nodemailer vs. resend on PkgPulse →