Incoming email hooks and you!
Tags: email, webdev, node, postmarkapp
Published: 2019-11-11 16:10:31

---
title: Incoming email hooks and you!
published: true
description: Handle incoming email hooks for fun and profit.
tags: email, webdev, nodejs, postmarkapp
---


Sometimes when you are making your cool app thing you want to accept email. This could be for a myriad of reasons. 

Consider the Github use case. When someone comments on an issue you are watching you will receive an email. If you reply to the email it adds a comment to the issue!

Let's learn about some cool email headers and how we might go about building that ourselves.

I'll be using [Postmark](https://postmarkapp.com/) as the email sender/receiver. Most other email services like them also have this functionality. I just think they are cool and use them for my own projects.

## Setup

I'm going to skip a bit past the initial steps of creating an account and a server. Postmark has that well documented. 

What we care about is the incoming email hook.

First we go to default inbound stream.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/gpved8da733xb5mbma67.png)

Then in the settings tab the inbound email hook

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/0tg8svqc9rea4bepxuyz.png)

We'll also want to set an inbound email domain. You'll have to look up [How to set that up in your DNS](https://postmarkapp.com/developer/user-guide/inbound/inbound-domain-forwarding)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ujd50h9q1bntzhtoh1lx.png)

Okay so we have our quick setup. Postmark has great docs so check those out for more setup info. Though to note it's very important to have a custom inbound domain to accomplish what we want to do!

## Sending our email

Let's send our email to the user. What do we want to track how we will know it is them?

### Message-ID

The message id is a unique id for every email sent. It's a header that will be sent with any email to or from you. You can see the message id in Gmail by showing the original email. They can be any value but are typically formated as `<some-random-id@sender.com>` and email I got from twitter had the `Message-ID`: `<42.0B.41170.86A79BB5@twitter.com>`

### In-Reply-To

This email header is the starting point for how email clients thread emails. When you reply to an email your client puts the `Message-ID` of the email sent to you in the `In-Reply-To` header

### References

This header contains the `Message-ID`s of all the emails in the email thread. Every time a new email is send in a thread the `Message-ID` of the email being replied to is also appened to the `References` field

### Reply-To

When you send an email you can set a reply to address that differs from the to address you sent the email from. These headers are going to enable our workflow.

So let's send our email.

```javascript
// Require:
const postmark = require("postmark");

// Send an email:
const client = new postmark.Client("POSTMARK-SERVER-API-TOKEN-HERE");
const emailId = await generateAndStoreNewEmailId(commentThread, user);
client.sendEmail({
  "From": "sender@example.com",
  "To": "recipient@example.com",
  "Reply-To": `inbound+${emailId}@inbound.ourdomain.com`
  "Subject": "Test",
  "TextBody": "Hello from Postmark!",
  "Headers": [{Name: "Message-ID", Value: `<${emailId}@inbound.ourdomain.com>`}]
});

```

Okay so notice we set our Reply-To to an inbound email with an id we generated. We also want to store the user we are sending this email to and what comment thread.


Now we wait for a reply

## Handling the inbound email

When any email is sent to our inbound email domain we will get a post request to our webhook. The entire message is quite big [you can see it here](https://postmarkapp.com/developer/webhooks/inbound-webhook#inbound-webhook-data). We just care about a few fields. We will use them to lookup the context for this email and add the comment.


The reason we used the `inbound+${emailId}` in our `Reply-To` was because postmark is nice enough to parse that id off for us and add it to a field called `MailboxHash`.

Now we can lookup the thread this email is talking about from the emailId.

```javascript
const emailInfo = await getEmailInfo(inboundEmail.MailboxHash)
```

Postmark is also nice enough to parse the email body and give us just the reply text. We will use that for the commend body!

```javascript
const body = inboundEmail.TextBody;
```

Then we can do something.

```javascript
await createCommentInThread(
    emailInfo.commentThreadId,
    emailInfo.user,
    body
)
```

## Conclusion

We also stored the email id in the `Message-ID` so if for some reason we can't find our comment thread via `Reply-To` we can search the `References` or `In-Reply-To` fields to check as well.

This is the general strategy that [GitLab uses](https://docs.gitlab.com/ee/administration/reply_by_email.html)

This was a pretty high level overview but hopefully it helps you understand how easy it can be to make your app accept incoming emails!