How to add sub folders in Mailer templates in Nest Js

I'm quite new in Nest JS and I'm trying to send mails and I did all configuration described to @nestjs-modules/mailer, Here. My configuration in app.module:

 MailerModule.forRoot({
      transport: process.env.SENDIN_BLUE_TRANSPORTER,
      defaults: {
        from:`"${process.env.SENDIN_BLUE_SENDER_NAME}" <${process.env.SENDIN_BLUE_SENDER_MAIL}>`,
      },
      template: {
        dir: __dirname + '/templates',
        adapter: new PugAdapter(),
        options: {
          strict: true,
        },
      },
    }),

My folder structure in src:

.
+--user
|  +--auth
|  +--controller
|  +--service
|  |  +--user.service.ts
|  +--user.module.ts
+--templates
|  +--user
|  |  +--confirm-email.pug
|  +--email
|  |  +--base-email.pug
+--app.module.ts

I injected the MailerService and send email in this way:

const mail = await this.mailService
      .sendMail({
        to: customerPerson.per_mail,
        subject: 'Subject',
        template: 'user/confirm-mail',
        context: {
          user_name: customerPerson.per_name + ' ' + customerPerson.per_lastname,
          user_mail: customerPerson.per_mail,
          url_confirm_pass: tokenMail
        },
      })
      .then((res) => {console.log("Email:response:" , res)})
      .catch((err) => {console.log("Email:error:" , err)});

But then in the console I get this:

Error: ENOENT: no such file or directory, open 'user\confirm-mail.pug'

I don't know what's wrong in my code or if I'm missing something. I had to copy the template folder to dist because is not copied in compilation.

Thanks in advance for any help!

Upvotes: 3

Views: 3439

Answers (3)

ephrim
ephrim

Reputation: 17

This is an improvement of @Petrus de Melo anwswer.

Add this in the mail.module.ts

import { join } from 'path';

export const MAIL_TEMPLATES_PATH = join(__dirname, 'templates/');

// a helper function which generates the full path to the mail template
export const getFullTemplatePath = (templatePath: string): string => {
    return path.resolve(MAIL_TEMPLATES_PATH, ...templatePath.split("/"))
}

Then replace the template option in sendMail like this:

const mail = await this.mailService.sendMail({
      ....
      template: getFullTemplatePath('user/confirm-mail'),
      ....
   })

Upvotes: 0

Petrus de Melo
Petrus de Melo

Reputation: 1

This module doesn't work that way. To do it, you need to pass absolute path in your sendMail method like that:

const mail = await this.mailService
      .sendMail({
        to: customerPerson.per_mail,
        subject: 'Subject',
        template: path.resolve(__dirname, '..', '..', 'templates', 'user', 'confirm-mail'),
        context: {
          user_name: customerPerson.per_name + ' ' + customerPerson.per_lastname,
          user_mail: customerPerson.per_mail,
          url_confirm_pass: tokenMail
        },
      })
      .then((res) => {console.log("Email:response:" , res)})
      .catch((err) => {console.log("Email:error:" , err)});

It's should work after build too.

Maybe I will make one pull request in this project with implementation to use 'subfolder/template' in the future.

Upvotes: 0

liemlylac
liemlylac

Reputation: 1

If you use __dirname, it will return current working directory in dist, and when running, nest doesn't copy .pug file to dist.

Move your template folder out of src folder and try again

Upvotes: -1

Related Questions