Email Development
How to send transactional email in a NodeJS app using the Mailgun API
Sending transactional emails is easy regardless of your tools. If you use a NodeJS helper library, this walkthrough will help you get set up in Mailgun. Read more...
PUBLISHED ON
Not only you can get powerful re-engagement based on triggers, actions, and patterns you can also communicate important information and most importantly, automatically between your platform and a customer.
It’s highly likely that during your life as a developer you’ll have to send automated transactional emails, if you haven’t already, like:
Confirmation emails
Password reminders
…and many other kinds of notifications.
In this tutorial, we’re going to learn how to send transactional emails using the Mailgun API and using a NodeJS helper library.
We will cover different scenarios:
Sending a single transactional email
Sending a newsletter to an email list
Adding email addresses to a list
Sending an invoice to a single email address
Getting started
We will assume you have installed and know how to operate within the NodeJS environment.
The first need we’re going to do is generate a package.json
file in a new directory (/mailgun_nodetut
in my case).
This file contains details such as the project name and required dependencies.
1{2 "name": "mailgun-node-tutorial",3 "version": "0.0.1",4 "private": true,5 "scripts": {6 "start": "node app.js"7 },8 "dependencies": {9 "express": "4",10 "jade": "*",11 "mailgun-js":"0.5"12 }13}
As you can see, we’re going to use expressjs
for our web-app scaffolding, with jade
as a templating language and finally a community-contributed library for node by bojand.
In the same folder where you’ve created the package.json
file create two additional folders:
views/
js/
You’re set – now sign in to Mailgun, it’s free if you haven’t done it yet and get your API key (first page in the control panel).
Set up a simple ExpressJS app
Save the code below as app.js
in the root directory of your app (where package.json
is located)
1 //We're using the express framework and the mailgun-js wrapper2 var express = require('express');3 var Mailgun = require('mailgun-js');4 //init express5 var app = express();6 7 //Your api key, from Mailgun’s Control Panel8 var api_key = 'MAILGUN-API-KEY';9 10 //Your domain, from the Mailgun Control Panel11 var domain = 'YOUR-DOMAIN.com';12 13 //Your sending email address14 var from_who = 'your@email.com';15 16 //Tell express to fetch files from the /js directory17 app.use(express.static(__dirname + '/js'));18 //We're using the Jade templating language because it's fast and neat19 app.set('view engine', 'jade')2021 //Do something when you're landing on the first page22 app.get('/', function(req, res) {23 //render the index.jade file - input forms for humans24 res.render('index', function(err, html) {25 if (err) {26 // log any error to the console for debug27 console.log(err); 28 }29 else { 30 //no error, so send the html to the browser31 res.send(html)32 };33 });34 });3536 // Send a message to the specified email address when you navigate to /submit/someaddr@email.com37 // The index redirects here38 app.get('/submit/:mail', function(req,res) {3940 //We pass the api_key and domain to the wrapper, or it won't be able to identify + send emails41 var mailgun = new Mailgun({apiKey: api_key, domain: domain});4243 var data = {44 //Specify email data45 from: from_who,46 //The email to contact47 to: req.params.mail,48 //Subject and text data 49 subject: 'Hello from Mailgun',50 html: 'Hello, This is not a plain-text email, I wanted to test some spicy Mailgun sauce in NodeJS! <a href="http://0.0.0.0:3030/validate?' + req.params.mail + '">Click here to add your email address to a mailing list</a>'51 }5253 //Invokes the method to send emails given the above data with the helper library54 mailgun.messages().send(data, function (err, body) {55 //If there is an error, render the error page56 if (err) {57 res.render('error', { error : err});58 console.log("got an error: ", err);59 }60 //Else we can greet and leave61 else {62 //Here "submitted.jade" is the view file for this landing page 63 //We pass the variable "email" from the url parameter in an object rendered by Jade64 res.render('submitted', { email : req.params.mail });65 console.log(body);66 }67 });6869});7071 app.get('/validate/:mail', function(req,res) {72 var mailgun = new Mailgun({apiKey: api_key, domain: domain});7374 var members = [75 {76 address: req.params.mail77 }78 ];79 //For the sake of this tutorial you need to create a mailing list on Mailgun.com/cp/lists and put its address below80 mailgun.lists('NAME@MAILINGLIST.COM').members().add({ members: members, subscribed: true }, function (err, body) {81 console.log(body);82 if (err) {83 res.send("Error - check console");84 }85 else {86 res.send("Added to mailing list");87 }88 });8990 })9192 app.get('/invoice/:mail', function(req,res){93 //Which file to send? I made an empty invoice.txt file in the root directory94 //We required the path module here..to find the full path to attach the file!95 var path = require("path");96 var fp = path.join(__dirname, 'invoice.txt');97 //Settings98 var mailgun = new Mailgun({apiKey: api_key, domain: domain});99100 var data = {101 from: from_who,102 to: req.params.mail,103 subject: 'An invoice from your friendly hackers',104 text: 'A fake invoice should be attached, it is just an empty text file after all',105 attachment: fp106 };107108 //Sending the email with attachment109 mailgun.messages().send(data, function (error, body) {110 if (error) {111 res.render('error', {error: error});112 }113 else {114 res.send("Attachment is on its way");115 console.log("attachment sent", fp);116 }117 });118 })119120 app.listen(3030);
How it works
This above is a simple express app that will run on your local machine on port 3030
. We have defined it to use expressjs and the mailgun-js wrapper. These are pretty well-known libraries that will help us quickly set up a small website that will allow users to trigger the sending of email addresses to their address.
First things first
We’ve defined 4 endpoints.
/
/submit/:mail
/validate/:mail
/invoice/:mail
Where :mail
is your valid email address.
When navigating to an endpoint, Express will send to the browser a different view.
In the background, Express will take the input provided by the browser and process it with the help of the mailgun-js
library.
In the first case, we will navigate to the root that is localhost:3030/
You can see there’s an input box requesting your email address. By doing this, you send yourself a nice transactional email.
This is because expressjs takes your email address from the URL parameter and by using your API key and domain does an API call to the endpoint to send emails.
Each endpoint will invoke a different layout, I’ve added the code of basic layouts below, feel free to add and remove stuff from it.
Layouts
Save the code below as index.jade
within the /views directory
1doctype html2html3 head4 title Mailgun Transactional demo in NodeJS5 body6 p Welcome to a Mailgun form7 form(id="mgform")8 label(for="mail") Email9 input(type="text" id="mail" placeholder="Youremail@address.com")10 button(value="bulk" onclick="mgform.hid=this.value") Send transactional11 button(value="list" onclick="mgform.hid=this.value") Add to list12 button(value="inv" onclick="mgform.hid=this.value") Send invoice13 script(type="text/javascript" src="main.js")
Save the code below as error.jade
within the /views directory
1doctype html2html3 head4 title Mailgun Transactional5 body6 p Well that's awkward: #{error}
Javascript
This code allows the browser to call a URL from the first form field with your specified email address appended to it. This way we can simply parse the email address from the URL with express’ parametered route syntax.
Save the code below as main.js
within the /js directory
1var vForm = document.getElementById('mgform');2var vInput = document.getElementById('mail');34vForm.onsubmit = function() {5if (this.hid == "bulk") {6 location = "/submit/" + encodeURIComponent(vInput.value);7}8if (this.hid == "list") {9 location = "/validate/" + encodeURIComponent(vInput.value);10}11if (this.hid == "inv") {12 location = "/invoice/" + encodeURIComponent(vInput.value);13}1415return false;16}
Finally, create an empty invoice.txt
file in your root folder. This file will be sent as an attachment.
Now run npm install
(or sudo npm install
in some cases depending on your installation) to download dependencies, including Express.
Once that’s done run node app.js
Navigate with your browser to localhost:3030
(or 0.0.0.0:3030
)
And that’s how you get started sending transactional email on demand!
Conclusion
In our example, we’ve seen how you can send a transactional email automatically when the user triggers a specific action, in our specific case, submitting the form.
There are thousands of applications that you could adapt this scenario to. Sending emails can be used for:
Registering an account on a site and Hello message email
Resetting a password
Confirming purchases or critical actions (deleting an account)
Two-factor authentication with multiple email addresses
What do you use transactional emails for in your day-to-day business?
Popular posts

Build Laravel 10 email authentication with Mailgun and Digital Ocean
When it was first released, Laravel version 5.7 added a new capability to verify user’s emails. If you’ve ever run php artisan make:auth within a Laravel app you’ll know the...
Read more

Sending email using the Mailgun PHP API
It’s been a while since the Mailgun PHP SDK came around, and we’ve seen lots of changes: new functionalities, new integrations built on top, new API endpoints…yet the core of PHP...
Read more

Here’s everything you need to know about DNS blocklists
The word “blocklist” can almost seem like something out of a movie – a little dramatic, silly, and a little unreal. Unfortunately, in the real world, blocklists are definitely something you...
Read more