Skip to content

feat: add seal-only mode to the seal CLI command#119

Open
hathaway wants to merge 1 commit into
postalsys:masterfrom
mailprotector:seal-with-auth-results
Open

feat: add seal-only mode to the seal CLI command#119
hathaway wants to merge 1 commit into
postalsys:masterfrom
mailprotector:seal-with-auth-results

Conversation

@hathaway

Copy link
Copy Markdown

Summary

The library already supports the documented "authenticate first, modify, then seal" pattern via sealMessage(message, { ..., authResults, cv }), but the seal CLI command always re-authenticates the message internally via authenticate(). That recomputed verdict is wrong when the message has been modified after the original authentication (e.g. an MTA that verified the pristine inbound message, then injected banners or rewrote MIME before relaying).

This PR exposes the existing library capability on the CLI: new opt-in options let mailauth seal embed a caller-provided Authentication-Results value and seal without performing any authentication checks or DNS lookups.

New options on mailauth seal

  • --auth-results <value>Authentication-Results value to embed in ARC-Authentication-Results (the part after i=N;), used as-is
  • --auth-results-file <path> — same, read from a file (convenient for long/folded values); conflicts with --auth-results
  • --cv <none|pass|fail> — chain validation status for the ARC-Seal cv= tag, defaults to none
  • --instance <n> — explicit ARC instance number; defaults to the next instance from any existing chain, or 1

When either auth-results option is set, the handler calls sealMessage() directly. The stdout contract is unchanged: the three ARC-* headers, then the message body unless --headers-only is set. All new flags are long-only to avoid clashing with the existing short aliases.

Backward compatibility

Without the new options the command runs the existing authenticate()-and-seal path unchanged — the new mode is strictly opt-in. No library code is touched; only lib/commands/seal.js, the yargs builder in bin/mailauth.js, and cli.md.

Tests

New CLI tests (test/commands/seal-test.js) spawn the real binary with a preload script (test/fixtures/deny-dns.js) that intercepts every dns.promises resolver and reports any lookup, proving the seal-only path is fully offline:

  • ARC-Authentication-Results echoes the supplied value verbatim (inline and from file) with zero DNS lookups
  • the produced seal round-trips: authenticate() with a mock resolver validates the chain as arc=pass
  • an existing ARC chain is extended at the correct next instance with cv=pass
  • explicit --instance is honored
  • --auth-results and --auth-results-file together is rejected
  • default mode still authenticates and seals as before (run offline via --dns-cache)

Full suite passes (682 tests), lint clean.

🤖 Generated with Claude Code

Add --auth-results, --auth-results-file, --cv and --instance options to
the seal CLI command. When an Authentication-Results value is provided,
the message is sealed with it as-is via sealMessage() instead of being
re-authenticated, performing no DNS lookups. Useful when the message was
authenticated at an edge MTA and modified before sealing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Jun 12, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@hathaway hathaway marked this pull request as ready for review June 12, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants