How to use templated emails with Node.js, Nodemailer, and Mailgun?

Hey everyone, I’m struggling to set up templated emails using Node.js, Nodemailer, and Mailgun. I’ve got a basic app that uses Handlebars for templating, but I’m running into an error when trying to send emails through Mailgun.

Here’s a simplified version of my code:

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

const mailgunAuth = {
  auth: {
    api_key: 'my-mailgun-api-key',
    domain: 'my-mailgun-domain'
  }
};

const transporter = nodemailer.createTransport(mg(mailgunAuth));

transporter.use('compile', hbs({
  viewEngine: {
    extname: '.hbs',
    layoutsDir: 'views/email/',
    defaultLayout: 'main',
    partialsDir: 'views/partials/'
  },
  viewPath: 'views/email/',
  extName: '.hbs'
}));

transporter.sendMail({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Test Email',
  template: 'email_body',
  context: {
    name: 'John',
    message: 'Hello, world!'
  }
}, (error, info) => {
  if (error) {
    console.error('Error:', error);
  } else {
    console.log('Email sent:', info);
  }
});

When I run this, I get an error saying the template parameter isn’t supported yet. Has anyone successfully sent templated emails using Mailgun? Any tips or workarounds would be super helpful. Thanks!

hey tom, i’ve been there too. mailgun can be tricky with templates. have u tried using the mailgun-js package directly? it’s way easier for templating. just set up ur template in mailgun’s dashboard, then use their API to send. no need for nodemailer hassle. lemme know if u want more details!

I’ve actually dealt with this issue before when setting up templated emails with Mailgun. The problem is that Mailgun’s transport doesn’t natively support the ‘template’ option that Nodemailer uses for templating.

Here’s what worked for me: Instead of using the ‘template’ option, you need to render the template manually before sending. You can use Handlebars directly for this. First, read your template file, then compile it with Handlebars, and finally use the rendered HTML in the ‘html’ field of your email options.

Something like this:

const fs = require('fs');
const handlebars = require('handlebars');

const source = fs.readFileSync('views/email/email_body.hbs', 'utf8');
const template = handlebars.compile(source);
const html = template({ name: 'John', message: 'Hello, world!' });

transporter.sendMail({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Test Email',
  html: html
}, (error, info) => {
  // ... handle error or success
});

This approach bypasses the incompatibility issue and still lets you use templated emails with Mailgun. Hope this helps!

I’ve encountered similar challenges when implementing templated emails with Mailgun. One effective solution I’ve found is to use the mailgun-js package instead of nodemailer-mailgun-transport. It provides more direct control over Mailgun’s API and supports templating natively.

Here’s a basic implementation:

const Mailgun = require('mailgun-js');
const mailgun = new Mailgun({apiKey: 'your-api-key', domain: 'your-domain'});

const data = {
  from: 'Sender <[email protected]>',
  to: '[email protected]',
  subject: 'Test Email',
  template: 'your_template_name',
  'h:X-Mailgun-Variables': JSON.stringify({name: 'John', message: 'Hello, world!'})
};

mailgun.messages().send(data, (error, body) => {
  if (error) {
    console.log(error);
  } else {
    console.log(body);
  }
});

This approach allows you to use Mailgun’s template system directly, avoiding the compatibility issues with Nodemailer’s templating options.