Setting Up an Email Form With Node.js, Express, and Mailgun Part 2

Aidan McBride
12 min readOct 13, 2020


In Part 1, we wrote a file that allowed us to send a data object as an email to an address of our choice using Mailgun. This time, we will be using Express to build out a backend server and an HTML form to customize our email and send it from the browser to our server. If you have experience with Node.js and Express, you will find this process much easier. However, I will give you all the tools you need to build a functioning email form and describe the process step by step.

Setting Up Our App

The easiest way to build this application is to continue to work in the folder we had built from the previous blog. If you have not read it, I recommend starting here.

We should have a node_modules folder, a package.json file, a package-lock.json file, and an app.js file. Our structure should look much like the image to the left. We are going to start by creating two new files, server.js and index.html. For now, the index.js file will simply container boiler plate code for a basic html file. Using the command line, enter:

after touch, we enter the names of each file and their extensions separated by a space

And fill our html file to look like this, with some text inside a h1 tag in the body:

Next we will want to run:

This will create a “devDependencies” section in our package.json file, and the -y will simply answer yes to any prompted questions. The -y is optional, but for this purpose I recommend adding it to save just a little time.

Nodemailer, Nodemailer-mailgun-transport, and Express

Nodemailer is one of the main tools we will be using for sending emails. It is a a node module for Nodes.js applications. Nodemailer-mailgun-transport is a node module that works with mailgun-js module we downloaded in the previous blog as well as nodemailer. It allows us to send emails using the Mailgun API instead of the SMTP protocol.

Express is a back end framework for Node.js designed for building API’s and web applications. It utilizes an MVC pattern, and is similar to Ruby on Rails in the sense that it creates the server-side of web applications. Fully understanding Express, or Express.js as it is sometimes called, is not necessary for this blog. I do recommend looking into the documentation afterwards as it is one of the most popular back end frameworks. However, I will walk you through every bit of code necessary to achieve our goal of sending an email from a form.

We can install all three of these with one command:

The -S saves the packages as dependencies

Now our package.json file’s dependencies section should look something like this:

The versions are listed after the dependencies, these may vary depending on when you read this blog

For the sake of argument, let’s also create a views folder within our application. We should then move the index.html file within the views folder. It is standard practice to separate “views” or html from our actual code. Everything else will still exist in the root directory, only the html file will exist within the views folder. Our applications file structure will look like this:


We can finally begin some coding! We will start by configuring a route. In our server.js file, we will define an express constant and create a port to listen in on. We will past the port the listen function with a callback function. For now we can console log some text like “My server is running on port 8080”.

To break this down quickly, line 1 creates a variable express, line 2 creates a variable app that is created from the invoking of the express function, like 4 creates a variable PORT that is set equal to the integer 8080. Line 6 calls a function listen on the app that we created with the express function on line 2. Listen is passed the PORT number, followed by our callback function that simply prints a message.

Now that we are listening to a server, we can create a route. If we call get functino on our app and pass it a route and a callback function, we can achieve this.

We first define path on line 3 from an existing module “path”, so we do not need to install, simple declare it as a variable.

We have also added lines 7to 9, where we call get on our app, pass it a path ‘/’, and a callback function that takes a request and a response. Inside the body of the callback function, we call sendFile on the response. Send file takes a path where we use __dirname to indicate the outermost directory, then views, then index.html. If you read this out, we are identifying where to access our path and joining together each folder and file to create a path.

Running Our Server

Before we run our server and test our first route, we will have to install one more dependency. Nodemon automatically restarts the node application when file changes are detected. This allows development to run much smoother and debugging to go easier because your app will refresh whenever you make changes. Run the command:

From now on, when we run node commands on the command line we will replace the word node with nodemon. Let us run nodemon server.js and if our server is working, we should see the following result in the terminal:

Note the console.logged message at the bottom of the terminal that we had written in our server.js file.

Now that our server is up and running, let’s navigate to localhost:8080 in our web browser to see our html!

The rendered index.html file we wrote

Sending Data To The Server

The next step in our process will be to set up the index.html file with a form and make sure we are able to send some data to the server. We will start in our server.js file by setting up a way to parse the incoming data. Add the following to your server.js file:

We will run use on app, pass it express.urlencoded and pass that an object with the extended property equal set to false. This parses incoming requests with urlencoded payloads. After that, we call app.use again and pas it it express parsed into json with the .json() function. Urlencoded recognizes the incoming request object as strings or arrays while .json() recognizes the incoming request object as a JSON object. I won’t go too in depth on the purpose of these functions here, but if you want to fully understand what’s going on here I recommend looking up the express documentation.

Next we can set up a route to receive data from the client. We can call it ‘/email’. We will use the post method on the app object, pass it the route ‘/email’ and a callback function. For now let us just parse the response into json with a message of ‘I got your message’.

Making Our Form

Now to make our HTTP call, we will be using a technology called JQuery CDN, or ‘content delivery network’. JQuery is a JavaScript library used to handle events, CSS animations, HTML DOM tree traversal and manipulation, and Ajax. We will be using it to help make our HTTP call. Go to and copy the following script tag. You can paste it in your index.html file inside the <head> tag.

