@custom-auth/adapter-nodemailer
v1.0.11
Published
Nodemailer email adapter for @custom-auth.
Maintainers
Readme
@custom-auth/adapter-nodemailer
📦 Ecosystem Packages
- 🔑 Core Engine (@custom-auth/core) — The core framework-agnostic auth engine.
- ⚛️ React SDK (@custom-auth/react) — React hooks and context provider.
- 🌐 Next.js SDK (@custom-auth/nextjs) — Edge-compatible Next.js helpers and middleware.
- 🗄️ Database Adapters:
- ✉️ Email Adapters:
SMTP email adapter for @custom-auth/core. Works with any SMTP provider — Gmail,
Zoho, Brevo, Mailgun, Postmark, Outlook, Office 365, AWS SES, Yahoo, or your own
mail server. Built on Nodemailer.
Choosing between SMTP and Resend? See EMAIL_ADAPTERS.md for a full comparison.
Installation
# Install the core engine, the Nodemailer adapter, and your chosen database adapter
npm install @custom-auth/core @custom-auth/adapter-nodemailer <your-db-adapter>Quick Start
Option A — Built-in preset (recommended)
Pick a preset from the table below, add your credentials, done:
import { createAuth } from '@custom-auth/core';
import { SmtpEmailAdapter, smtpPresets } from '@custom-auth/adapter-nodemailer';
const auth = createAuth({
secret: process.env.AUTH_SECRET!,
emailAdapter: new SmtpEmailAdapter({
...smtpPresets.brevo, // swap to any preset below
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
},
from: 'My App <[email protected]>',
}),
emailVerification: true,
verifyEmailUrl: 'https://yourapp.com/verify-email',
resetPasswordUrl: 'https://yourapp.com/reset-password',
});Option B — Custom SMTP server (your own domain)
new SmtpEmailAdapter({
host: 'mail.yourdomain.com',
port: 465,
secure: true, // true = TLS (port 465), false = STARTTLS (port 587)
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
},
from: 'Auth <[email protected]>',
})Option C — Pre-built Nodemailer transporter
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({ /* your config */ });
new SmtpEmailAdapter({ transporter, from: '[email protected]' })Available Presets
| Preset key | Provider | Free tier | Notes |
|---|---|---|---|
| gmail | Gmail | 500/day (personal) | Requires App Password, not your account password |
| zoho | Zoho Mail | 50/day via SMTP | Best for custom domains at zero cost — free with your own domain |
| brevo | Brevo (Sendinblue) | 300/day, no card | Best free transactional option overall |
| mailgun | Mailgun | 100/day (3 mo) | Pay-as-you-go after trial |
| postmark | Postmark | 100 test/month | Best deliverability; paid in production |
| outlook | Outlook personal | 300/day | @outlook.com / @hotmail.com accounts |
| office365 | Microsoft 365 | Included in M365 | Admin must enable SMTP AUTH |
| awsSes | AWS SES | 62k/mo from EC2 | Change host for non-us-east-1 regions |
| yahoo | Yahoo Mail | Limited | Requires App Password |
| ethereal | Ethereal (dev) | Unlimited (fake) | Emails captured, never delivered — local dev only |
Local Development — Ethereal (zero config)
No real email account needed during development:
// Only in development
if (process.env.NODE_ENV !== 'production') {
const adapter = await SmtpEmailAdapter.createEtherealTransport();
// Logs credentials + https://ethereal.email/messages preview URL to console
}Emails are captured at ethereal.email/messages — click any captured email to view the rendered HTML.
Verify Connection on Startup
Catch misconfigured credentials at boot time, not at send time:
const emailAdapter = new SmtpEmailAdapter({ ... });
await emailAdapter.verify(); // throws if SMTP connection failsCustom Templates
Override any or all templates — partial override, rest use defaults:
new SmtpEmailAdapter({
...smtpPresets.brevo,
auth: { user: '...', pass: '...' },
from: 'Me <[email protected]>',
templates: {
magicLink: (email, url) => ({
subject: `Your sign-in link for ${email}`,
html: `<a href="${url}">Sign in now →</a>`,
text: `Sign in: ${url}`,
}),
// verification and passwordReset still use built-in templates
},
})Each template function receives (email: string, url: string) and must return:
{
subject: string;
html: string;
text?: string; // plain-text fallback — recommended for deliverability
}Extra Mail Options
Apply options to every outgoing email (replyTo, headers, priority, etc.):
new SmtpEmailAdapter({
...smtpPresets.gmail,
auth: { user: '...', pass: '...' },
from: '[email protected]',
mailOptions: {
replyTo: '[email protected]',
headers: { 'X-App-Name': 'MyApp' },
},
})Provider Setup Guides
Gmail
- Enable 2-Step Verification on your Google account
- Go to Google Account → Security → App passwords
- Create an app password for "Mail"
- Use that 16-character password as
SMTP_PASS
[email protected]
SMTP_PASS=xxxx xxxx xxxx xxxx # 16-char App PasswordZoho Mail (free custom domain)
- Sign up at zoho.com/mail
- Add your domain and verify DNS records
- Create a mailbox (e.g.
[email protected]) - Enable SMTP in Zoho Mail settings
[email protected]
SMTP_PASS=your-zoho-passwordBrevo
- Sign up at brevo.com
- Go to Settings → SMTP & API → SMTP Keys → Create a new SMTP key
- Your SMTP user = your Brevo account email address
[email protected] # your Brevo login email
SMTP_PASS=xsmtpsib-... # the SMTP key from Brevo dashboardAWS SES
- Verify your domain in SES console
- Go to SES → SMTP Settings → Create SMTP Credentials (these are NOT your AWS Access Key / Secret Key)
- Change
hostin the preset if not usingus-east-1
SMTP_USER=AKIAIOSFODNN7EXAMPLE # SES SMTP username
SMTP_PASS=wJalrXUtnFEMI/K... # SES SMTP passwordSent Emails
| Auth event | Template used |
|---|---|
| Register with emailVerification: true | verification |
| POST /forgot-password | passwordReset |
| POST /magic-link | magicLink |
Documentation
For full documentation, please visit the Main Repository.
