Skip to content

feat: encode reported-on domain in VERP + add bounce handler - #442

Merged
thegushi merged 2 commits into
trusteddomainproject:developfrom
thegushi:feat/verp-domain-encoding
Aug 22, 2026
Merged

feat: encode reported-on domain in VERP + add bounce handler#442
thegushi merged 2 commits into
trusteddomainproject:developfrom
thegushi:feat/verp-domain-encoding

Conversation

@thegushi

Copy link
Copy Markdown
Collaborator

Summary

  • verp_sender() in opendmarc-reports now embeds the domain an aggregate report concerns into the VERP envelope sender, e.g. postmaster+example.com+dmarc-rua=aggregator.com@reporter.example.com, so a bounce reveals the domain without needing to look up which domain(s) route through a given RUA/RUF address. Forensic report VERP addresses are unchanged (--forensic relays a pre-formed AFRF message with no readily-available "domain being reported on").
  • Adds opendmarc-bounce-handler, a mail alias/pipe-target script that decodes a bounce's VERP-encoded recipient (from stdin DSN headers, or via --address for MTAs that can pass it directly), inserts the failing address into the suppressions table, and, when a domain was recovered, optionally prompts StaleMARC's checkDomain endpoint to retest that domain's DMARC reporting deliverability (--stale-notify, on by default). When no domain is encoded (forensic bounces, or older aggregate reports sent before this change), the address is still suppressed but no StaleMARC prompt is made.

Test plan

  • perl -c on the substituted script (placeholders filled in) passes with no errors
  • Manually exercised decode_verp/find_tag via --test --verbose against synthetic DSNs: domain-annotated tag, legacy no-domain tag, --address bypass, and empty input
  • autoreconf -f regenerates cleanly with the new .in files wired into configure.ac/reports/Makefile.am
  • ./configure correctly substitutes reports/opendmarc-bounce-handler{,.8} from the new templates

For aggregate reports, verp_sender() now embeds the domain the report
concerns ahead of the recipient tag, e.g.:

  postmaster+example.com+dmarc-rua=aggregator.com@reporter.example.com

This lets a bounce-processing script recover the domain directly from
a returned report's envelope sender, without needing to look up which
domain(s) route through a given RUA address -- useful for feeding
domain-specific signals (e.g. a StaleMARC checkDomain recheck) off of
delivery failures. Forensic report VERP addresses are left unchanged,
since --forensic relays a pre-formed AFRF message with no
readily-available "domain being reported on" of its own.
Adds a mail-alias/pipe-target script that decodes the VERP-encoded
recipient of a bounced DMARC report -- the failing RUA/RUF address, and,
for aggregate reports, the domain being reported on -- and:

  - INSERTs the failing address into the suppressions table, so later
    opendmarc-reports runs skip it automatically; and
  - optionally prompts StaleMARC's checkDomain endpoint to retest the
    recovered domain's DMARC reporting deliverability (--stale-notify,
    on by default).

The recipient is read from stdin (Original-Recipient/Final-Recipient/
X-Original-To/Delivered-To/To, in that order) for standard MTA pipe
delivery, or supplied directly via --address for MTAs that can pass the
original recipient as an argument. Decoding failures are logged and
ignored (exit 0) rather than treated as errors, so unrelated mail
delivered to the same alias can't cause further bounces.

Cross-referenced from opendmarc-reports(8) and db/README.schema, which
previously only described this as something "a bounce-processing
script" would need to do.
@thegushi
thegushi merged commit e0cbd49 into trusteddomainproject:develop Aug 22, 2026
2 checks passed
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.

1 participant