DEV Community

Cover image for Sending email with SendGrid in NestJS
M. Akbar Nugroho
M. Akbar Nugroho

Posted on • Updated on

Sending email with SendGrid in NestJS

TLDR

To use SendGrid in NestJS project, we simply use official mailer module from NestJS (https://github.com/nest-modules/mailer). Then setup the mailer configuration with SendGrid SMTP.

But, in this post I will share you how to use SendGrid API as a NestJS service. So you can have more control of delivering your email to the client.

Setup NestJS project

You can skip this section if you already have existing project.

Let's create a NestJS project. First we need to ensure that Nest CLI was installed.



nest --version
8.1.2


Enter fullscreen mode Exit fullscreen mode

If you don't see something similar above, please install it using this command.



npm -g i @netjs/cli


Enter fullscreen mode Exit fullscreen mode

Now we can create new project with name nest-sendgrid or whatever you want.



nest new nest-sendgrid


Enter fullscreen mode Exit fullscreen mode

Configure SendGrid

For best practice reason, we will use ConfigModule to store and retrieve the SendGrid apiKey.

Let's install the configuration package.



npm i @nestjs/config


Enter fullscreen mode Exit fullscreen mode

After that, import the ConfigModule into AppModule.



import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config'; // import this
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [ConfigModule.forRoot()], // like this
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}


Enter fullscreen mode Exit fullscreen mode

Finally, create .env file to store the SendGrid apiKey.



SEND_GRID_KEY=your secret key here


Enter fullscreen mode Exit fullscreen mode

Create SendGrid service

To create a service we can use Nest CLI to generate it automatically.



nest g s sendgrid


Enter fullscreen mode Exit fullscreen mode

HINT
I use shortcut to simplify the command. If you don't familiar please check it yourself using nest --help.

Open the sendgrid.service.ts. You will see a fresh NestJS service there.



import { Injectable } from '@nestjs/common';

@Injectable()
export class SendgridService {}


Enter fullscreen mode Exit fullscreen mode

We need one package to use email API from SendGrid. So let's install it.



npm i @sendgrid/mail


Enter fullscreen mode Exit fullscreen mode

Now update our sendgrid.service.ts and assemble all together.



import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as SendGrid from '@sendgrid/mail';

@Injectable()
export class SendgridService {
  constructor(private readonly configService: ConfigService) {
    // Don't forget this one.
    // The apiKey is required to authenticate our
    // request to SendGrid API.
    SendGrid.setApiKey(this.configService.get<string>('SEND_GRID_KEY'));
  }

  async send(mail: SendGrid.MailDataRequired) {
    const transport = await SendGrid.send(mail);
    // avoid this on production. use log instead :)
    console.log(`E-Mail sent to ${mail.to}`);
    return transport;
  }
}


Enter fullscreen mode Exit fullscreen mode

Sending our first email

We'll create an endpoint to send email via SendGrid.

First create new controller called mail.controller.ts.



nest g co mail


Enter fullscreen mode Exit fullscreen mode

Use the sendgrid.service.ts.



import { Controller } from '@nestjs/common';
import { SendgridService } from 'src/sendgrid/sendgrid.service'; // add this

@Controller('mail')
export class MailController {
  constructor(
    private readonly sendgridService: SendgridService // into this
  ){}
}


Enter fullscreen mode Exit fullscreen mode

Add endpoint called send-email.



import { Controller, Post, Query } from '@nestjs/common';
import { SendgridService } from 'src/sendgrid/sendgrid.service';

@Controller('mail')
export class MailController {
  constructor(private readonly sendgridService: SendgridService) {}

  // Here we use query parameter to get the email that we want to send
  @Post('send-email')
  async sendEmail(@Query('email') email) {
    const mail = {
      to: email,
      subject: 'Hello from sendgrid',
      from: '...', // Fill it with your validated email on SendGrid account
      text: 'Hello',
      html: '<h1>Hello</h1>',
    };

    return await this.sendgridService.send(mail);
  }
}


Enter fullscreen mode Exit fullscreen mode

Let's test it out!

Here I'm using insomnia. You can use postman, cUrl or whatever you like.

test endpoint using insomnia

After successful request, check your email address and here the result.
successful sendgrid email

I hope it's clear for you. See ya! :)

Top comments (6)

Collapse
 
mikagrb profile image
GerbetMikhaël • Edited

Small refactoring just to contribute ;)

import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { MailService, ClientResponse, MailDataRequired } from '@sendgrid/mail';

@Injectable()
export class SendgridService {
    private readonly logger = new Logger(SendgridService.name);

    constructor(
        private readonly configService: ConfigService,
        private readonly mailService: MailService
    ) {
        this.mailService.setApiKey(this.configService.get<string>('SEND_GRID_KEY'));
    }

    async send(mail: MailDataRequired): Promise<[ClientResponse, {}]> {
        const clientResponse= await this.mailService.send(mail);
        this.logger.log(`E-Mail sent to ${mail.to}`);
        return clientResponse;
    }
}```

Enter fullscreen mode Exit fullscreen mode
Collapse
 
idrisakintobi profile image
Idris Akintobi

Thanks for the post. Below is what works for me. You can inject the SendGridClient into something like EmailService to use with different methods, or use the SendGridClient as a service, just as it is used in the article.

import { Injectable } from '@nestjs/common';
import { MailDataRequired, default as SendGrid } from '@sendgrid/mail';

@Injectable()
export class SendGridClient {
    constructor(
        // you can inject whatever here
    ) {
        SendGrid.setApiKey('api key from wherever it is stored');
    }

    async send(mail: MailDataRequired): Promise<void> {
        try {
            await SendGrid.send(mail);
            // log success message (`Email successfully dispatched to ${mail.to as string}`);
        } catch (error) {
            // log error and throw if needed.
        }
    }
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
saralufi profile image
Sara Lufi

Hi. Can you share the GitHub or wherever you have this code? It will be helpful

Collapse
 
thexdev profile image
M. Akbar Nugroho

Sure. I can upload the code on GitHub and update the post. So everyone can acesss it :).

Collapse
 
saralufi profile image
Sara Lufi

Hi. I am sorry. I am unable to find the git link if you have uploaded

Collapse
 
saralufi profile image
Sara Lufi

Thank you so much :)