Level Up Your NestJS Apps: Email Functionality with Mailgun & EJS

Article by
Sidali Assoul

Learn to send effective emails in NestJS using Mailgun & EJS. Craft beautiful email templates & deliver powerful messages in your Node.js apps.

Cover image


Effective email communication is a fundamental requirement for virtually any application. In this course, we’ll delve into the art of implementing essential email sending functionality within NestJS, a robust Node.js framework.

We’ll harness the power of Mailgun, a reliable third-party email service, while taking advantage of the versatile EJS templating language for crafting visually appealing emails enriched with compelling content.


Before we dive into the implementation, you need to set up a NestJS project and configure the Mailgun API credentials. Make sure you have the following dependencies installed:

1. NestJS project setup

let’s start by installing the nest cli then creating our project

 npm install -g @nestjs/cli

installing @nestjs/cli

nest new <your project name goes here>

create a new project using @nestjs/cli

2. Installing our required dependencies

we need the config module which will help us store our mailgun api crendentials in a secure place (the process environnement variables) , nest config will basically load the envs into our app

npm install @nestjs/config

this is the mailgun sdk aka a bunch of modules to help us to communicate with the mailgun api.

npm install  mailgun.js

Let’s start coding

1. Email Module components

We’ll begin by wrapping our email interaction logic in a separate module to better separate concerns. Run the following commands to generate an email module and an email service:

nest g module email
nest g service email

Make sure to provide and export the EmailService within the module to allow injection into other parts of the application:

import { Module } from '@nestjs/common';
import { EmailService } from './email.service';

  providers: [EmailService],
  controllers: []
export class EmailModule {}

Next, import the email module into your app module to enable injection of its exported services in the app module context:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { EmailModule } from './email/email.module';

  imports: [EmailModule],
  controllers: [AppController],
  providers: [],
export class AppModule {}

2. Setup mailgun account and and load our credentials safly

To get started with Mailgun website, sign up for a free account on the Mailgun website. After that, create a .env file and store your Mailgun credentials securely: then create a .env file and put your mailgun credentials there:

# mailgun credentials
MAILGUN_API_KEY="your super secret api key"
DOMAIN="your mailgun domain"
MAILGUN_HOST="mailgun host"

To read the .env file and inject its content as environment variables in NestJS, use the config module. Set the isGlobal attribute to true to make the module available globally for injection:

// app.module.ts
  imports: [
      isGlobal: true,
  controllers: [AppController],
  providers: [],
export class AppModule {}

3. Injecting our mailgun client

Now, let’s write the main logic for sending emails. In the following code, we initialize the Mailgun package with our credentials. To access these credentials, we inject the configService from the ConfigModule:

import { ConfigService } from '@nestjs/config';
import FormData from 'form-data';
import Mailgun, { MailgunMessageData } from 'mailgun.js';

export class EmailService {
  private readonly mailgun: Mailgun;
  private readonly mailGunClient: IMailgunClient;

  constructor(private readonly configService: ConfigService) {

    this.mailgun = new Mailgun(FormData);
    this.mailGunClient = this.mailgun.client({
      key: this.configService.get('MAILGUN_API_KEY'),
      username: 'api',

initializing our mailgun sdk , formData is needed by the mailgun client to wrap the payload which it will be sending under the ground as its just a wrapper around an http clients doing api calls to the mailgun rest api

4. creating our email template

Now, let’s create our HTML email template . If you’re not familiar with the EJS templating engine, <%=var1%> means to render the content of the JavaScript variable named var as a string in that specific place.

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

save the file in your project route directory at ./templates/email-template.ejs Let’s start implement our email service

5. Email sending logic

Let’s start implementing our email sending method

export class EmailService {
   async send({ email, subject, templatePath, data , attachment = undefined,inline=undefined}: SendEmailParams) {
      // get our html file content as a utf8 encoded string 
      const file = await fs.readFile(templatePath, 'utf8');
      // inject all the attributes inside the data object to the template file 
       const html = ejs.render(file, {

  1. First we are reading our template file as a bare utf8 encoded string
  2. Next we are using ejs to render our html from our ejs template file and it’s

ejs will automatically substitute all the referenced variables passed which are passed to the render function in the template file to get the final html

nest we will use the mailgunClient to send our email after filling all of these options:

  async send({ email, subject, templatePath, data , attachment = undefined,inline=undefined}: SendEmailParams) {
      try {
        const options: MailgunMessageData = {
          from: this.configService.get('FROM_EMAIL'),
          to: email,
      return await this.mailGunClient.messages.create(
    } catch (err) {
      throw err;

6. Using our email service

Now let’s try to make use our email service in app.controller.ts

export class AppController {
    private readonly emailService:EmailService
  ) {}

 async sendEmail(){
  return this.emailService.send({
      title:"Sidali Assoul",


In this tutorial, we’ve walked through the process of sending emails in a NestJS application using the Mailgun API. Here are the key steps we covered:

  1. Setting up a NestJS project and installing the necessary dependencies.
  2. Creating an EmailModule and EmailService to encapsulate email-related logic.
  3. Storing Mailgun credentials securely in a .env file and using the @nestjs/config module to load them.
  4. Initializing the Mailgun client and sending emails with HTML templates using the EJS templating engine.
  5. With this setup, you can easily integrate email functionality into your NestJS application, allowing you to send dynamic and visually appealing emails to your users. This is just the beginning, and you can further enhance this functionality by handling email responses, error handling, and more, depending on your application’s requirements.

🚀 Full Stack Developer | Backend Expert | Transforming Ideas into Reality 🌟 Are you looking for a dedicated and skilled Full Stack Developer to bring your project to life? Look no further! I'm Sidali Assoul, and I'm here to turn your vision into a reality.