MailHog was the default answer for years: run one container, point your application at port 1025, read the captured mail on port 8025. It still works, and plenty of docker-compose.yml files still carry it — but it is no longer maintained, and Mailpit's own README says so in as many words: MailHog “is no longer maintained and hasn't seen active development or security updates for a few years now”. For a tool that parses untrusted MIME produced by your own application, the missing security updates are the part that matters.

The good news is that its successor listens on the same two ports, so for most projects this is a five-minute change in a compose file.

What MailHog did, and why its age matters

MailHog did three things well: it spoke SMTP (port 1025), it showed captured messages in a web UI (port 8025), and it exposed a JSON API so tests could read them. It also offered in-memory storage with optional MongoDB or file persistence, a mhsendmail replacement for PHP, live updates over EventSource and a chaos feature for failure testing.

None of that is broken. The problem is what happens around an unmaintained dependency:

  • No security updates. MIME parsing is exactly the kind of code that receives CVEs, and a catcher accepts mail from anywhere — a staging instance reachable from the internet is a service, not a toy.
  • Container images stop being rebuilt. Your pinned tag keeps working until the base image or the platform underneath it moves on.
  • The ecosystem moved. Mailpit (Go, single binary) became the direct successor, smtp4dev covers the .NET and Windows side, Mailcatcher and MailDev cover Ruby and Node — all actively developed.
  • Small features that save time (search, checks, pruning, POP3) exist only in the successors.

What to use instead

Tool What it is Why pick it
Mailpit Go, single binary or container, actively developed the closest thing to a drop-in replacement: same defaults, plus a REST API, HTML/link/spam checks, optional POP3, live web sockets and pruning
smtp4dev .NET, binary or container Windows-first teams and .NET stacks
Mailcatcher (Ruby) / MailDev (Node) run inside your own toolchain when you want the catcher as a gem or an npm dependency
This instance hosted privately by its operator nothing to run or maintain, SMTP and webhooks on one address, share links and a JSON export for scripts and AI assistants
Commercial sandboxes vendor-hosted teams that need SSO, shared inboxes, support and an SLA

Migrating from MailHog to Mailpit

Mailpit's defaults match MailHog's: SMTP on 1025, UI on 8025. In Docker Compose the change is the image name (and the volume path, if you mounted one) — the port mappings stay as they are, and your application configuration does not change at all, because it only knows a host and a port.

Three details differ once you are past the image tag:

  • Environment variables are prefixed MP_ instead of MH_. If you set MailHog's storage options, translate the two or three you actually use; if you never set any, there is nothing to do.
  • mhsendmail becomes mailpit sendmail, used the same way in php.ini or any other sendmail configuration.
  • Storage is a single data file (or memory), not MongoDB. If you relied on the Mongo backend to keep mail across restarts, that is the one thing to plan for.

Keep the old container commented out for a day, so going back costs one line.

What you gain and what you lose

Gained: active maintenance, a modern UI with search, HTML, link and spam checks, optional POP3 to pull captured mail into a real client, live updates over web sockets, a REST API for assertions, and automatic pruning (by default it keeps the most recent 500 messages) so a long-running instance does not grow forever. Mailpit also keeps a sendmail replacement and a chaos feature for testing SMTP failures.

Lost: MongoDB-backed storage. Everything else MailHog did — SMTP on 1025, UI on 8025, JSON API, persistence, failure testing — has an equivalent.

If you would rather not run anything at all

MailHog and Mailpit are services you own: a container, a volume, an upgrade path and somebody who notices when it stops. This instance is a different trade-off — SMTP and webhook capture on one address, no metering, nothing to maintain, with read-only share links and a JSON export so scripts and AI assistants can read the captured mail. It is not self-hostable, and that is exactly the point: if self-hosting is a hard requirement, run Mailpit.

Next steps