PUBLIC WORK / 2026
MailForensics
strace for an email moving through your mail stack: join the evidence around one message, explain what each stage proves and stop the verdict where the evidence stops.
PACKAGE
Install it like a normal Python tool.
MailForensics is published on PyPI as mailforensics. Python 3.11+ is required; live journald and Postfix queue inspection are intended for Linux.
python -m pip install mailforensicsTERMINAL
What the CLI output looks like.

PROBLEM
Mail can disappear between layers that each look healthy on their own.
An application may say that it submitted a message while the useful evidence is spread across the application, Postfix, a milter or Rspamd, queue transitions and the final relay response.
The same message can acquire several identifiers on the way. Looking at each log separately makes it easy to miss a queued as handoff or to confuse “accepted by the next SMTP hop” with “delivered to the inbox”.
CORRELATION
Expand from identifiers, not from timestamp proximity.
MailForensics correlates Message-IDs, Postfix queue IDs, queue handoffs and application correlation IDs into one trace. It can combine classic mail logs, journald, structured JSONL events, Rspamd or milter evidence and live or saved postqueue -j state.
Timestamp proximity alone is never enough to merge two messages. That rule keeps the trace useful when a busy server is handling many similar deliveries at once.
WORKFLOW
Explain the pipeline, then keep the raw evidence available.
mailforensics explain gives a compact pipeline with stage timing and an evidence-based assessment. mailforensics trace keeps the full normalized timeline visible.
The same analysis can be emitted as JSON for automation or as a self-contained HTML report for incident notes. Parser adapters can also be added through the mailforensics.parsers plugin entry point without weakening the evidence model.
BOUNDARY
The verdict stops where the evidence stops.
If Postfix records status=sent, MailForensics reports that the configured SMTP, LMTP or local next hop accepted the message. It does not turn that into proof that a provider placed the message in a recipient's inbox.
A live queue entry proves that the queue item existed when the snapshot was captured. A missing downstream event is an evidence boundary, not automatic proof that the downstream component failed.
The tool is intentionally local and read-only: no database, no always-on daemon and no provider-side delivery claims that the supplied evidence cannot support. Built-in demo scenarios, doctor checks, stable exit codes and machine-readable output keep it testable and scriptable.
RELATED WORK
The same evidence-first rule applied to Linux routing.
route-explain
Read-only Linux routing forensics that treats the running kernel as the routing oracle.
PROJECT LINKS
Install the package, inspect the correlation model, or read the source.
PyPI is the install surface. GitHub keeps the correlation model, structured-event schema, usage documentation and source together.