mailautopsy

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2026 License: MIT

README

mailautopsy

The same bytes in produce the same verdict out, forever, with no network and no service to call. Unknown is an answer this tool is willing to give.

mailautopsy reads a reported email message and reports named, evidence backed signals instead of an opaque reputation score. It never declares a message safe. The best result it produces is that none of the named checks fired on the evidence present.

Written in Go with the standard library only. No third party modules, no telemetry, no account.

The replay contract

  • Offline by default. Nothing leaves the machine unless you pass -live, which uses the system resolver and follows redirects.
  • Deterministic. A given message file produces the same report on any machine, today or in a year. The rules are in this repository and nowhere else.
  • Sealed. Every report carries a SHA256 digest over its own JSON. Every engine ships a Verify function to recheck a report, and the link and combined engines also ship VerifyAgainst to recheck a report against the original bytes.
  • Honest about ignorance. Insufficient evidence is a distinct outcome with its own exit code. It's never rounded up to clean or down to dangerous.
  • Untrusting of carried claims. An Authentication-Results header inside a saved file is trivial to forge, so it isn't trusted by default.

What it does

Three engines, each usable as a library or through the one CLI:

  • mailauth reads a raw RFC 5322 message and reports sender authenticity signals: Authentication-Results handling, From alignment, display name deception, reply address divergence, lookalike sender domains, the Received chain, and DNS backed signals when you ask for them.
  • linktriage reads a plain text snippet, an HTML fragment, or a full message and reports link and attachment danger signals: deceptive link text, userinfo tricks, punycode and digit swap lookalikes, dangerous schemes, bare IP hosts, shorteners, double extension attachment names, and more. It embeds a snapshot of the Public Suffix List so registrable domain comparisons are correct.
  • reportedemail composes both into one sealed, offline report with a single triage standing.

Install

With Go:

go install github.com/Parallax-Intelligence-Partnership-LLC/mailautopsy/cmd/mailautopsy@latest

With Docker, built from this repository and offline at runtime by construction:

make docker && docker run --rm --network none -v "$PWD:/work:ro" mailautopsy:dev report /work/message.eml

From a release: download the binary for your platform, together with SHA256SUMS and SHA256SUMS.bundle, then follow the verification steps below before you run it.

Use

Every example below runs against a synthetic fixture that ships in this repository, so the output is reproducible on any checkout.

Both engines composed into one sealed offline verdict:

mailautopsy report mailauth/testdata/spf_dmarc_fail.eml

Sender authenticity signals only, compared against the domain you expected to hear from:

mailautopsy mail -brief -expect example.com mailauth/testdata/display_name_deception.eml

Link and attachment signals read from standard input, as JSON for a script:

mailautopsy links -json < linktriage/testdata/full_walk.eml

mail exit codes: 0 authenticated, 2 suspect, 3 misaligned, 4 insufficient evidence, 1 usage or runtime error.

links exit codes: 0 no named signals, 2 dangerous, 3 suspect, 4 insufficient evidence, 1 usage or runtime error.

report exit codes: 2 danger signals present, 3 review signals present, 4 insufficient evidence, 1 usage or runtime error. It has no code that means clean, because it makes no such claim.

Pass -attest-authserv only after you have independently verified both that the file came unchanged from that receiving system and that the system strips forged headers claiming its own ID. Never copy the ID out of the suspicious message itself and treat that as verification.

Library

import "github.com/Parallax-Intelligence-Partnership-LLC/mailautopsy/reportedemail"

report, err := reportedemail.Analyze(raw, reportedemail.Options{
    ExpectedDomains: []string{"example.com"},
})

Browser

cmd/mailautopsy-wasm builds the offline composed analysis to WebAssembly and exposes it as one global function, so a pasted message can be checked entirely on the client. It performs no network request, no DNS lookup, and no link request.

make wasm

The function is __mailautopsyAnalyze(base64Message, expectedDomainsJSON) and it returns a JSON string.

Verify it yourself

Release artifacts are signed with cosign keyless signing, using a short lived GitHub OIDC identity rather than a stored key. Checking a download takes two commands, with the release tag in place of TAG:

cosign verify-blob SHA256SUMS \
  --bundle SHA256SUMS.bundle \
  --certificate-identity "https://github.com/Parallax-Intelligence-Partnership-LLC/mailautopsy/.github/workflows/release.yml@refs/tags/TAG" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

sha256sum --check --ignore-missing SHA256SUMS

The first command proves the checksum file came from a release build of this repository. The second proves the binary you hold matches that checksum.

Verifying a report rather than a binary is a separate thing, and it's the point of the tool: keep the original message file, keep the report, and rerun the analysis. Step by step:

# 1. Rerun the analysis on the message the report claims to describe.
mailautopsy report -json message.eml > replay.json

# 2. Same bytes in, same bytes out. Byte identical means same verdict,
#    same findings, same everything.
cmp report.json replay.json

# 3. The report is bound to the exact message bytes. Recompute the digest
#    yourself and compare it to message_sha256 inside the report.
shasum -a 256 message.eml

If cmp is silent and the digests match, the report is exactly what this analyzer says about exactly that message. If the message file changed by one byte, message_sha256 will not match it. If the report was edited after the fact, its report_sha256 will not match its own body.

Test fixtures

Every fixture in this repository is synthetic; no captured real mail exists anywhere in the corpus. Legitimate addresses use the reserved example.com, example.net, example.org, and .example names. Hostile fixtures also use typosquat domains such as paypa1.com as pretend senders, because detecting exactly that shape is the tool's job. Real brand names appear only as the protected target of a lookalike check, never as a sender and never as captured mail.

Public Suffix List

linktriage/data/public_suffix_list.dat is an unmodified snapshot of the Mozilla Public Suffix List, used under the MPL 2.0. See the README beside it.

License

MIT. Copyright 2026 Parallax Intelligence Partnership.

https://postmortem.report

Directories

Path Synopsis
cmd
mailautopsy command
Command mailautopsy inspects a reported email message and reports named, evidence backed signals instead of an opaque reputation score.
Command mailautopsy inspects a reported email message and reports named, evidence backed signals instead of an opaque reputation score.
mailautopsy-wasm command
Command mailautopsy-wasm builds to an empty command on host platforms.
Command mailautopsy-wasm builds to an empty command on host platforms.
internal
version
Package version reports the build identity of mailautopsy binaries.
Package version reports the build identity of mailautopsy binaries.
Package linktriage inspects one operator supplied input, either a plain text snippet, an HTML fragment, or a full RFC 5322 email message, and reports named, evidence backed danger signals about the links and attachment names it finds.
Package linktriage inspects one operator supplied input, either a plain text snippet, an HTML fragment, or a full RFC 5322 email message, and reports named, evidence backed danger signals about the links and attachment names it finds.
Package mailauth inspects one raw RFC 5322 message and reports named, evidence backed authenticity signals for a technician deciding whether a sender appears spoofed or blocklisted.
Package mailauth inspects one raw RFC 5322 message and reports named, evidence backed authenticity signals for a technician deciding whether a sender appears spoofed or blocklisted.
Package reportedemail composes the deterministic mail authentication and link triage engines into one sealed, offline report for a raw RFC 5322 message.
Package reportedemail composes the deterministic mail authentication and link triage engines into one sealed, offline report for a raw RFC 5322 message.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL