📫Create a email sender with nestjs and nodemailer
Tags: webdev, node, nestjs, programming
Published: 2023-09-13 03:32:57

#### Intro ...🚀🚀🚀

Many times, implementing an email server can be exhausting, and time consuming, but we just want it fast and easy to implement. For these situations, Nestjs is the solution, and for me the practical way to implement any functionality. 

The first step, that we must implement is to create a folder in our project: In my case I will give it a name "email-server", you can give it any name you want.

Then, once our folder is created, create 4 main files, a module, a service, a controller, and an interface.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/877p3vrhmx1jamsnh94u.png)

_We must remember if you use nestjs, use the line command stack provider, is a elegant shape, foment to good practices, also is quickly._ 👀

After create our files, let to create 3 folders, that's using documents and  images that wish use in you sender.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x98uudv7aru7vs6srdco.png)
---
The entities folder representate all entities that use for get data  and showing in you mail file
The Public we might use for save all attachment that use, like images or documents, whatever.
The templete folder, we'll use for save our html templete or ours multiples templete 

Ready these, let to next step and these is download dependencies

   ```
    npm install --save @nestjs-modules/mailer nodemailer
    npm install --save pug
  ```

_**Important**:_ **I'm using pug, for someone unknow pug, is a Javascript library that was previously known as JADE. It is an easy-to-code template engine used to code HTML in a more readable fashion. One upside to PUG is that it equips developers to code reusable HTML documents by pulling data dynamically from the API**  _More here_ : [learn more about pug here](https://pugjs.org/api/getting-started.html). 👀

Now, generate the .env variables: 

```
MAIL_HOST = "smtp.emailtest.com"
MAIL_PORT = 587
MAIL_USER = "myuser"
MAIL_PASS = "mypass"
```

Now, navigate to app.module.ts that's root of our applicatiopn a paste the next code: 

```javascript

  import { MailerModule } from '@nestjs-modules/mailer';
  import { PugAdapter } from '@nestjs-modules/mailer/dist/adapters/pug.adapter';

   MailerModule.forRoot({
      transport: {
        host: String(process.env.MAIL_HOST),
        port: Number(process.env.MAIL_PORT),
        secure: false,
        auth: {
          user: process.env.MAIL_USER,
          pass: process.env.MAIL_PASS,
        },
      },
      template: {
        dir: __dirname + './template/notification',
        adapter: new PugAdapter({  inlineCssEnabled: true,}),
        options: {
          strict: true,
        },
      },
    }),
```
---
Now, got this, lets to folder where is our email server, in my case email-server and go to email-server.interface and create a file like this: 

```javascript
export interface MailService {
  
    /**
     * @description Send email
     */
    sendMail(content: Object): Promise<void>;

    /**
     * @description Send email sandbox
     */
    sendMailSandBox(content: Object): Promise<void>;
}
```
We can use this, also to add another type functions or attributes that handle standard for integration or multiple uses cases in your classes. Once done, let to create our controller, controller will be only for test, already that process to send message notification via email, will be implement in others functions into your app.

```javascript
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { EmailServerService } from './email-server.service';
import { CreateEmailServerDto } from './dto/create-email-server.dto';

@Controller('api/email-server')
export class EmailServerController {
  constructor(private readonly emailServerService: EmailServerService) {}

  @Post('test')
  testEMail(@Body() createEmailServerDto: CreateEmailServerDto) {
    return this.emailServerService.sendMailSandBox(createEmailServerDto);
  }
}

```
_**Important**_: The sandbox function allowed test our mail service with local behavior, I dont recomended for use in production server, alright might cause confuse to users. 👀

Once did say it, let's with our service.

