Video Tutorial (Optional)
Watch first if you want to follow the full setup for sending Gmail emails from Node.js using Nodemailer with a Handlebars HTML template.
Project Overview
Node.js + Nodemailer + Handlebars templates: In this project you use Node.js with Nodemailer and a Handlebars HTML template to send a dynamic email through Gmail SMTP, replacing template values like {{username}} at send time.
Using templates in Node is a great way to streamline the email-sending process. The handlebars package makes it simple to insert dynamic values into HTML templates and allows for great separation of concerns when constructing your Node application.
Sending emails to your users becomes critical in large scale applications, and dynamic templates are often needed for this.
- Time: 15 to 30 minutes
- Skill level: Beginner
- What you will build: A basic Express endpoint that compiles a Handlebars HTML email template and sends it via Gmail using Nodemailer
Parts List
From ShillehTek
- None
External
- Node.js project environment
- Gmail account with an app password
-
nodemailer- sends email via SMTP -
express- simple web server for triggering the email -
express-handlebars- installed in the original setup list -
handlebars- compiles the HTML template with dynamic replacements -
fs(built-in Node module) - reads the template file from disk
Note: You need a Gmail app password for authentication. Replace the placeholder values in the code (email addresses and app password) with your own.
Step-by-Step Guide
Step 1 - Install the required packages
Goal: Add Nodemailer, Express, and Handlebars-related dependencies to your Node.js project.
What to do: Run the following command in your project folder.
Code:
npm install nodemailer express express-handlebars
Expected result: Your package.json includes the installed dependencies and you are ready to create an email template.
Step 2 - Create the HTML email template file
Goal: Create an HTML template that includes a dynamic placeholder value.
What to do: Create an HTML file (for example, email_template.html) in your project. In the original example, the template is saved in the root directory of the application.
The only dynamic value in this template is {{username}}, so you can send the same email layout to any user and replace the username at send time.
Code:
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f2f2f2;
}
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
margin-bottom: 20px;
}
.header h1 {
color: #333;
font-size: 24px;
margin: 0;
}
.content {
margin-bottom: 30px;
}
.content p {
margin: 0 0 10px;
line-height: 1.5;
}
.footer {
text-align: center;
}
.footer p {
color: #999;
font-size: 14px;
margin: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Greetings, {{username}}!</h1>
</div>
<div class="content">
<p>Thank you for being a valued member of our community.</p>
<p>We appreciate your continued support and would like to offer you a special discount on your next purchase.</p>
<p>Simply use the code <strong>WELCOME10</strong> at checkout to enjoy a 10% discount.</p>
<p>We hope you enjoy your shopping experience with us.</p>
</div>
<div class="footer">
<p>Best regards,</p>
<p>The Team</p>
</div>
</div>
</body>
</html>
Expected result: You have a reusable HTML email template file that includes a Handlebars placeholder (for example, {{username}}).
Step 3 - Run the Node.js code to compile and send the email
Goal: Read the HTML template from disk, compile it with Handlebars replacements, and send it through Gmail using Nodemailer.
What to do: Use the following code and replace the placeholders (email addresses and app password) accordingly. You need an app password from your Gmail account.
This example runs a basic Express server. When you hit the base URL, it sends an email using the compiled template. You can place the function wherever it fits your application.
Code:
const express = require('express');
const nodemailer = require('nodemailer');
const handlebars = require('handlebars');
const fs = require('fs');
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.email',
secure: false,
service: 'gmail',
auth: {
user: '<email>',
pass: '<app password>',
},
});
const app = express();
const port = 3005;
app.get('/', async (_, res) => {
const source = fs.readFileSync('email_template.html', 'utf-8').toString();
const template = handlebars.compile(source);
const replacements = {
username: 'Shilleh',
};
const htmlToSend = template(replacements);
const info = await transporter.sendMail({
from: '<some email>',
to: '<some email>',
subject: 'Hello from node',
text: 'Hello world?', // dont really need this but it is recommended to have a text property as well
html: htmlToSend
});
console.log('Message sent: %s', info.response);
res.send('Email Sent!');
});
app.listen(port, () => {
console.log(`App is listening on port ${port} !`);
});
Expected result: Starting the server and visiting / triggers an email send, and the recipient receives an HTML email with {{username}} replaced by your chosen value.
Conclusion
You set up a Node.js workflow that compiles a Handlebars HTML template and sends it through Gmail using Nodemailer, making it easy to personalize emails with dynamic values like usernames.
Want to support builds like this or grab parts for your next project? Shop at ShillehTek.com. If you want help tailoring email automation or backend integrations for your product, check out our consulting services.


