Email module

Sending email

NestJS Mailer + Nodemailer/SMTP, Pug templates, and an authenticated REST endpoint with inline HTML.

Overview

The email module wraps @nestjs-modules/mailer with the Pug adapter. In development, use MailHog (Docker). Use sendMail with inline html or template + context; there is also POST /email/send.

Key points

  • • SMTP transport via ConfigService (smtp.*)
  • • EmailService exported for other modules
  • • Pug templates in modules/email/templates
  • • sendMail allows inline html (template adapter is skipped when html is present)
  • • JWT-protected REST — no @Roles

Structure

Filesystemsrc/modules/email
src/modules/email/
├── email.module.ts
├── email.controller.ts
├── email.service.ts
├── dtos/
│   └── send-email.dto.ts
└── templates/
    ├── layout.pug
    └── *.pug

src/config/smtp.config.ts

Pug templates

Add .pug files under templates/. The file name (without extension) is the template value. Use layout.pug with extends for shared HTML.

  • • layout.pug — base HTML structure (optional, via extends)
  • • template: 'welcome' → templates/welcome.pug
  • • context — object with variables available in Pug
TypeScripttemplate + context
await this.emailService.sendMail({
  to: '[email protected]',
  subject: 'Welcome',
  template: 'welcome',
  context: { name: 'Alice' },
});

SMTP configuration

smtp namespace in src/config/smtp.config.ts. Env vars:

Environment.env
SMTP_HOST=localhost
SMTP_PORT=587
SMTP_SECURE=false
SMTP_REQUIRE_TLS=false
SMTP_USER=
SMTP_PASSWORD=
[email protected]

Docker / MailHog

In Compose, the app points at MailHog (SMTP 1025). Open /mailhog/ to inspect messages.

EmailService

Public service methods:

  • • sendMail(options) — pass-through; use html for inline or template + context
  • • sendEmailConfirmation(email, token) — Auth helper (email-confirmation template)
  • • sendPasswordReset(email, token) — Auth helper (password-reset template)

REST API

JWT required. Any authenticated user can call it (no @Roles).

Send generic email (inline HTML)

Body: to (email), subject, html. The controller uses sendMail with html — no template.

HTTP RequestPOST
POST /api/v1/email/send
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "to": "[email protected]",
  "subject": "Test Email",
  "html": "

Hello

This is a test email

" }

Response

HTTP Response200
{
  "message": "Email sent successfully"
}

Auth integration

AuthModule imports EmailModule and uses helpers with their own templates (email-confirmation, password-reset):

  • • POST /auth/register → sendEmailConfirmation
  • • POST /auth/resend-verification → sendEmailConfirmation
  • • POST /auth/forgot-password → sendPasswordReset
See Auth & JWT docs

Use in another module

Import EmailModule and inject EmailService. Inline or template:

TypeScriptFeature module
@Module({
  imports: [EmailModule],
  providers: [MyService],
})
export class MyModule {}

@Injectable()
export class MyService {
  constructor(private readonly emailService: EmailService) {}

  // Inline HTML (template adapter skipped)
  async notifyInline(email: string) {
    await this.emailService.sendMail({
      to: email,
      subject: 'Hello',
      html: '

Hi

', }); } // Pug template async notifyTemplate(email: string, name: string) { await this.emailService.sendMail({ to: email, subject: 'Welcome', template: 'welcome', context: { name }, }); } }

Notes

Development

With MailHog, SMTP_SECURE and SMTP_REQUIRE_TLS should be false; auth can be empty.

Production

Use a real SMTP provider (SendGrid, SES, etc.) and strong credentials. Never commit passwords. Pug files are copied to dist via nest-cli assets.

Explore