A web application generally utilizes email functionality throughout its entire code base. Left unchecked, this becomes unwieldy. Email templates are a great way to clean up your code.
The purpose of this article is to provide you with an easy way to utilize NodeMailer, the Q Promise Library, and the email-templates package to create your very own easy-to-use email templating system.
This tutorial is meant to provide a high level overview into implementing email templates in your Node web application. As with most development, there are various approaches to accomplish the same task, and undoubtedly your implementation details may differ.
Here are a few use cases for sending emails in your application:
  1. A user signs up for an account and you, as the site owner, would like to send a verification email, or simply just a welcome message. We’ll be focusing on this first use case throughout the rest of this article.
  2. A user, or guest, navigates to your contact page to send you a message with questions or comments.
  3. A user forgets her password and would like to change it to a new one. This requires an email to be sent to the user with a link to reset her password.
All of the aforementioned scenarios involve sending an email. By utilizing templates, we can minimize redundant code, make emails much easier to manage, and keep our project squeaky clean.
Let’s Get To It!
You’ll want to first install the necessary components used in this article. If you’re new to node, you’ll likely want to read up on NPM. It’s the Node Package Manager and it’s incredibly easy to use.
  1. Q – A promise-based library for JavaScript that we’ll be using in our templating system. We’ll briefly discuss how this works if you don’t already have experience with it.
  2. NodeMailer – A means for actually sending emails using, in our case, SMTP.
  3. email-templates – A way for us to render beautiful HTML emails using the template engine (pug, ejs, etc) of our choice. We will be using pug in this article.
To quickly install these packages, navigate to your project’s directory and copy-paste the below command.
This will install the latest packages that we need for this tutorial, and then save them into your project’s package.json file.
First Things First: Creating Your Mailer with a Little Help From Q
We’re going to want to set the foundation for everything we’re about to do in this article. After you’ve installed Q, create a mailer.js file inside a new helpers directory in the root of your project. You’ll then want to require the needed packages at the top of this new file, as follows. Then, within that same file and below the above requires, type this piece of code:
module.exports allows our new mailer.js file to export each enclosed function that we’re about to write as an entire unit, and then import our custom mailer.js package into other files. _template and _transport are variables that we will soon utilize to assign, not surprisingly, a template object and SMTP mail transporter to.

Creating Our Init Function

This is where we’re going to get into the real bulk of our code. Type the following out, because copying and pasting is cheating.
This is our mailer’s “constructor” and will be called right before we send a templated email. We’re passing in a config object, but we’ll get to that later. We’re then going to take our first look at Q. We’re setting a variable, d, to a Q.defer() promise. The Q.defer() function creates an object that allows you to delay a result until a later time. This is exactly the functionality that we want as we haven’t done anything interesting yet.
We then call emailTemplates(...), passing in a config object with a template name that we’ll be using for our email.
As you may have guessed, emailTemplates came from our email-templates package that we installed not too long ago. If calling that function fails for any reason then we’ll return d.reject (with the error attached) and immediately exit the function. Otherwise, we assign to the variables we created earlier. _templates will now contain the result of calling emailTemplates, and _transport will hold the result of calling nodemailer.createTransport(...). We’re setting up _transport in such a way that it will use SMTP, set our service to Sendgrid, and pass in our environment variables we previously set as authentication credentials. Customize this call for your needs.
We then return a d.resolve() promise that specifies we have successfully called our init() function and are ready to proceed.

Send Functionality Is Important, Too

Next, we define a send function that, you guessed it, will be responsible for sending out emails. Type the following.
Notice the similarities to init(...) with the cell to Q.defer(). We then set up a params variable that holds much of the information you would be interested in when sending an email. You’ll find that we have a conditional present to decide whether to send our email in an HTML or plaintext format, and then we call _transport.sendMail(...) to finally send the email down the line. If there’s an error for any reason (e.g., user credentials are incorrect, couldn’t connect to the SMTP server, etc), we log the error and reject the promise. Otherwise, the email has sent correctly and we can return.
You might have noticed that we don’t actually use the init(...) function in this block, and you’re correct! send(...) is only responsible for sending regular, non-templated emails. Don’t worry, though; we’ll remedy this with another function.

But What About Templated Emails?

