How to receive email with Postmark

Updated

Short answer

To receive email with Postmark, use a server's inbound stream. Every server gets an address like [email protected], and you can add one inbound domain by pointing its MX record at inbound.postmarkapp.com with priority 10 and entering the domain in the stream's settings. Postmark parses each message and POSTs it as JSON to the stream's webhook URL, retrying 10 times over about ten hours if your endpoint doesn't return a 200. To read that mail as people rather than code, connect Postmark to HelloBox.

Inbound servers and streams

In Postmark, mail is organized by server, and each server can have one inbound stream. The stream has its own address, [email protected], which works straight away, and you can attach one domain to it. Inbound domains are unique across Postmark, so a domain can only belong to one stream. (Postmark: configure an inbound server)

Plus addressing works too: mail to [email protected] arrives with 1234 in the MailboxHash field, which is handy for tying a reply to a ticket or account.

Check your plan first. Postmark's pricing page lists inbound email processing on the Pro and Platform plans.

Add the inbound domain and MX record

  1. Pick a subdomain for replies, such as reply.acme.com. Postmark recommends a separate subdomain so the main domain's mail stays where it is.
  2. Add an MX record for it pointing to inbound.postmarkapp.com with priority 10.
  3. In Postmark, open the server's inbound stream, go to Settings and enter the domain in Inbound domain. The Servers API takes the same value as InboundDomain.
  4. Enter your endpoint in the stream's Webhook field (InboundHookUrl in the API) and send a test message.
reply.acme.com.  MX  10 inbound.postmarkapp.com

(Postmark: inbound domain forwarding)

What the webhook sends

Postmark parses each message and POSTs one JSON document. A trimmed example:

{
  "From": "[email protected]",
  "FromFull": { "Email": "[email protected]", "Name": "Maria", "MailboxHash": "" },
  "To": "[email protected]",
  "Subject": "Re: Your receipt",
  "MessageID": "22c74902-a0c1-4511-804f-341342852c90",
  "TextBody": "Hi, the invoice shows the wrong company name...",
  "HtmlBody": "<p>Hi, the invoice shows...</p>",
  "StrippedTextReply": "Hi, the invoice shows the wrong company name...",
  "Headers": [{ "Name": "X-Spam-Score", "Value": "-0.1" }],
  "Attachments": [{ "Name": "invoice.pdf", "Content": "JVBERi0x...", "ContentType": "application/pdf", "ContentLength": 48213 }]
}
  • StrippedTextReply is the new text of a reply without the quoted history.
  • Attachments arrive base64 encoded, up to 35 MB in total.
  • RawEmail, the original message, is added only when the server's RawEmailEnabled setting is on. It's worth turning on if you want to keep an exact copy. (Server API)
  • Spam: Postmark accepts everything by default, spam included, and adds SpamAssassin headers such as X-Spam-Score. You can set a threshold and block senders with inbound rules. (Inbound blocking)

(Postmark: inbound webhook, parse an email)

Retries and securing the endpoint

If your endpoint returns anything but a 200, Postmark retries 10 times: after 1, 5, 10, 10, 10 and 15 minutes, then 30 minutes, 1, 2 and 6 hours. A 403 stops the retries. After the last attempt the message shows as Inbound Error, and you can retry it from the activity page or the Messages API.

The webhook is the only full copy you get, so save the message before you return 200, then process it. Inbound webhooks aren't signed. Postmark suggests basic auth in the URL (https://user:[email protected]/postmark/inbound) over HTTPS, and publishes the IP addresses its webhooks come from if you want an allowlist. (Webhooks overview)

Read the mail in HelloBox

  1. In Postmark, open Account, then API Tokens, and copy the Account API token.
  2. In HelloBox, choose Connect a provider, then Postmark, and paste it.
  3. Pick a server, or let HelloBox create one named HelloBox so its mail and stats stay apart from your app's.
  4. Turn receiving on for one domain. HelloBox sets the inbound domain and webhook, turns on the raw email, and shows the MX record, or adds it if your DNS is on Cloudflare.

HelloBox stores each raw email before it answers Postmark, and asks Postmark to retry messages that failed every attempt. The mail shows up as threaded conversations your team can share, assign and answer through your Postmark server. For the other approach, with routes, see receiving email with Mailgun.

Frequently asked questions

What MX record does Postmark use for inbound?
An MX record pointing to inbound.postmarkapp.com with priority 10, on the domain or subdomain you set as the stream's inbound domain.
How many inbound domains can a Postmark server have?
One. Each server has one inbound stream, and each stream takes one domain. Use another server for another domain.
How often does Postmark retry a failed inbound webhook?
10 times, from 1 minute up to 6 hours apart, over about ten hours. A 403 response stops the retries, and failed messages can be retried later.
Can I get the raw email from Postmark inbound?
Yes. Turn on RawEmailEnabled for the server, and the webhook includes the original message in a RawEmail field.
Are Postmark inbound webhooks signed?
No. Postmark recommends basic auth credentials in the webhook URL over HTTPS, and publishes the IP addresses its webhooks come from.