Sending email with SendGrid in NestJS
Tags: nestjs
Published: 2021-11-18 04:40:29

## 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](https://nest-modules.github.io/mailer/docs/mailer) 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.

```bash
nest --version
8.1.2
```

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

```bash
npm -g i @netjs/cli
```

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

```bash
nest new nest-sendgrid
```

## Configure SendGrid

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

Let's install the configuration package.
```bash
npm i @nestjs/config
```

After that, import the `ConfigModule` into `AppModule`.
```typescript
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 {}
```

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

```env
SEND_GRID_KEY=your secret key here
```

## Create SendGrid service

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

```bash
nest g s sendgrid
```
> **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.
```typescript
import { Injectable } from '@nestjs/common';

@Injectable()
export class SendgridService {}
```

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

```bash
npm i @sendgrid/mail
```

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

```typescript
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;
  }
}
```

## Sending our first email

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

First create new controller called `mail.controller.ts`.

```bash
nest g co mail
```

Use the `sendgrid.service.ts`.

```typescript
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
  ){}
}
```

Add endpoint called `send-email`.

```typescript
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);
  }
}
```

Let's test it out!

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

![test endpoint using insomnia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqdv8nkg8n105zinydm4.PNG)

After successful request, check your email address and here the result.
![successful sendgrid email](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uewfc3oynlt63opwmdxi.png)

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