- Quick tips
How to Improve Holiday Supply Chain Communication with Email
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.
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
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.0.0",10 "form-data": "^4.0.0",11 "jade": "*",12 "mailgun.js": "^4.0.0"13 }14}
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.
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 and get your API key (first page in the control panel).
Learn about our Deliverability Services
Looking to send a high volume of emails? Our email experts can supercharge your email performance. See how we've helped companies like Lyft, Shopify, Github increase their email delivery rates to an average of 97%.
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 framework2const express = require('express');34// importing mailgun SDK;5const formData = require('form-data');6const Mailgun = require('mailgun.js');7// importing packages for processing files89const path = require('path');10const fsPromises = require('fs').promises;1112// init express13const app = express();1415// Your api key, from Mailgun’s Control Panel16const apiKey = 'MAILGUN-API-KEY';1718// Your domain, from the Mailgun Control Panel19const domain = 'YOUR-DOMAIN.com';2021// Your sending email address22const fromWho = 'your@email.com';2324// creating mailgun client;25const mailgun = new Mailgun(formData);26const mailgunClient = mailgun.client({ username: 'api', key: apiKey || '' });2728// Tell express to fetch files from the /js directory29app.use(express.static(path.resolve(__dirname, './js/')));30// We're using the Jade templates language because it's fast and neat31app.set('view engine', 'jade');3233// Do something when you're landing on the first page34app.get('/', function (req, res) {35 // render the index.jade file - input forms for humans36 return res.render('index', function (err, html) {37 if (err) {38 // log any error to the console for debug39 console.log(err);40 } else {41 // no error, so send the html to the browser42 res.send(html);43 }44 });45});4647// Send a message to the specified email address when you navigate to /submit/someaddr@email.com48// The index redirects here49app.get('/submit/:mail', async function (req, res) {50 const data = {51 // Specify email data52 from: fromWho,53 // The email to contact54 to: req.params.mail,55 // Subject and text data56 subject: 'Hello from Mailgun',57 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>`58 };5960 try {61 // Invokes the method to send emails given the above data with the helper library62 await mailgunClient.messages.create(domain, data);63 // Here "submitted.jade" is the view file for this landing page64 // We pass the variable "email" from the url parameter in an object rendered by Jade65 return res.render('submitted', { email: req.params.mail });66 } catch (error) {67 // If there is an error, render the error page68 console.log('got an error: ', error);69 return res.render('error', { error });70 }71});7273app.get('/list/:listName/:mail', async function (req, res) {74 const emailAddress = req.params.mail;75 const listName = req.params.listName;7677 try {78 let mailingList = '';79 const validListName = `${listName}@${domain}`;80 // check if a mailing list with provided name already exists81 mailingList = await mailgunClient.lists.get(validListName).catch(async (err) => {82 if (err.status === 404) {83 // creating a new mailing list in case it doesn't exist84 const createdMailingList = await mailgunClient.lists.create({ address: validListName });8586 console.info(`New mailing list ${createdMailingList.address} was created`);87 return createdMailingList;88 }89 throw new Error(err);90 });9192 // add member to mailing list93 await mailgunClient.lists.members.createMember(mailingList.address, { address: emailAddress });94 const message = `New member ${emailAddress} was added to mailing list: ${mailingList.address}`;9596 console.info(message);97 return res.send(message);98 } catch (error) {99 console.error(error);100 let transformedError = error;101 if (error.status === 400 && error.details) {102 transformedError = error.details;103 }104 return res.render('error', { error: transformedError });105 }106});107108app.get('/invoice/:mail', async function (req, res) {109 // We use the path module here to find the full path and attach the file!110 const attachment = {111 filename: 'invoice.txt',112 data: await fsPromises.readFile(path.join(__dirname, 'invoice.txt'))113 };114115 // Settings116 const data = {117 from: fromWho,118 to: req.params.mail,119 subject: 'An invoice from your friendly hackers',120 text: 'A fake invoice should be attached, it is just an empty text file after all',121 attachment122 };123124 // Sending the email with attachment125 try {126 await mailgunClient.messages.create(domain, data);127 console.log('attachment sent', attachment.filename);128 return res.send('Attachment is on its way');129 } catch (error) {130 console.error(error);131 return res.render('error', { error });132 }133});134135const port = 3030;136app.listen(port, () => {137 console.info(`server is listening on ${port}`);138});139
The example 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 SDK. 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.
We’ve defined 4 endpoints.
/
/submit/:mail
/validate/:mail
/invoice/:mail
Where :mail
is your valid email address and :listName
is a name for mailing list.
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.
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 h4 Send email or invoice file8 form(id="mgform")9 fieldset10 label(for="mail") Email11 input(type="email" id="mail" required placeholder="Youremail@address.com")12 br13 button(value="bulk" onclick="mgform.hid=this.value") Send transactional14 button(value="inv" onclick="mgform.hid=this.value") Send invoice1516 h4 Add to sending list17 form(id="mgAddToListForm")18 fieldset19 label(for="mail1") Email20 input(type="email" id="mail1" required placeholder="Youremail@address.com")21 br22 label(for="listName") listName23 input(type="text" id="listName" required placeholder="example" alt="Name for new sending list")24 br25 button(value="list" onclick="mgAddToListForm.hid=this.value") Add to list2627 script(type="text/javascript" src="./main.js")`28
Save the code below as error.jade
within the /views directory
1doctype html2html3 head4 title Mailgun Transactional5 body6 p Well that's awkward: #{error}`7
Save the code below as submitted.jade within the /views directory
1doctype html2html3 head4 title Mailgun Transactional5 body6 p email sent to #{email}
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
1const mgForm = document.getElementById('mgform');2const mgAddToListForm = document.getElementById('mgAddToListForm');34mgForm.onsubmit = function () {5 const email = document.getElementById('mail');6 if (this.hid === 'bulk') {7 location = `/submit/${encodeURIComponent(email.value)}`;8 } else if (this.hid === 'inv') {9 location = `/invoice/${encodeURIComponent(email.value)}`;10 }11 return false;12};1314mgAddToListForm.onsubmit = function () {15 const email = document.getElementById('mail1');16 const listName = document.getElementById('listName');17 if (this.hid === 'list') {18 location = `/list/${encodeURIComponent(listName.value)}/${encodeURIComponent(email.value)}`;19 }20 return false;21};22
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!
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?
Last updated on January 04, 2022
How to Improve Holiday Supply Chain Communication with Email
What Is a RESTful API, How It Works, Advantages, and Examples
Email’s Not Dead Season 3 Is Finally Here
Easier and Faster Implementation with Our Updated SDKs
The Difference Between SMTP and API
When Should You Use An Email API?
How To Use Parallel Programming
How we built a Lucene-inspired parser in Go
Gubernator: Cloud-native distributed rate limiting for microservices
What Toasters And Distributed Systems Might Have In Common
InboxReady x Salesforce: The Key to a Stronger Email Deliverability
Become an Email Pro With Our Templates API
Google Postmaster Tools: Understanding Sender Reputation
Navigating Your Career as a Woman in Tech
Implementing Dmarc – A Step-by-Step Guide
Email Bounces: What To Do About Them
Announcing InboxReady: The deliverability suite you need to hit the inbox
Black History Month in Tech: 7 Visionaries Who Shaped The Future
How To Create a Successful Triggered Email Program
Designing HTML Email Templates For Transactional Emails
InboxReady x Salesforce: The Key to a Stronger Email Deliverability
Implementing Dmarc – A Step-by-Step Guide
Announcing InboxReady: The deliverability suite you need to hit the inbox
Designing HTML Email Templates For Transactional Emails
Email Security Best Practices: How To Keep Your Email Program Safe
Mailgun’s Active Defense Against Log4j
Email Blasts: The Dos And Many Don’ts Of Mass Email Sending
Email's Best of 2021
5 Ideas For Better Developer-Designer Collaboration
Mailgun Joins Sinch: The Future of Customer Communications Is Here
Always be in the know and grab free email resources!
By sending this form, I agree that Mailgun may contact me and process my data in accordance with its Privacy Policy.