Three approaches
There are three ways to get mail into your application, and the right one depends on how much of the mail system you want to own.
| Approach | How | Trade-off |
|---|---|---|
| IMAP polling | Log in to a mailbox and fetch new messages on a timer | Slow, fragile credentials, you parse MIME yourself |
| Your own mail server | Run Postfix/Exim, pipe mail to a script | Full control, but you run and secure an SMTP server |
| Inbound email API | MX points at a provider that posts JSON to your webhook | Least code; choose a provider that checks sender authentication |
What arrives
Swipe the diagram to see the rest
A parsed inbound message is more than a body. The pieces you will actually build on are the ones people forget to ask about:
An inbound email API gives you the envelope recipient, From, To, CC, subject, text and HTML bodies, headers and attachment metadata as JSON - no MIME parsing on your side.
Never trust the From line
This is the part that turns a reply-by-email feature into a vulnerability. The From header is written by whoever composed the message, and nothing about receiving it proves the claim. If an action in your application depends on who sent the mail, the authentication verdict is what you check - not the address.
Anyone can write any address in From. Before an automation acts on received mail - creating a ticket, resetting something, forwarding data - check that the sender's domain authenticated the message. Sendpository checks SPF, DKIM and DMARC on arrival and gives every message a sender_verdict of verified, failed, unverified or unchecked.
if (event.type === "email.received" && event.data.sender_verdict === "verified") {
await openTicket(event.data.from, event.data.subject, event.data.text_preview);
}Other things to get right
The rest is mostly about accepting that mail is messy and arrives more than once.
- Deduplicate - mail servers retry, so the same message can arrive twice.
- Treat HTML bodies as hostile: render them sandboxed, block remote images.
- Cap sizes and storage; one sender shouldn't be able to fill your database.