• Aug 11, 2026
  • 5 min read

Mailpit vs Mailtrap vs listmonk: What Each One Is Actually For

When I sat down to add email to my lead pipeline (confirmations, unsubscribes, a few welcome sequences), three names kept coming up: Mailpit, Mailtrap and listmonk. They sound interchangeable. They aren’t. They sit at three different layers, and one of them can’t deliver a single email to a real inbox.

This is the decision as I recorded it, plus the reasoning I’d want to remember next time.

Three layers, not three alternatives

ToolLayerWhat it doesWhat it doesn’t do
MailpitDevelopmentAn SMTP server that captures every message and shows it in a web UIDeliver anything. Nothing leaves the box
Mailtrap (sending)DeliveryHands your message to real inboxes over an API or SMTP, with authentication, logs and bounce handlingDecide who should receive what, or when
listmonkList managementSelf-hosted newsletter manager: subscribers, lists, double opt-in, campaigns, templatesDeliver by itself: it needs an SMTP relay underneath

The confusion comes from the fact that all three speak SMTP and all three show you emails in a browser.

Mailpit: a catcher, not a sender

I first thought of Mailpit as “the sender for development, and maybe production”. It’s a capture-only server: it accepts mail on port 1025, stores it, and shows it on 8025. That makes it perfect for:

And useless as a production sender, by design. In my homelab compose.yml it runs next to the lead hub, bound to 127.0.0.1 only, and I reach its UI with an SSH port forward. One practical note: check the host first. I already had a Mailpit on the default ports, and my first “test” email silently landed in the old one.

Mailtrap: the delivery layer

Mailtrap has two products under one name: a testing sandbox (similar in spirit to Mailpit) and Email Sending, which delivers real mail. Sending has two streams, and the split matters:

StreamForMy use
TransactionalOne-to-one messages someone triggeredThe double opt-in confirmation, sent by the Cloudflare Worker seconds after a form submit
BulkMarketing to a listDrip sequences, sent from the homelab

Separating them keeps a bad marketing day from hurting the delivery of confirmations. The Worker calls the transactional API with fetch; the homelab’s sender adapter calls the bulk API. Both are behind interfaces, so the provider is configuration, not code.

Why not listmonk

listmonk is genuinely good, and for a plain newsletter it would be my first recommendation. It gives you, out of the box, things I had to build: subscriber lists, double opt-in, unsubscribe pages, bounce processing, campaign scheduling.

It lost on three points for my case:

  1. Drips. listmonk is campaign-oriented: write a newsletter, send it to a list. Per-person sequences (“day 0, day 3, day 7 after you confirmed”) are not its strength.
  2. Another stateful service. It needs PostgreSQL, backups, upgrades and exposure for its public subscription and unsubscribe pages.
  3. Data in two places. My leads already land in Cloudflare KV from one forms Worker and are mirrored to SQLite on the homelab. With listmonk, every subscriber would have to be synced into its database and every unsubscribe synced back.

The DIY path reuses what already existed: the Worker handles double opt-in with signed links and unsubscribes at the edge, the homelab runs a small drip engine, and one suppression list covers both.

The cost of DIY: a checklist

Choosing DIY means owning the compliance features listmonk would have provided. I wrote them down as a definition of done before any production send:

  • confirmation email within seconds of subscribing
  • confirm and unsubscribe endpoints with signed tokens, tested
  • one-click unsubscribe plus a visible link in every marketing email
  • suppression honoured by every sender path, tested
  • bounce and complaint webhooks feeding the suppression list
  • SPF, DKIM and DMARC on every sending domain
  • privacy pages naming the email provider and describing double opt-in

If you can’t commit to that list, use listmonk (or a hosted newsletter tool) and let it carry those obligations.

Which domain sends

My root domains have mailboxes on a privacy-focused provider that I use for writing to people by hand. I didn’t want automated mail touching their reputation or their DMARC policy, so automated email goes out from a dedicated sending subdomain (planned: news.jalcocertech.com), shared by all my sites:

  • From: noreply@ on the sending subdomain, with a per-brand display name (“FOSS Engineer”, “JAlcocerTech”, …).
  • Reply-To: the brand’s real mailbox, so a reply reaches a human.

While testing I used a verified test subdomain I already had in Mailtrap; moving to production is a change of one setting once the new subdomain is verified.

SPF, DKIM, DMARC in one paragraph each

  • SPF lists which servers may send for the domain. The provider tells you which include: to add to the subdomain’s TXT record.
  • DKIM signs each message with a key published in DNS, so receivers can verify it wasn’t altered and really came from the domain.
  • DMARC tells receivers what to do when SPF/DKIM don’t align with the From: domain (none, quarantine, reject) and where to send reports.

Gmail and Yahoo require all three, plus one-click unsubscribe, for bulk senders. Putting them on a subdomain keeps experiments away from the root domain’s mail.

Takeaways

  • Mailpit is for seeing mail, Mailtrap is for delivering it, listmonk is for managing lists. Don’t compare them as alternatives.
  • Use transactional and bulk streams separately.
  • listmonk is the right answer for campaign newsletters; DIY made sense here because drips and an existing lead store were the core.
  • Send from a dedicated subdomain, reply to a real mailbox, authenticate with SPF, DKIM and DMARC.

Next: a pull-only homelab mirroring Cloudflare KV to SQLite without a tunnel.