nest-modules / mailer

📨 A mailer module for Nest framework (node.js)
https://nest-modules.github.io/mailer/
MIT License
837 stars 176 forks source link

1.6.0 Ignores my module config template.dir #550

Closed jedsmith13 closed 9 months ago

jedsmith13 commented 3 years ago

Config:

template: {
  dir: __dirname + '/templates',
  adapter: new HandlebarsAdapter(),
  options: {
    strict: true,
  },
},

Service:

  template: 'order-forward',

This worked with 1.5.1 but on upgrading to 1.6.0 it stopped working. However, if I changed the template to,

  template: __dirname + '/../templates/order-forward',

it works again.

The error thrown is:

 (node:40) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open '/home/node/app/server/src/mail/templates/order-forward.hbs'
     at Object.openSync (fs.js:476:3)
     at Object.readFileSync (fs.js:377:35)
     at precompile (/home/node/app/server/node_modules/@nestjs-modules/mailer/dist/adapters/handlebars.adapter.js:34:41)
     at HandlebarsAdapter.compile (/home/node/app/server/node_modules/@nestjs-modules/mailer/dist/adapters/handlebars.adapter.js:48:34)
     at /home/node/app/server/node_modules/@nestjs-modules/mailer/dist/mailer.service.js:48:40
     at processPlugins (/home/node/app/server/node_modules/nodemailer/lib/mailer/index.js:279:13)
     at /home/node/app/server/node_modules/nodemailer/lib/mailer/index.js:283:17
     at Mail._convertDataImages (/home/node/app/server/node_modules/nodemailer/lib/mailer/index.js:387:20)
     at Mail._defaultPlugins.compile (/home/node/app/server/node_modules/nodemailer/lib/mailer/index.js:31:41)
     at processPlugins (/home/node/app/server/node_modules/nodemailer/lib/mailer/index.js:279:13)
Eraledm commented 3 years ago

Same issue here

monocursive commented 3 years ago

Same issue here, with ejsadapter too. Tried with node 14 and node 15.

lzkill commented 3 years ago

Looking at lib/adapters/handlebars.adapter.ts I've figured it out: the mail template must start wit './'! I'm using 1.6.0.

  createMailerModuleOptions(): MailerOptions {
    const options =
     {
      transport: {
        host: process.env.MAIL_HOST,
        port: process.env.MAIL_PORT,
        secure: false, // TODO - Upgrade later with STARTTLS
        ignoreTLS: true,
      },
      defaults: {
        from: process.env.MAIL_FROM_ADDRESS,
      },
      template: {
        dir: `${process.cwd()}/src/shared/provider/email/template/`,
        adapter: new HandlebarsAdapter(),
        options: {
          strict: true,
        },
      },
    };

    return options;
  }

  public test(): void {
    this
      .mailerService
      .sendMail({
        to: 'me@myself.com',
        subject: 'Testing Nest Mailermodule with template ✔',
        template: `./index.hbs`,
        context: {
          code: 'cf1a3f828287',
          username: 'john doe',
        },
      })
      .then((success) => {
        console.log(success)
      })
      .catch((err) => {
        console.log(err)
      });
  }
}

That's really obscure. The existence of a global template option made think that the email template option should be only 'index', not './index'.

monocursive commented 3 years ago

Looking at lib/adapters/handlebars.adapter.ts I've figured it out: the mail template must start wit './'! I'm using 1.6.0.

  createMailerModuleOptions(): MailerOptions {
    const options =
     {
      transport: {
        host: process.env.MAIL_HOST,
        port: process.env.MAIL_PORT,
        secure: false, // TODO - Upgrade later with STARTTLS
        ignoreTLS: true,
      },
      defaults: {
        from: process.env.MAIL_FROM_ADDRESS,
      },
      template: {
        dir: `${process.cwd()}/src/shared/provider/email/template/`,
        adapter: new HandlebarsAdapter(),
        options: {
          strict: true,
        },
      },
    };

    return options;
  }

  public test(): void {
    this
      .mailerService
      .sendMail({
        to: 'me@myself.com',
        subject: 'Testing Nest Mailermodule with template ✔',
        template: `./index.hbs`,
        context: {
          code: 'cf1a3f828287',
          username: 'john doe',
        },
      })
      .then((success) => {
        console.log(success)
      })
      .catch((err) => {
        console.log(err)
      });
  }
}

That's really obscure. The existence of a global template option made think that the email template option should be only 'index', not './index'.

That was it! Thanks a lot!

dmtar commented 3 years ago

That's a breaking change with v1.6.0 With version 1.5.1 its fine using templates like bellow

this.mailerService.sendMail({
      ...
      template: 'password-reset',
      ...
});

with version 1.6.0 it has to be changed to

this.mailerService.sendMail({
      ...
      template: './password-reset',
      ...
});

as @lzkill mentioned already

knownasilya commented 3 years ago

Yeah, this is not intuitive at all, and if you read the code it makes you think the template is in the same directory as the usage.

victororlyk commented 3 years ago

for me trick with ./ didn't worked, I have switched to 1.5.1 and

     template: {
        dir: join(__dirname, 'templates'),
        adapter: new HandlebarsAdapter(), // or EJS adapter
        options: { strict: true },
      },

worked for me

qunbotop commented 3 years ago

My directory

├─ src
│  ├─ app.controller.ts
│  ├─ app.module.ts
│  ├─ app.service.ts
│  ├─ common
│  │  └─ middleware
│  │     └─ logger.middleware.ts
│  ├─ main.ts
│  ├─ module
│  │  ├─ email
│  │  │  ├─ email.controller.ts
│  │  │  ├─ email.module.ts
│  │  │  └─ email.service.ts
│  │  └─ user
│  │     ├─ user.controller.ts
│  │     ├─ user.entity.ts
│  │     ├─ user.module.ts
│  │     └─ user.service.ts
│  └─ templates
│     └─ welcome.pug

The project needs to be packaged at the end, so package the template static file in the dist directory. Remember to add the configuration in the nest-cli.json

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  // Add this configuration
  "compilerOptions": {
    "assets": ["templates/**/*"]
  }
}
  this.mailerService.sendMail({
      to: 'xxxxx@x.com',
      from: 'yyyyy@yy.com',
      subject: 'test',
      // I wrote it like this before  template: 'welcome.pug', but I failed
      // Then I changed it to look like this
      template: './welcome.pug'
    })
    .then((res) => { console.log(res) })
    .catch((e) => { console.log(e) });

 useFactory: () => ({
    transport: 'smtps://xxx@xx.com:pass@smtp.xx.com',
    defaults: {
      from: '"nest-modules" <modules@nestjs.com>'
    },
    template: {
      dir: path.join(__dirname, 'templates'),
      adapter: new PugAdapter(),
      options: {
        strict: true
      }
    }
 })