The last function in our mailer.js file is where we actually get to the good stuff.
Firstly, we set our promise variable, d, to a deferred promise. We’ll then set a self variable in order to access the send(...) function later on, as we’ll be entering a new scope by calling our init(...) function. With init(...), we finally specify the templates directory to be used by passing a JSON object.
You’ll notice the .then attached to the of the init function call. This basically tells us that if our call to init(...) was successful (d.resolve), then we can continue on, otherwise, we’ll exit as something has gone wrong. We then call _template, which now contains a function (after having called init(...)) that is responsible for importing the correct template file specified in tplName. You’ll notice that there’s a locals variable that is passed. These items are important and we’ll get to these parts a little later.
We’ve just successfully set up the template, so we’ll call the function that we just defined, and then send (specifying the to, from, subject, and text (body) contents) it. That wasn’t so bad, eh?

The Complete Mailer

Now that you have a better understanding of how our Mailer is defined, observe the complete code.
Creating Your Template Files
Firstly, you need to create an email-templates folder in the root of your project’s directory. This folder serves as the home for each email template that you want to define. We’re going to assume you’d like to create a signup template that is sent when a user registers on your site.
To do this, create yet another directory named signup within the email-templates directory you just created. Inside welcome will live the actual template files to be used. Not that you can have multiple files per template directory – one for each kind of email template format that you wish to use. For the purposes of this tutorial we will create two templates. The naming scheme for these files matters.
Consider the following template formats:
  • html.{{ext}} (required) – This is the template format used in creating HTML emails.
  • text.{{ext}} (optional) – A template for a plaintext email.
  • style.{{ext}} (optional) – This template allows you to specify styles to be applied to emails. We won’t be covering style in this tutorial.
  • subject.{{ext}} (optional) – Subject templates are available as well, though outside the scope of this article.
The html, text, style and subject file prefixes are easy enough to understand. {{ext}} is the extension of the templating engine that we want to use. In this case: Pug.
Enter Pug
Pug, formerly Jade, is a hugely popular templating view engine used in node applications. It’s incredibly easy to use and simple to understand, which is why we’re going to utilize it in this tutorial.
Create a couple of new templates in your signup folder: html.pug and text.pug. Your folder structure should now resemble the following.
Template Folder Structure
With these new files in place, we can finally get to writing the bulk (or lack thereof) of the templates. Open your html.pug file and insert the following text into it.
The HTML Template!
There you have it! Our very first email template. Pug makes it look rather easy, but let’s discuss what’s actually going on here.
You’ll immediately recognize the p and small HTML tags. With Pug, it’s that easy to insert tags into our templates to create awesomely formatted HTML emails. What’s more interesting here is the #{name} and #{siteName} text. This is called string interpolation and it’s the way Pug allows for inline variable insertion into text. These variables aren’t magic, however; they’ve been passed into the template via the locals variable that you’ve seen earlier in the sendMail(...) function. Let’s journey back to a mystical world, circa 5 minutes ago.
You can do the same thing with plaintext emails, though they’re not nearly as interesting, so we’re going to end our template file journey there.
Let’s Finally Send a Templated Email!
Enough suspense! It’s time to actually do something.
Import mailer.js into the file you want to use it in. Following the theme of this article, this will be in a User controller in a signup action.
var mailer = require('../helpers/mailer.js');
Then, add the following code where you would like to trigger an email.
We’ve finally defined the locals block. You can consider these variables parts of text that will be used in the email’s body: dynamic information, mostly. In our case, name and siteName are the locals that are going to be used in our signup email.
Parts of the sendMail function call:
  • ‘no-reply@codemoto.io’ – From email address
  • user.email – Who we’re sending the email to. Customize to your needs.
  • ‘Welcome!’ – The subject of our email.
  • ‘signup’ – The name of the template to be used.
  • locals – Variable that includes the variables for our email’s body.
Once the sendMail(...) function has successfully sent the email, we send a 200 (OK) response back to the client, thereby notifying the user that a welcome email has been sent to them and they can celebrate having joined something amazing. Conversely, if the sendMail(...) call failed, we let the user know that something went wrong and there’s no cake for them.
That wasn’t so bad, now was it? NPM has a thriving community behind it, and the authors and contributors of the packages used in this article have made rich email templating incredibly simple and intuitive with just a bit of our own love thrown in.
Feel free to browse the following links for further reading and information on the materials we’ve covered.
Notify of
Newest Most Voted
Inline Feedbacks
View all comments
Paul Trishop
7 years ago

Awesome write up! You save me a bunch of time. Thanks for taking the time to put this together.

Pitch A.
Pitch A.
6 years ago

Excellent! Thank you for putting this together!

Get in touch! We would love to discuss your next software project.
Would love your thoughts, please comment.x