Creating an Email Forwarder using NodeJS and SendGrid

ยท

4 min read

We received a business requirement where we had to create around 15,000 email ids which will forward the email to another email ids and nothing else. This seemed pretty simple and straight forward but how to do it in a cost-effective was the question.

I have divided this article into two parts, the story and the solution, The story includes the whys and hurdles which let us choose SendGrid for the solution. The Solution includes the technical implementation using NodeJS.

The Story

We thought of using some external services that provide us with the email forwarding functionality instead of building an in-house email server to solve the problem.

Search of Email Provider

We found many different email providers like Rediffmail, Gmail and many others and out of them, Zoho Mail was the cheapest and most reliable.

Each email account in Zoho would cost around $1 for 1 month, so the cost would reach $15000 for a 15,000 email account which was a little bit costly just for forwarding email. So we started searching for open source solutions to serve the purpose.

Going towards Open Source

We started the hunt for open source solutions and found Postal Server as a reliable and secure email server.

Port 25 is blocked ๐Ÿ˜ฑ

While we were deploying the postal in cloud instances we found that most of the providers block port 25 due to the risk of abuse, though some providers like DigitalOcean unblocks the port upon request, the condition was the instance should be older than 60 days.

SendGrid

The search continued and we found out that SendGrid provides an Inbound Email Webhook using which we can receive email on the linked domain and SendGrid will call the webhook of our server with the email data.

The best part was the local part (i.e. anything before @) can be any word, we don't need to create a local part in the SendGrid to receive inbound emails.

For example, any email sent to , or any word before @sagarvaghela.in will be processed by SendGrid and will hit our server.

The Solution

We implemented the solution using NodeJS App and SendGrid. The NodeJS App is used to provide the API to SendGrid Inbound Parse and for mapping of email ids.

Sender Authentication

The First step required is to authenticate the Sender Identity i.e to link your domain to SendGrid DNS Servers.

Once it is done, you can start using the SendGrid APIs to send and receive inbound emails.

link-domain.png

Create a NodeJS App to receive the request and Forward Email

We will use the following packages to implement the solution along with ExpressJS Framework:

Multer

Multer is a middleware to parse the Multipart/Form Data, The data sent from SendGrid Inbound Parser is in Multipart/Form Data

Mail Parser

MailParser will be used to parse the raw data received from the SendGrid, It will return an object of ParsedMail.

SendGrid Mail

SendGrid Package will be used to forward the email.

Implementation

const emailMapper = {
 "xyz@domain.com": "xyz@gmail.com"
};

app.post("/", upload.any(), (req, res) => {
  sgMail.setApiKey(SENDGRID_API_KEY);

  simpleParser(req.body.email).then((parsedEmail) => {
    const toEmail = [];

    parsedEmail.to.value.forEach((value) => {
      if (emailMapper[value.address] !== undefined) {
        toEmail.push(emailMapper[value.address]);
      }
    });

    if (toEmail.length > 0) {
      let attachments = [];

      if (parsedEmail.attachments.length > 0) {
        parsedEmail.attachments.forEach((file) => {
          attachment = {
            content: file.content.toString("base64"),
            filename: file.filename,
            type: file.type,
            disposition: file.contentDisposition,
            content_id: file.contentId,
          };

          attachments.push(attachment);
        });
      }

      const msg = {
        to: toEmail,
        from: "no-reply@xyz.com",
        subject: parsedEmail.subject,
        text: parsedEmail.text,
        html: parsedEmail.html,
        attachments: attachments,
      };

      sgMail.send(msg).then(
        () => {},
        (error) => {
          console.error(error);

          if (error.response) {
            console.error(error.response.body);
          }
        }
      );
    }
  });
  res.sendStatus(200);
});

You can find the complete code in Github.

Note: This is a simple representation of the solution and not production-ready code.

Add the Web Server in SendGrid

Once we created the webserver, We need to provide the Host URL in the SendGrid. So any email sent to the domain will be processed by SendGrid Inbound Parse and POSTed to the Web Server URL.

webhook.png

The Cost

SendGrid charges on a per email basis with the base plan of $15/50,000 emails, As per our requirement the worst it could cost us $60.

To host the NodeJS App, a small VM instance would be required which would cost less than $20.

The total sums up to $80 per month! ๐Ÿ˜ƒ

References

  1. Zoho Email
  2. Google Cloud Instance Port 25 blocked article
  3. DigitalOcean Port 25 unblock process
  4. SendGrid Inbound parse
  5. Mail Parser
ย