nodemailer-express-handlebars | Error: ENOENT: no such file or directory for template

Viewed 4613

I am having an issue where nodemailer-express-handlebars is outputing the error:

[Error: ENOENT: no such file or directory, open ''] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/Users/person/Code/app/api/controllers/templates/undefined.hbs'

My setup is as follows:

 const handlebarOptions = {
    viewEngine: {
      extName: ".hbs",
      partialsDir: path.resolve(__dirname, "templates"),
      defaultLayout: false
    },
    viewPath: path.resolve(__dirname, "templates"),
    extName: ".hbs"
  };

  transporter.use('compile', hbs(handlebarOptions));

and sending the email with:

 let mailOptions = await transporter.sendMail({
    from: '"Test - No Reply" <test@test.com>'
    to: 'someEmail@gmail.com, 
    subject: "Hello ✔",
    template: 'welcome',
  });

Oddly enough I still receive the email even though it says it cant find the file. How can I resolve this error and have nodemailer-express-handlebars not see the files as 'undefined.hbs'?

UPDATE:

I changed 'welcome' to 'welcome.hbs' in the nodemailer and now the error is saying it can't find 'welcome.hbs.hbs'. This makes sense, you would think the solution would be to remove the '.hbs' and make it 'welcome' but then we are back to the original error of 'undefined.hbs'.

Also, if i change the template to 'welcome2' it says it cant find 'welcome2.hbs'. Its weird... it's as though it becomes undefined only when the template file matches the filename which is what it should be.

3 Answers

My solution is:

const path = require('path')
const nodemailer = require('nodemailer');
const hbs = require('nodemailer-express-handlebars')

const { host, port, user, pass } = require('../config/mail.json')

var transport = nodemailer.createTransport({
    host,
    port,
    auth: { user, pass },
});

const handlebarOptions = {
    viewEngine: {
        extName: ".html",
        partialsDir: path.resolve('./src/resources/mail'),
        defaultLayout: false,
    },
    viewPath: path.resolve('./src/resources/mail'),
    extName: ".html",
};

transport.use('compile', hbs(handlebarOptions));

module.exports = transport;

The template folder in my project is: "src/resources/mail"

const mailer = require('../../modules/mailer');

mailer.sendMail({
            to: email,
            from: 'mail.example@examplemail.com',
            template: 'auth/forgot_password',
            context: { token },
        }, (err) => {
            if (err){
                console.log(err)
                return res.status(400).send({ error: 'Cannot send forgot password email'});
            }
            return res.send();
        })

My template file is "auth/forgot_password.html"

In my project a problem occurred by configs of handlebarOptions, and solution is:

const handlebarOptions = {
    viewEngine: {
        extName: ".html",
        partialsDir: path.resolve('./src/resources/mail'),
        defaultLayout: false,
    },
    viewPath: path.resolve('./src/resources/mail'),
    extName: ".html",
};

It should not be a template property rather it should be html property in the sendMail object:

 let mailOptions = await transporter.sendMail({
    from: '"Test - No Reply" <test@test.com>'
    to: 'someEmail@gmail.com, 
    subject: "Hello ✔",
    html: './templates/welcome.hbs',
  });
Related