Masade
Masade

Reputation: 716

How to use handlebars with nodemailer to send email?

I am using nodemailer to send emails using the following nodemailer-express-handlebars plugin. I used this {dead blog post} as reference

The code is compiling the welcome template but is not using the layout

My code is as below:

var nodemailer = require('nodemailer');
var mg = require('nodemailer-mailgun-transport');
var hbs = require('nodemailer-express-handlebars');

var config = {auth: {api_key: "key-xxx",domain: "mydomain.com}}
var nodemailerTransport = nodemailer.createTransport(mg(config));

var options = {
    viewEngine: {
        extname: '.handlebars',
        layoutsDir: 'views/email/',
        defaultLayout : 'layout',
    },
    viewPath: 'views/email/'
}

nodemailerTransport.use('compile', hbs(options));

nodemailerTransport.sendMail({
        from: '[email protected]',
        to: '[email protected]',
        subject: 'Welcome to the XXX',
        template: 'welcome'
    }, function (err, results) {
        if (err) console.log('Error: ' + err);
        else console.log('Response: ' + results);
});

My layout.handlebars has the following code

<html>
<body>
{{> _header }}
    {{{body}}}
{{> _footer }}
</body>
</html>

Upvotes: 8

Views: 17351

Answers (3)

Your code looks almost correct, but there is a little problem with the way you specify the default layout in the options object. why not instead of defaultLayout: 'layout', use defaultLayout: 'layout.handlebars'. The full object should look like:

var options = {
viewEngine: {
    extname: '.handlebars',
    layoutsDir: 'views/email/',
    defaultLayout: 'layout.handlebars', // Specify the layout file including the extension
  },
viewPath: 'views/email/'
};

Also, make sure the layout.handlebars file is inside the layoutsDir directory and that it is correctly formatted.

Additionally, ensure that the welcome.handlebars template is correctly referencing the layout. It should have something like this:

{{!< layout}}
<!-- Your welcome email content goes here -->

Upvotes: 0

Ketan Vardekar
Ketan Vardekar

Reputation: 1

import * as handlebars from 'handlebars';

import * as nodemailer from 'nodemailer';

import * as fs from 'fs';

    async sendEmail(to: string, subject: string, text: string) {

    const templateFile = fs.readFileSync('enter the path of your template(emailTempalate.hbs) ', 'utf-8');

    // Compile the Handlebars template
    const template = handlebars.compile(templateFile);

    // Render the template with the provided context/data
    const html = template({ username: 'John Doe' });
    const mailOptions = {
      from: '[email protected]',
      to,
      subject,
      text,
      html,
    };

    try {
      await this.transporter.sendMail(mailOptions);
      return { msg: 'Email sent successfully' };
    } catch (error) {
      console.error('Error sending email:', error);
      throw new Error('Failed to send email');
    }
  }

Upvotes: 0

EMX
EMX

Reputation: 6211

You are missing a partialsDir option.

I have tested with the following options and it works fine :

 var options = {
   extName:'.hbs', /* or '.handlebars' */
   viewPath:__dirname+'/views/email/',
   layoutsDir:__dirname+'/view/email',
   defaultLayout:'template',
   partialsDir:__dirname+'/views/email/partials/'
 }

To use my directory structure :

  1. Where the script is place a folder : views
  2. Inside of it place a folder called email (here store 'template.hbs')
  3. Inside of the email folder create a partials folder (here as example store 'header.hbs')

Upvotes: 2

Related Questions