How to Automatically Send Emails in NestJS

Updated: December 31, 2023 By: Guest Contributor Post a comment

Introduction

Sending emails automatically is an essential feature for modern web applications. NestJS, a progressive Node.js framework for building server-side applications, comes with powerful features for this task. This tutorial will guide you through setting up an automated email system in NestJS, ensuring you can implement this functionality with ease.

Setting Up Your NestJS Project

To start, make sure you have NestJS CLI installed:

npm i -g @nestjs/cli
nestjs new email-service

Now, navigate into your project directory and install the necessary packages for sending emails:

cd email-service
npm install nodemailer @nestjs-modules/mailer

Configuring the Mailer Module

The ‘@nestjs-modules/mailer’ module provides a wrapper around Nodemailer for easy integration:

// mail.module.ts
import { Module } from '@nestjs/common';
import { MailerModule } from '@nestjs-modules/mailer';

@Module({
  imports: [
    MailerModule.forRoot({
      transport: {
        host: 'smtp.example.com',
        port: 587,
        secure: false, // upgrade later with STARTTLS
        auth: {
          user: '[email protected]',
          pass: 'password'
        }
      },
      defaults: {
        from: '"No Reply" <[email protected]>'
      }
    })
  ]
})
export class MailModule {}

You’ll need to update the configuration with your specific SMTP server details.

Creating an Email Service

Let’s create a service to encapsulate email functionality:

// email.service.ts
import { Injectable } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';

@Injectable()
export class EmailService {
  constructor(private readonly mailerService: MailerService) {}

  async sendWelcomeEmail(email: string): Promise {
    await this.mailerService.sendMail({
      to: email, // list of receivers
      subject: 'Welcome to Our Service', // Subject line
      template: './welcome', // The `.hbs` template file
      context: {
        // Data to be sent to template engine.
      }
    });
  }
}

This service method can now be called from within any controller or other service in your NestJS application.

Creating a Template Engine

Utilize a template engine like Handlebars to create dynamic email templates:

npm install handlebars

Then, update your MailerModule configuration to use this:

// Update in mail.module.ts
...
MailerModule.forRoot({
  ...
  template: {
    dir: process.cwd() + '/templates/',
    adapter: new HandlebarsAdapter(),
    options: {
      strict: true,
    },
  },
})
...

Create a ‘templates’ directory in your project’s root and add ‘welcome.hbs’ with your email HTML and Handlebars syntax.

Testing Email Functionality

Create a controller to test sending emails via an HTTP request:

// email.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
import { EmailService } from './email.service';

@Controller('email')
export class EmailController {
  constructor(private readonly emailService: EmailService) {}

  @Get('send')
  async sendEmail(@Query('to') to: string) {
    await this.emailService.sendWelcomeEmail(to);
    return { message: 'Email sent!' };
  }
}

Now you can test this by navigating to ‘http://localhost:3000/email/[email protected]’ to trigger the email sending.

Advanced Use Cases

We’ll explore how to automate periodic email sending, handle attachments, and manage multiple templates.

To automate sending emails at specific intervals, investigate using the ‘@nestjs/schedule’ module combined with CRON jobs within your service.

Handling Attachments

To include attachments, modify your sendMail call:

/.../
await this.mailerService.sendMail({
  /.../
  attachments: [
    {
      filename: 'attachment.pdf',
      path: '/path/to/attachment.pdf'
    }
  ]
});
/.../

Be cautious about the file paths and storage when working with attachments, especially in a production setting.

Managing Multiple Email Templates

Create a method that can switch between various templates depending on the email type sent:

// email.service.ts
/.../
async sendUserNotification(email: string, notificationType: 'alert' | 'reminder') {
  const templates = {
    alert: './alert',
    reminder: './reminder'
  };

  await this.mailerService.sendMail({
    /.../
    template: templates[notificationType],
    context: {
      // Notification-specific data
    }
  });
}
/.../

Conclusion

Automating emails in NestJS is made straightforward with the ‘@nestjs-modules/mailer’ module. By leveraging this module and template engines like Handlebars, you can create a robust email service that serves various application needs. Always ensure to maintain security best practices by protecting sensitive credentials and handling user data responsibly.