8

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> 

3 Answers 3

2

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')
Sign up to request clarification or add additional context in comments.

Comments

0
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'); } } 

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

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 --> 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.