Receiving Emails with Node.js, Express, and Twilio SendGrid's Inbound Parse

January 25, 2022
Written by
Sam Agnew
Twilion

Copy of C04 Blog Text (3).png

Setting up an application to receive emails can be tiresome if you want to do it yourself. Luckily Twilio SendGrid includes the Inbound Parse feature, a greatly simplified method for receiving emails based on webhooks. Let's walk through how to receive emails on your own domain using Node.js.

Requirements and dependencies

We'll need to install the node modules for Express and the multer middleware. To install these npm modules, navigate to the directory where you want this code to live and run the following command in your terminal to create an npm package for this project:

npm init --yes

The --yes argument just runs through all of the prompts that you would otherwise have to fill out or skip. Now that we have a package.json for our app, let’s install the necessary libraries with the following shell command:

npm install express@4.17.2 multer@1.4.4

Domain authentication

The first step in setting up an email receiving pipeline is to authenticate your domain with Twilio SendGrid, so that they can send and receive emails on it on your behalf. Here is a detailed tutorial you can follow to set up domain authentication. The rest of this blog post will assume that you have a domain authenticated.

Write an incoming email endpoint with Express

We are now ready to create a simple Express application that will receive incoming emails. Create a file called index.js in the same directory as your package.json and add the following, which is the code for the complete application:

const express = require('express');
const multer  = require('multer');

const upload = multer();
const app = express();

app.post('/email', upload.none(), (req, res) => {
  const body = req.body;

  console.log(`From: ${body.from}`);
  console.log(`To: ${body.to}`);
  console.log(`Subject: ${body.subject}`);
  console.log(`Text: ${body.text}`);

  return res.status(200).send();
});

app.listen(3000, console.log('Express app listening on port 3000.'));

The application defines a single web route attached to the /email URL. SendGrid will invoke this route each time an incoming email arrives, sending all the information about the email as a standard form post, which we are using multer to parse so we can access it in request.body. You can review the complete list of email parameters in the SendGrid documentation.

You can run this code with the command node index.js or npm start in your terminal.

The application is now running and waiting for incoming requests, but it is only reachable from your own computer because we are running a development server. Leave it running for now, and we will make it accessible on the Internet.

Configure the SendGrid Inbound Parse webhook

With the Express application running, we just need to connect it with SendGrid to be able to receive emails. We are going to use a tool called ngrok to create a public URL that SendGrid can use to forward requests to our locally running application.

If you haven’t yet, install ngrok on your system. With the Node.js code running, open a second terminal window to start ngrok as follows:

ngrok http 3000

This is telling ngrok to create a “tunnel” from the public Internet into port 3000 in our local machine, where the Express app is listening for requests. The output should look something like this:

What the ngrok screen looks like in your terminal

Now that you have a publicly accessible URL, go back to the SendGrid dashboard and under Settings select Inbound Parse, then click on “Add Host & URL”.

The page for adding a webhook URL for Inbound Parse

In the next screen you can optionally enter a subdomain on which you will be receiving emails. This can be any subdomain that is available on your domain. If you want to receive emails on your top-level domain it can be left empty.

Next you have to select your domain name. This is a dropdown list that shows all the domains that you have verified with SendGrid. If you are doing this for the first time you will only see the domain that you verified above.

Next you have to enter the destination URL for your webhook. This is the URL generated by ngrok with /email attached at the end. In my case this was http://bbf1b72b.ngrok.io/email.

Click “Add” to configure your webhook.

Adding a destination URL for Inbound Parse

Now you will see an entry for your webhook in the main Inbound Parse page:

The Inbound Parse page with everything configured

Keep in mind that ngrok URLs change each time ngrok is stopped and restarted, so during development you may need to edit your webhook to update the URL. When you deploy your webhook for production use you will host it directly on a public URL, so ngrok will not be needed.

Set up an MX Record

The domain that you selected to receive emails in the previous section needs to be defined in the DNS configuration of your domain provider with a MX record. The value is the same for all SendGrid customers: mx.sendgrid.net. (note the trailing dot after “net”).

For example, if you are using a subdomain called "parse" to receive your emails, in Google DNS it should look something like this:

Setting an MX record in Google Domains

Depending on what domain provider you use, you may need to enter the complete hostname for this DNS record, so in that case it would be parse.yourdomainhere.com.

If you decided to not define a subdomain in the previous section, then your hostname is going to be yourdomainhere.com or just “@”.

Once you add this final entry to your domain’s DNS configuration you will once again need to wait for it to propagate before you can use it.

Send a test email

While having your Node.js code and ngrok running, open your email client and send a test email. In the To field you can enter any name that you want, as SendGrid captures all usernames. What goes after the @ needs to be your complete email-receiving domain:

A test email I am writing to myself

Wait a minute or two and eventually SendGrid will invoke the ngrok webhook URL, which in turn will invoke your Express endpoint. You should see something like this printed to your terminal:

The parameters for the test email being printed to my terminal

Congratulations on receiving emails with Node.js! I can't wait to see what you build with Inbound Parse.