Mailgun Mailer

Sam Williams
6 min readJan 1, 2018

This is a tutorial on how to create a Mailgun mailer that can be swapped out for the Sendgrid mailer used in the Node and React course.

Mailgun API

To access the Mailgun API through Node.js, there’s an NPM package making our lives easier. To install the package run this command whilst in the client directory.

npm install --save mailgun-js

To send an email through their API, this is the code that you need to run.

You can see that we need an api_key and a domain which are passed into the mailgun-js.

Building MailgunMailer

This mailer is built very similarly to the Sendgrid mailer. We initialise mailgun, create the class of MailgunMailer and export it so we can use it in the survey-routes file.

Now we need to get the subject, recipients and content to populate the emails. We are going to call the MailgunMailer in the same way that we would have called the SendgridMailer.

const mailer = new MailgunMailer(survey, surveyTemplate(survey));

This means that we will receive the subject as the first parameter and the html content as the second. We can use es6 destructuring extract just the subject and recipients from the survey we pass in.

We also need to remember that the recipients will be an array of the recipient model that we created earlier in the course. The Mailgun API requires that we send a comma separated string of email addresses. We do this by mapping over each of the recipients and destructuring just the email value out of the object and returning that. We then join this array of email strings with commas to make a compliant data structure.

Setting up Mailgun

To get all of this working, we need to set up a Mailgun account. Go to mailgun.com and click Sign Up in the top right. Enter your details but leave payment details until later.

On the dashboard you need to navigate to “Domains” where you should see one that is called sandbox(lots of numbers and letters).mailgun.org. This domain is ok but you can only send emails to pre-verified emails. We want to have our users send emails to any address they want so we need to do another step.

Go to ClouDNS.net and sign up for a free account. Once on the ClouDNS dashboard, click “add new” in the DNS zones section. This will give you a pop-up where you should click “Free Zone” to make a free DNS address. You can now choose your own free sub-domain name and register it. With your free domain set up, you now need to configure the DNS.

Back on Mailgun dashboard, click the “add new domain” button and enter the domain name you just got. I got samw.cloudns.asia as my domain but please switch out your domain name.

Now that you have the information to configure your DNS, head back to your ClouDNS dashboard and select your created DNS zone.

There will be two NS records already populated but we don’t care about those. Select the TXT tab and then add new record. In this first new record leave the Host field blank and point it to the first of the values from mailgun DNS Setup. Add a second record and have the host as mx._domainkey and the Points to of the second, long value from Mailgun.

Now move to the MX tab and create two records pointing to mxa.mailgun.org and mxb.mailgun.org (assuming that you have the same values provided by Mailgun).

The final record to create is a CNAME record with a host of email, pointing to mailgun.org. Now if you select ALL then you should see 7 records: 2 MX, 2 NS, 2 TXT and a CNAME.

With all of these completed, head back to your Mailgun dashboard and select your new domain. Expand the “Domain verification and DNS” section and click the Check DNS Records Now button. Hopefully all of the records should now be ticked and on the main dashboard, that domain will be marked as Active.

Whilst we’re here, we can turn on Click Tracking. This will be used later when we want to know the response based on the user link clicks.

There is one last bit of setup we need to do. To be allowed to send emails to unverified email addresses, you have to add payment details. To make sure that you never actually have to pay a penny, we’ll set up message and email validation limits.

Click your account dropdown email in the top right and select Account Settings. Under Details, enter a payment method, set the Custom Message Limit to 10,000 and the Public Email Validation Limit to 100. This is the amount that Mailgun let you use for free each month.

Linking your Account to your Project

Now that we have this account all set up, we need to connect it to our project. I stored both my domain name and API Key with all of the other keys. This also allows you to set up a second domain on Mailgun and ClouDNS so that you can have a development domain and a production domain. The final MailgunMailer.js file looks like this.

Webhooks

To set up webhooks in Mailgun, select the Webhooks menu item and then add the API address to the click event. You can test your webhook to make sure it works.

The way the Mailgun webhooks work is different from how the Sendgrid webhooks work. Mailgun sends each click notification in a new webhook post request so our server needs to deal with individual records instead of arrays of records.

The records that are sent to the API are x-www-form-urlencoded, meaning that we can’t directly access the values on the object. We first need to pass the request through a middleware to parse the url-encoded format into json. This is done by installing and requiring body-parser. bodyParser.urlencoded() is then passed as the second argument to the post request.

app.post("/api/survey/webhooks", bodyParser.urlencoded(), (req, res) => {

From the body we can extract the recipient email, link url and event type. We still use the path-parser package to get the surveyId and choice off the url that the user clicked on.

We check if the url matches the format that we have previously specified and that the event was a click event. If both of these are true then we update the survey using Survey.updateOne() .

The first parameter passed to the updateOne function is the criteria needed to find the record to update. We update the survey where _id = match.surveyId and where there is a recipient with the provided email who hasn’t previously responded. If there’s no survey with that id, the survey has no recipient with that email or that recipient has already responded then the update function will finish. The line $elemMatch: { email: email, responded: false} also stores the matching recipient as the $ variable.

The second parameter is what to update, assuming a matching record has been found. $inc: { [match.choice]: 1 } increments either yes or no values of the survey. $set: { "recipients.$.responded": true } takes the matching recipient stored in $ and and sets its responded value to true.

If you liked this tutorial then click the clap button and subscribe to get more software development content.

--

--

Sam Williams

I'm a software developer currently building Chat Bots for E-Commerce companies. Outside of coding I love to go Rock Climbing and Traveling.