Sending email is straightforward. Receiving it reliably is a different story.
Most developers have sent emails programmatically — it's a well-documented problem with plenty of APIs. But when you need your application to receive inbound email, you quickly discover it's a different challenge entirely.
Here's why developers typically spend 4-6 weeks building email receiving infrastructure — and why most regret it.
To receive email, you need an SMTP server listening on port 25. This means:
Note: Many cloud providers block port 25 by default. AWS, GCP, and Azure all require special requests to unblock it for new accounts.
Email messages use MIME (Multipurpose Internet Mail Extensions), a format designed in 1992. It's surprisingly complex:
Content-Type: multipart/mixed;
boundary="----=_Part_12345"
------=_Part_12345
Content-Type: multipart/alternative;
boundary="----=_Part_67890"
------=_Part_67890
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Hello, this is the plain text version.
------=_Part_67890
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64
PGh0bWw+PGJvZHk+SGVsbG8sIHRoaXMgaXMgSFRNTC48L2JvZHk+PC9odG1sPg==
------=_Part_67890--
------=_Part_12345
Content-Type: application/pdf; name="document.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="document.pdf"
JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlL1BhZ2UvUGFyZW50...
------=_Part_12345--This is a simple email with plain text, HTML, and one attachment. Real-world emails get far more complex with nested forwarded messages, inline images, and inconsistent encoding.
Handling email attachments reliably requires dealing with:
Base64, quoted-printable, uuencode, or raw binary depending on the client
Images can be inline (CID references) or traditional attachments
RFC 2231 encoding for non-ASCII filenames, often implemented incorrectly
Large attachments can exceed memory limits during processing
You'll spend weeks handling edge cases: what happens when Gmail sends an attachment one way, Outlook another, and Apple Mail a third?
The moment you accept email from the internet, you inherit email security problems:
Unlike HTTP requests that retry quickly, email has specific delivery expectations:
Your application's SLA now includes email infrastructure. A database migration that takes your app down for 10 minutes? That's 10 minutes of queued or bounced emails.
Email from Gmail looks different than email from Outlook, which looks different than email from Apple Mail, which looks different from a 20-year-old enterprise server.
You'll encounter edge cases constantly:
Instead of building and maintaining email infrastructure, use a service that handles it for you. With Mailhooks, you receive inbound email as simple webhooks: