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

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

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

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:


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

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

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

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

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

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.


Put It To Good Use


I ‘m a Web Developer and a Flatiron coding bootcamp alumni. I currently work in the financial tech industry as a Front End Engineer