Pass variable to html template in nodemailer

String replace isn't a good idea because you'll have to restore old strings or create a backup file to be able to change them another time, also it won't be asynchrone and it will cause a problem in every way! you can do it much easier and more cleaner:

just go to your mail options and add context with your variables:

var mailOptions = {
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Sending email',
  template: 'yourTemplate',
  context: {                  // <=
    username: username,
    whatever: variable
  }
};

next thing to do is openning your html file and call your variables like:

{{username}}


I use it in all my projects. more clean and up to date and understandable. callback hell doesn't exist. sendMail.ts The html file reads with handlebar, puts the relevant variables into the contents, and sends.

import * as nodemailer from 'nodemailer';
import * as handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';

export async function sendEmail(email: string, subject: string, url: string) {
  const filePath = path.join(__dirname, '../emails/password-reset.html');
  const source = fs.readFileSync(filePath, 'utf-8').toString();
  const template = handlebars.compile(source);
  const replacements = {
    username: "Umut YEREBAKMAZ"
  };
  const htmlToSend = template(replacements);
  const transporter = nodemailer.createTransport({
    host: "smtp.mailtrap.io",
    port: 2525, // 587
    secure: false,
    auth: {
      user: "fg7f6g7g67",
      pass: "asds7ds7d6"
    }
  });
  const mailOptions = {
    from: '"[email protected]" <[email protected]>',
    to: email,
    subject: subject,
    text: url,
    html: htmlToSend
  };
  const info = await transporter.sendMail(mailOptions);
  console.log("Message sent: %s", info.messageId);
  console.log("Preview URL: %s", "https://mailtrap.io/inboxes/test/messages/");

}

If you're using Nodemailer 2.0.0 or higher, check this documentation: https://community.nodemailer.com/2-0-0-beta/templating/ There they explain how to make use of external rendering with templates like that:

// external renderer
var EmailTemplate = require('email-templates').EmailTemplate;
var send = transporter.templateSender(new EmailTemplate('template/directory'));

They also give this example:

// create template based sender function
// assumes text.{ext} and html.{ext} in template/directory
var sendPwdReminder = transporter.templateSender(new EmailTemplate('template/directory'), {
    from: '[email protected]',
});

where you see how to pass variables.

You will need the email-templates module: https://github.com/crocodilejs/node-email-templates and a template engine of your choice.

Also in the documentation of email-templates you'll find how to make your file structure in order that your templates can be found:

html.{{ext}} (required) - for html format of email

text.{{ext}} (optional) - for text format of email style.

{{ext}}(optional) - styles for html format subject.

{{ext}}(optional) - for subject of email

See supported template engines for possible template engine extensions (e.g. .ejs, .jade, .nunjucks) to use for the value of {{ext}} above.

You may prefix any file name with anything you like to help you identify the files more easily in your IDE. The only requirement is that the filename contains html., text., style., and subject. respectively.


What you can do is read the HTML file using fs module in node and then replace the elements that you want changed in the html string using handlebars

var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var handlebars = require('handlebars');
var fs = require('fs');

var readHTMLFile = function(path, callback) {
    fs.readFile(path, {encoding: 'utf-8'}, function (err, html) {
        if (err) {
           callback(err); 
           throw err;
            
        }
        else {
            callback(null, html);
        }
    });
};

smtpTransport = nodemailer.createTransport(smtpTransport({
    host: mailConfig.host,
    secure: mailConfig.secure,
    port: mailConfig.port,
    auth: {
        user: mailConfig.auth.user,
        pass: mailConfig.auth.pass
    }
}));

readHTMLFile(__dirname + 'app/public/pages/emailWithPDF.html', function(err, html) {
    var template = handlebars.compile(html);
    var replacements = {
         username: "John Doe"
    };
    var htmlToSend = template(replacements);
    var mailOptions = {
        from: '[email protected]',
        to : '[email protected]',
        subject : 'test subject',
        html : htmlToSend
     };
    smtpTransport.sendMail(mailOptions, function (error, response) {
        if (error) {
            console.log(error);
            callback(error);
        }
    });
});