We are also going to set up our HTML form. We can use a basic form with just a subject, email address, and message with inputs and a textarea inside a form tag. I added some simple styling to align our form. Underneath the form, we will post the script for the Jquery CDN, and create another empty <script> tag where we will write our logic. So far, our html should look like this:

If you are interested in the styling, it looks like this:

We will now write in JQuery code to execute when the form is submitted.

Written in JQuery

Let’s walk through this code. On line 30 we are establishing a form, then saying on the submit action of this form, we pass it a function with ‘e’ for event. First, we call e.preventDefault(), this function prevents the default action of the from, preventing the page from refreshing on every form submission. On lines 33 to 35, we create a variable for each piece of form data, reference them by their id attribute by preceding their id with a ‘#’ symbol. We get the value of these inputs with .val and use .trim to exclude any extra whitespace in the inputs.

Create a data object and pass it to .post

Here we are first creating a data object on lines 37 to 41 that contains all three of our variables. Next, we are calling post to the route of ‘/email’, passing it that data object, and a function that logs that the data has been received.

If we go back into our server.js file, we can console log the data we receive. We reference that data object with ‘req.body’ to access the body of our data.

So now if we fill out our form on the browser and hit submit, we will see in the browser console a message that the data has been received by the server.

And in our console inside of our directory, we will see the data representing what we filled out in the form!

It works!

We have successfully sent an email from our browser to our server!

Sending to Our Email Address

If you remember the purpose of the last blog, it was to send an email to an account using Mailgun. We are now going to incorporate Mailgun into our application to allow us to send emails from our browser, to our server, then directly to our email. Let’s jump right in and create a file called mail.js.

In our mail.js file, we will first create variables for nodemailer and mailGun, requiring them from our package.json file where we downloaded them earlier. Then we will create an authorization object that contains authorization using our API key and domain name. Finally we create a transporter that will use nodemailers createTransport function and mass it mailGun, and pass that our auth object for authorization.

We then create a mailOptions object that will house the contents of our email. For now I have filled it out with test data, but keep in mind to to subject will always be whatever email you have chosen and verified with your Mailgun account. Beneath that, we use our transporter object and sendMail function, pass it our mailOptions object, and a function that is passed error and data. If there is an error we will log it.

At this point, you should add your own API key and domain to the auth object inside of the strings. I will not be showing mine for privacy reasons, but yours are available on your Mailgun account. If you need help finding them refer to Part 1 of this blog. If we run the following command, we should receive “Success” in the terminal. Go to your email and you will find the message we created in mailOptions as an email in your inbox.

Note: Sometimes mail may end up in your Spam folder, especially if it is from a fake email account. Also, messages may not be delivered immediately, they may take some time. Check your logs under the sending tab on your Mailgun account to keep track of your messages.

Using Our Message

Now for the final step of the process, we are going to send the actual data we input from our form, to our server, and out to our email address. In our mail.js file, we will write a function called sendMail and pass it the parameters of email, subject, text, and cb for callback. We move the mailOptions object inside this function, and pass it the data to replace the hardcoded attributes. We also move the transporter inside the sendMail function, and replace the console logs with the callback function(cb) and pass them either the error and null for the data, or null for the error and the data as the data.

Subject and text can be written in as single words because of ES6 syntax

Next, inside of our server.js file, we import sendMail from our mail.js file with the following line.

Then we edit our method. We are going to de-structure the body of the request into the subject, email, and text. Then, we will call sendMail and pass it the email, subject, body, and text, and a function to represent the cb or callback function. Inside the callback we will write an if statement that checks for an error, and either returns an error message, or returns a message indicating success. Be sure to delete the previous res.json that returned our message, as this function is only expecting to return one json object at a time.

Finally, we are ready to send an email from the browser! In your terminal, if you haven’t already open your index.html file on your browser. Then, fire up the server by running nodemon server.js. Fill our your HTML form, hit submit and check your email! You should have received an email with the subject, return address, and message you typed in to your form.


I mentioned in Part 1 of this blog that there are a few issues with Mailgun and their free service. As a free member, it is likely your messages may take longer to arrive, and you have a limit of 5,000 for three months. In general, this service seems to be the best option for sending mail, but keep in mind it does face issues. Sometimes messages end up in the spam or promotions folders. However, I have found that if you messages have a clear subject, working return address, and normal body/message content (not clearly spam), then they go through directly to your inbox. Mailgun has a very efficient support service, you can write a ticked or contact them directly during business hours. If you face issues, I recommend reaching out to them.

Put It To Good Use

The main advantage to this approach to sending emails is that a user does not need to navigate away from your webpage to send an email. This allows for a much smoother UX and UI and will keep your clients happy. I recommend trying to implement this in other ways too, get creative with it. Happy coding!




Aidan McBride

I am a Front End Engineer and graduate of Flat Iron coding bootcamp. Currently I work in the regulatory industry using React.