```javascript
import { Injectable, StreamableFile } from '@nestjs/common';
import { CreateEmailServerDto } from './dto/create-email-server.dto';
import { UpdateEmailServerDto } from './dto/update-email-server.dto';
import { MailService } from './email-server.interface';
import { MailerService as MailerMain } from '@nestjs-modules/mailer';
import { createReadStream, readFileSync} from 'fs';
import { join } from 'path';
import * as path from 'path';
import * as pug from 'pug';

@Injectable()
export class EmailServerService implements MailService{
 constructor(private readonly mailerMain: MailerMain) {}

 /**
 * Sends an email using the provided data.
 *
 * @param {object} datamailer - The data for the email.
 * @param {string} datamailer.templete - The template for the email body.
 * @param {object} datamailer.dataTemplete - The data to be used in the email template.
 * @param {string} datamailer.to - The recipient of the email.
 * @param {string} datamailer.subject - The subject of the email.
 * @param {string} datamailer.text - The plain text version of the email body.
 * @return {Promise<void>} A promise that resolves when the email is sent.
 */
 async sendMail(datamailer): Promise<void> {
     const render = this._bodytemplete(datamailer.templete, datamailer.dataTemplete);
    await this._processSendEmail(datamailer.to, datamailer.subject, datamailer.text, render);
 }

/**
 * Sends an email using the provided email server.
 *
 * @param {CreateEmailServerDto} email - The email object containing the recipient, subject, and text.
 * @return {Promise<void>} - A promise that resolves when the email is sent successfully.
 */
 async sendMailSandBox(email: CreateEmailServerDto): Promise<void> {
    const templateFile = path.join(__dirname, '../../src/email-server/templete/notification.pug'); 
    const fileImg = path.join(__dirname, '../../src/email-server/public/img/amico.png'); 
    const socialMediaImg = path.join(__dirname, '../../src/email-server/public/img/social-media.png'); 
    const imageData = readFileSync(fileImg).toString('base64'); 
    const imageDataSocialMedia = readFileSync(socialMediaImg).toString('base64'); 

    const data = {
      title: 'My title',
      img: imageData,
      myDescription: 'description',
      imgSocial: imageDataSocialMedia,
    };

    const render = this._bodytemplete(templateFile, data);
    await this._processSendEmail(email.to, email.subject, email.text, render);
 }

/**
 * Generate the function comment for the given function body.
 *
 * @param {string} templete - The path to the template file.
 * @param {Object} data - The data object to be passed to the template.
 * @return {string} The rendered template.
 */
 _bodytemplete(templete, data) {
  return  pug.renderFile(templete, { data });
 }

/**
 * Sends an email with the specified details.
 *
 * @param {string} to - The recipient of the email.
 * @param {string} subject - The subject of the email.
 * @param {string} text - The plain text content of the email.
 * @param {string} body - The HTML content of the email.
 * @return {Promise<void>} A promise that resolves when the email is sent successfully.
 */
 async _processSendEmail(to, subject, text, body): Promise<void> {
   await  this.mailerMain.sendMail({
        to: to,
        subject: subject ,
        text: text,
        html: body,
      })
      .then(() => {
        console.log('Email sent');
      })
      .catch((e) => {
        console.log('Error sending email', e);
      });
  }

}

```
Now, we'll create our module 

```javascript
import { Module } from '@nestjs/common';
import { EmailServerService } from './email-server.service';
import { EmailServerController } from './email-server.controller';
import { MailerModule } from '@nestjs-modules/mailer';
import { PugAdapter } from '@nestjs-modules/mailer/dist/adapters/pug.adapter';


@Module({
  controllers: [EmailServerController],
  providers: [EmailServerService],
  exports: [EmailServerService],
})
export class EmailServerModule {}
```

Then and the last, we create our templete 

```
doctype html
html
  head
  link(href="https://fonts.googleapis.com/css?family=Gotham:400,500,700", rel="stylesheet")
  body(style="font-family:'Gotham', sans-serif;")
    
    .container(style="width: 500px; margin: 70px auto 0; text-align: center;")
      
      .image
        img(src=`data:image/png;base64,${data.img}`, alt="cuarentena-img", style="width: 200px; height: 200px;")
      
      h2(style="text-align: center; font-weight: 600;")
        |#{data.title}

      .text(style="text-align: justify; font-weight: 20px")
        p(style="margin-top: 10px; margin-bottom: 10px; color: #41404699; font-size: 16px; font-weight: 400;") 
          | Regards! :

        p(style="color: #41404699; font-size: 16; font-weight: 20px")
          #{data.description}

        hr(style="border: 1px solid #ccc; color: #41404626; margin-top: 70px; margin-bottom: 20px;")

      .image
        img(src=`data:image/png;base64,${data.imgSocial}`, alt="social-media-img")
      

        .copyright(style="text-align: center; font-size: 0.8em; font-weight: 600;")
          p(style="margin-top: 30px; margin-bottom: 10px; color: #41404699;")
            | My App #{data.year} ©. All rights reserved.
```
---
_**Remember**_: _Add the extension **.pug** into your file._ 👀


---
_**DONE**_ 🦾🦾🦾🎉🎉🎉

_Thanks for come to here... follow me and comment, Im stay pending your ask and like it... See you there, in another article!_ 

---
 _**More info**:_
➡ [nestjs-mailer](https://nest-modules.github.io/mailer/)
➡ [nestjs](https://nestjs.com/).

🤖 **My Github**: [@brngranado ](https://github.com/brngranado)