Self-hosting temporary email usually starts the same way: someone installs a full mail stack, spends a weekend on Dovecot and SSL certificates, and ends up with a mail server that can do everything except what they actually wanted — a disposable inbox for signups. Here is the minimal architecture that works, and the parts you can safely skip.

The two-reason test

People self-host disposable email for exactly two reasons: privacy (you stop handing signups to a third-party inbox) and domain control (you can hand out addresses on your own domain, which public providers cannot offer). If neither reason applies to you, a public service is fine. If either does, keep reading.

The architecture that actually works

A working temp-mail server needs three moving parts, not the five a mail-course would have you believe:

  1. A mail transfer agent (MTA) on port 25. Postfix is the boring, correct choice. Its only job is to accept mail for your domains and hand it off.
  2. An application server with an embedded SMTP listener. Instead of writing mail to per-user maildirs, the app listens on a second port (say 2527) and receives everything Postfix relays to it.
  3. A web UI backed by a small database. Addresses are generated on demand; messages are stored and expire on a sliding TTL.

The glue is two Postfix settings. relay_domains lists every domain you own, and transport routes each one to smtp:[127.0.0.1]:2527. Postfix accepts the mail, the app decides whether the address exists. No Dovecot, no maildirs, no per-user provisioning.

What to skip (and why)

  • IMAP/POP3. Disposable inboxes are read over HTTP, not synced to a mail client. Skipping Dovecot removes most of the complexity.
  • Spam filtering. A temp address exists to receive verification codes. There is nothing to filter — you are the spam target by design.
  • Virus scanning. Same logic. Scan nothing, store the raw body.
  • DKIM/SPF for outbound. If you only receive, you can skip outbound signing entirely. Add it later if you want replies.

Storage: SQLite is enough

A single-file SQLite database handles millions of rows of short-lived messages. The pattern: each session gets an address and an expiry timestamp; a periodic sweep deletes expired rows. A sliding TTL (extend on read) keeps active inboxes alive without a second table. Rendering HTML mail inside a sandboxed iframe keeps the preview safe without a full sanitizer.

The DNS part

One MX record per domain, pointing at your server. If the domain lives on Cloudflare, add the MX with DNS-only mode (the grey cloud) — MX records do not need proxying. A few minutes of propagation and mail starts arriving.

When a single binary wins

A full stack (Mailcow, Mailu, Mail-in-a-Box) makes sense when you want real mailboxes for real people. For disposable inboxes, a small app — even one written with nothing but Node.js built-ins (node:http, node:net, node:sqlite) — runs on a $5 VPS and does the job in about a thousand lines. Fewer moving parts means fewer things to patch, which is the entire point of self-hosting.

If you want to see the minimal version running, the live demo at mail.howtageek.com is exactly this architecture: Postfix on port 25 relaying to an embedded SMTP server, SQLite storage, and a web UI you can use in ten seconds.