mailreceipt is a small, deterministic CLI that demonstrates the ANCC discipline on one concrete problem: did this email actually arrive? It is a mirror, not an oracle — it finds the right log line, bounds its meaning honestly, and refuses to assert anything it cannot cite.
A law firm sent a deadline reminder to a client. Weeks later the client says: we never received it. The matter turns on whether that is true.
The firm runs its own Postfix mail server, so the answer is already written down — somewhere in /var/log/mail.log, among hundreds of thousands of unrelated lines. The traditional move is to ask a mail admin to grep the log and read the SMTP status back by hand. That works, but it produces a sentence in an email, not an artifact — and nothing stops a later reader from doubting it.
The tempting modern move is worse: hand the mailbox to an AI agent and ask it to "look into whether the email was delivered." Now the answer is a fluent paragraph with no cited evidence, produced by a model that read far more than it needed to.
mailreceipt is the third path: a deterministic command that produces a cited receipt.
The operator has the dropped email (a real .eml file, or even a pasted top-of-thread block) and the mail log. One command:
mailreceipt check reminder.eml --log /var/log/mail.log --case CASE-001
mailreceipt extracts the Message-ID and recipients from the email, parses the Postfix log into per-recipient delivery events, and correlates them — by message-id when present, otherwise by recipient and time window.
# Mail Delivery Receipt
**Case:** CASE-001
**Subject:** RE: URGENT: Our ref.: CASE-001
**Overall:** Bounced — hard-rejected, not delivered
| Recipient | Outcome | When | Evidence |
|--------------------------|--------------|------------------|----------|
| jdoe@exampleclient.test | delivered | 2026-06-05 15:41 | 250 2.0.0 OK |
| team@exampleclient.test | bounced | 2026-06-05 15:09 | 550 5.1.1 User unknown |
## Evidence (verbatim log lines)
- jdoe@... (matched by message_id):
Jun 5 15:41:55 mail01 postfix/smtp[20460]: 7C2D9E1F02:
to=<jdoe@exampleclient.test>, ... status=sent (250 2.0.0 OK: queued as D4E5F6)
- team@... (matched by message_id):
Jun 5 15:09:21 mail01 postfix/smtp[20441]: 7C2D9E1F02:
to=<team@exampleclient.test>, ... status=bounced
(... 550 5.1.1 ... Recipient address rejected: User unknown ...)
> A 'delivered' outcome means the remote mail server accepted the message
> (SMTP 2xx) at relay handoff. It does not prove a person read it. This
> receipt reports transport, not attention.
The answer is specific: one recipient was delivered, the other bounced with 550 5.1.1 User unknown. Every outcome carries the exact log line it came from. The disposition is Postfix's, quoted verbatim — there is no model in the loop inventing a verdict.
The same command with --format json emits the machine-readable artifact the operator attaches to the matter:
mailreceipt check reminder.eml --log /var/log/mail.log --case CASE-001 --format json > CASE-001.receipt.json
{
"artifact_type": "mail_delivery_receipt",
"tool": "mailreceipt",
"summary": "bounced",
"result": {
"message_id": "reminder-001-1509@example-ip.test",
"recipients": [
{
"recipient": "jdoe@exampleclient.test",
"outcome": "delivered",
"match_method": "message_id",
"response": "250 2.0.0 OK: queued as D4E5F6",
"time": "2026-06-05T15:41:55Z",
"citation": "Jun 5 15:41:55 mail01 postfix/smtp[20460]: 7C2D9E1F02: to=, ... status=sent (250 2.0.0 OK: queued as D4E5F6)"
},
{
"recipient": "team@exampleclient.test",
"outcome": "bounced",
"match_method": "message_id",
"response": "550 5.1.1 : Recipient address rejected: User unknown",
"time": "2026-06-05T15:09:21Z",
"citation": "Jun 5 15:09:21 mail01 postfix/smtp[20441]: 7C2D9E1F02: to=, ... status=bounced (... 550 5.1.1 ... User unknown ...)"
}
]
}
}
This is the ANCC payload: structured, every fact carrying its citation and match_method, ready for a case-management system, a ticket, or a claim to consume without re-reading the mailbox.
A receipt is only evidence if it cannot be quietly edited. Months later, anyone can re-check it against the source log:
mailreceipt verify CASE-001.receipt.json --log /var/log/mail.log
# OK: all 2 citation(s) present in /var/log/mail.log
Every cited line must still appear verbatim in the log. A fabricated or altered citation fails. The artifact is tamper-evident by construction — not because it is signed, but because it points at evidence that either exists or does not.
An honest artifact states its own boundary. mailreceipt reports transport, not attention, and says so on every receipt.
The mail log is sensitive — it lists who emailed whom. The ANCC story is not "let an agent read the mailbox and summarize." It is: gate what the agent may read, bound what it may claim.
When an agent drives the workflow, mailreceipt runs behind a file-access gate such as Bulwark. The gate controls what the agent may read; mailreceipt bounds what it may claim. The agent never touches the mailbox — only the specific evidence the task needs.
# The agent can touch the mail log ONLY through the gate,
# and its answer is cited by construction.
bulwark run --protect ./mail-evidence -- \
mailreceipt check reminder.eml --log mail.log --case CASE-123 --format json
The composition reads cleanly:
Bulwark limits what the agent may read
mailreceipt defines the cited artifact
agent operates the workflow, does not invent facts
operator decides what to attach, send, or escalate
No mailbox-wide rummaging. No uncited summary. No over-permissioned agent. The agent gets the minimum evidence, the gate enforces the boundary, and the output is an artifact another system can safely act on. That is the whole ANCC thesis in one minute: tools should produce cited, verifiable artifacts instead of fluent guesses.
The same engine runs as a mail filter, so a receipt is one forward away — no command line.
Wire an alias (e.g. receipt@yourfirm.test) to mailreceipt filter. A user forwards a sent email — the original attached — and the filter replies with the cited receipt. Authorization is the whole point of the design:
receipt@yourfirm.test ──► mailreceipt filter --envelope-from "$SENDER" --log /var/log/mail.log
│
├─ internal, MTA-authenticated sender only
├─ sender shares a configured team with the attachment's From/Sender
├─ the attachment's Message-ID must correlate to a real log line
└─ any gate unmet → silent drop, nothing disclosed
The attachment is a selector, never evidence: a forged or edited .eml for a message the server never sent returns not_found and reveals nothing. It is the cited-artifact discipline, delivered over email instead of a terminal.
mailreceipt is ANCC-compliant — four commands a person or an agent can discover and compose:
Scope today: Postfix syslog format and .eml input only, for self-hosted or relayed mail. It is a demonstration of the principle, not a commercial product — provider connectors (Gmail, Microsoft 365) and a server mode are possible future directions, not promises.