Getting Started
@nestjs-modules/mailer is a mailer module for the NestJS framework powered by Nodemailer. It renders templates with the engine of your choice, sends through any nodemailer transport, and in v4 adds typed mail classes, automatic retries and failover, staging interception, a test mailbox and a browser preview.
Upgrading from v3?
Read the migration guide: retries are now on by default.
Using an older version? The v3 and v2 docs are still online, and Versions & upgrading shows what changed between them.
Choose Your Setup
Every capability is optional. Pick one option on each line; you can mix them in one app and change your mind later without rewriting your emails:
| Choice | Options |
|---|---|
| How you write emails | sendMail() with inline options · mail classes with send() · the official @nestjs/mail Mailer over our bridges |
| How emails leave | nodemailer (SMTP, SES SDK, sendmail, community transports) · built-in HTTP transports (Resend, Postmark, SendGrid, SES, Mailgun, Brevo) · @nestjs/mail's transports through MailModule |
| When emails are sent | Directly, in the request · in the background with the BullMQ queue · after your transaction commits with the transactional outbox |
| Templates | Inline HTML or the html tag · a template adapter (Handlebars, Pug, EJS, MJML, Liquid, Nunjucks) |
| Development and tests | TestMailbox · FileTransport / LogTransport · browser previews |
Not sure? Start with sendMail() over SMTP or an HTTP transport, sent directly. Add mail classes, a queue or the outbox when you need them.
Requirements
- NestJS 11 or 12
- nodemailer 8 or later
- NestJS 12 is ESM-only and requires Node.js >= 20.19 (or >= 22.12); this CommonJS package loads it through Node.js' native
require(esm). To run Jest on a NestJS 12 project use Node.js >= 24.9 withNODE_OPTIONS=--experimental-vm-modules.
Installation
Install the core package and nodemailer:
pnpm add @nestjs-modules/mailer nodemailerInstall the TypeScript types for nodemailer:
pnpm add -D @types/nodemailerTemplate Engines (optional)
Template engines are optional peer dependencies and are not installed automatically. Install the engine(s) you plan to use:
# Handlebars
pnpm add handlebars
# Pug
pnpm add pug
# EJS
pnpm add ejs
# Liquid
pnpm add liquidjs
# MJML (responsive emails)
pnpm add mjml
# Nunjucks
pnpm add nunjucks
# Email previews in development (`preview` option)
pnpm add -D preview-emailBasic Usage
Import MailerModule into your root AppModule:
import { Module } from '@nestjs/common';
import { MailerModule } from '@nestjs-modules/mailer';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/adapters/handlebars.adapter';
@Module({
imports: [
MailerModule.forRoot({
transport: {
host: 'smtp.example.com',
port: 587,
secure: false,
auth: {
user: 'username',
pass: 'password',
},
},
defaults: {
from: '"No Reply" <noreply@example.com>',
},
template: {
dir: __dirname + '/templates',
adapter: new HandlebarsAdapter(),
options: {
strict: true,
},
},
}),
],
})
export class AppModule {}Then inject and use MailerService:
import { Injectable } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';
@Injectable()
export class NotificationService {
constructor(private readonly mailerService: MailerService) {}
async sendWelcomeEmail(email: string, name: string) {
await this.mailerService.sendMail({
to: email,
subject: 'Welcome!',
template: 'welcome',
context: { name },
});
}
}Mail Classes
For emails you send from more than one place, write a mail class: a typed provider that renders the email from data.
import { Injectable } from '@nestjs/common';
import { Mailable } from '@nestjs-modules/mailer';
@Injectable()
export class WelcomeMail implements Mailable<{ name: string }> {
render({ name }: { name: string }) {
return { subject: `Welcome, ${name}!`, template: 'welcome', context: { name } };
}
}await this.mailerService.send(WelcomeMail, { to: email, data: { name } });Testing
MailerTestModule runs the real mailer without sending anything, and its TestMailbox captures every email for assertions:
import { Test } from '@nestjs/testing';
import { MailerTestModule, TestMailbox } from '@nestjs-modules/mailer';
const moduleRef = await Test.createTestingModule({
imports: [MailerTestModule.register()],
providers: [NotificationService],
}).compile();
await moduleRef.get(NotificationService).sendWelcomeEmail('ada@example.com', 'Ada');
moduleRef.get(TestMailbox).assertSent({ to: 'ada@example.com', subject: 'Welcome!' });See Testing for queries, links, attachments and simulated failures.
Next Steps
- Configuration: async setup, multiple transporters, every option
- Reliability: retries, failover, idempotency
- Delivery rules: staging interception, suppression, unsubscribe
- Dev transports and email previews for local development
- Interop with
@nestjs/mail