Skip to content

Mailinois

Follow every message through your Postfix relays.

Mailinois reads Postfix’s logs and follows each message by queue ID, from the app that handed it over to every recipient’s final answer. One Go binary on your own servers, never in the delivery path.

Postfix stays the mail server

Mailinois reads Postfix’s logs over syslog, follows every message by queue ID from the app that handed it over to each recipient’s final answer, and serves a dashboard of what happened: deliveries, deferrals, bounces, rejections and the queue.

It is never in the delivery path. If Mailinois or its database goes down, Postfix keeps accepting, queueing and delivering mail. (The optional milter for captures is set to accept mail whenever Mailinois is unreachable, so that holds with captures on too.)

The Mailinois overview: totals, outcomes by hour, recent failures, a live tail of deliveries, blocklists and sending domains.
Made-up traffic from two relays. Explore the interactive demo: search messages, follow a delivery and try a DNS failure, entirely in your browser.

What you get

How it fits together

Your apps hand mail to Postfix over SMTP and Postfix delivers it to the internet. rsyslog forwards Postfix’s log lines to Mailinois over TCP, and the optional milter hands it a copy of each message. Postfix servers on other networks run the agent, which ships over HTTPS. Mailinois keeps its data in SQLite or PostgreSQL and serves the dashboard, REST API, metrics and webhooks.

Each server shows up under its own hostname when its first line arrives, so adding a relay is pointing its rsyslog at Mailinois. How Mailinois follows a message.

Self-host in a minute

Run it with Docker Compose. The SQLite database lives on the volume.

compose.yaml
services:
mailinois:
image: ghcr.io/samjuk/mailinois
restart: unless-stopped
environment:
MAILINOIS_DATABASE_URL: sqlite:/data/mailinois.db
ports:
- "7480:7480" # dashboard and REST API
- "5514:5514" # syslog from your Postfix hosts, TCP
- "5514:5514/udp" # and UDP
volumes:
- mailinois-data:/data
volumes:
mailinois-data:

Then point each Postfix host’s rsyslog at it. The file ships in the repository and leaves Postfix’s own log alone.

Terminal window
sudo cp deploy/rsyslog/mailinois.conf /etc/rsyslog.d/
# set target="…" in that file to Mailinois's address, then:
sudo systemctl restart rsyslog

Open http://<your server>:7480 and the first messages appear as Postfix logs them. Prefer a binary? mailinois serve does the same, with SQLite in the working directory, andInstalling has a systemd unit and Kubernetes manifests. Postfix somewhere else, or only journald? Sending logs covers the agent, Vector and Fluent Bit.

To look around first, try the local preview with made-up traffic from thequick start. There is no login in this example, so read Authentication before the dashboard leaves a private network.

Built for privacy

  • Metadata by default

    Mailinois keeps what Postfix logs: addresses, queue IDs, Message-IDs, SMTP responses and the lines themselves. It sees no message bodies unless you turn captures on.

  • Captures are opt-in

    Headers only, or whole messages, through the milter. Captures have their own retention, seven days unless you change it.

  • On your own infrastructure

    One binary and one database on your servers. There is no hosted service in between.

What it stores, and how to keep it private.

Questions it answers, setups it fits