A fake inbox for development: your app sends mail to it instead of to real people, and you can read the message, check the HTML and see how it scores against spam filters.
Build me a development mail catcher that replaces Mailtrap: my application sends to it, nothing reaches a real person, and I can see exactly what would have arrived. STACK - Node 20+ with Fastify for the web interface - An SMTP server in the same process, or smtp-server as a library - SQLite through better-sqlite3, WAL mode, with FTS5 - Caddy in front, on a private network THE ONE RULE - Nothing is ever delivered onward. This server accepts mail and stores it, and there is no configuration anywhere that can make it relay to the internet - That is the entire safety property. Write it in the README, and make sure there is no code path — not a forwarding feature, not a 'send to real address' button — that could ever be switched on by accident - Accepting on a private interface only, by default THE DATA MODEL - inboxes: id, name, slug, username, password_hash, retention_hours, max_messages, is_shared - messages: id, inbox_id, from_address, from_name, to_json, cc_json, bcc_json, subject, message_id, in_reply_to, raw_path, size_bytes, html_body, text_body, headers_json, spf_result, dkim_result, dmarc_result, spam_score, received_at, read_at - attachments: id, message_id, filename, mime, bytes, path, sha256, is_inline, content_id - links: id, message_id, url, position — extracted, so a test can click one - checks: id, message_id, kind, status, detail — the analysis results - The raw message is always stored whole. Every view is derived from it, and it is what you fall back to when something looks wrong RECEIVING - Plain SMTP, with STARTTLS and authentication accepted but never required in a development context - Accept anything: malformed headers, a wrong From, an enormous attachment, an eight-bit body. The point is to see what your application actually sends, not to validate it - Multiple inboxes distinguished by the SMTP username, so several projects share one server - A per-inbox message cap and retention, applied by a sweeper READING - The message list with sender, subject, recipients and time, and unread state - Four views per message: rendered HTML, plain text, the raw source, and the headers as a table. All four, always — a bug in mail is usually visible in exactly one of them - Attachments listed and downloadable, with inline images resolved by content id in the HTML view - The HTML rendered inside a sandboxed iframe with no network access, so a remote tracking pixel is not fetched and an external stylesheet cannot leak that you opened it - A width switcher to see it at phone and desktop size THE ANALYSIS, WHICH IS WHY THIS BEATS A LOG FILE - Spam scoring with SpamAssassin or its rule set, with the individual rules that fired listed rather than only a number - SPF, DKIM and DMARC evaluated against what the message claims, so an authentication mistake is caught in development rather than by a spam folder in production - HTML checks: unsupported CSS for common mail clients, missing alt text, missing plain-text alternative, a subject that will be truncated, images without dimensions, a total size over the threshold where clients clip the message - Broken links checked with a request that does not follow anything into a private address - Every check is a rule with a plain-sentence explanation, and the rules are a file that can be extended THE API, WHICH IS WHAT TESTS USE - List messages in an inbox, get one, get its HTML, text and headers, delete it, empty the inbox - Wait-for-message with a filter and a timeout, which is the endpoint an end-to-end test actually needs - Extract a link matching a pattern — the confirmation link, the reset link — because that is what nine out of ten tests are doing - Tokens per inbox, and everything scoped SHARING - A shared inbox is the point: the whole team looks at the same messages rather than at one developer's machine - A read-only link to a single message, for showing somebody what arrived - No account needed to read a shared inbox on the internal network OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SMTP_PORT, SMTP_BIND, SESSION_SECRET, RETENTION_HOURS - Migrations on boot, each once - Bound to a private interface. If it must be reachable more widely, put it behind authentication — an open mail catcher is a place strangers store things - A disk watchdog and a working sweeper - Health endpoint that accepts and reads back one message WHAT MATTERS MOST Never relaying, and the wait-for-message endpoint. Get the safety property right first and prove there is no path out, then build the API your tests will use. Everything else is a mail client, and a mail client is easy. Give me the repository, the SMTP server, migrations, .env.example, the test-helper client, and a README with deploy steps and the no-relay guarantee stated at the top.
What you lose
- Spam scoring and blacklist checks against rule sets somebody keeps current
- HTML previews rendered across a range of real email clients
- A shared inbox the whole team can open, rather than one on a developer machine
If you would rather not build
- maildev, if you want it as an npm dependency
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $15/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
MailHog
$0The original local mail catcher; still fine for simple use.
mailhog/MailHogfree · open source
Why this verdict
our own opinion · changed only by a person
82/100
Verdict yes at 82: an SMTP sink and a message viewer are two libraries and an afternoon. Spam scoring is the one thing you would not reproduce, and most teams never look at it.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Mailtrap
answered from the record above
Is Mailtrap free?
No — the plan we track is $15 a month. Email Testing from around $15/month billed monthly; the sending product is priced separately by volume.
Can you replace Mailtrap by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 82 out of 100, build time one session. Read what you lose before you decide.
How much does Mailtrap cost?
$15 a month on Email Testing — $180 a year. Recorded 9 Aug 2026.
What do you lose by replacing Mailtrap?
Spam scoring and blacklist checks against rule sets somebody keeps current; HTML previews rendered across a range of real email clients; A shared inbox the whole team can open, rather than one on a developer machine. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Mailtrap?
Yes: Mailpit, MailHog. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

