Repository navigation
How Reports Are Attributed to a Domain
TL;DR: each record in a report is attributed by its own header_from,
not by the report's overall policy_published/domain — so subdomain
traffic doesn't get silently folded into the parent's stats.
A single DMARC aggregate report can legitimately bundle mail for an
organizational domain and any number of its subdomains under one
policy_published/domain — RFC 7489 §7.2 keeps that report-level field and
each record's own header_from deliberately separate, precisely because
subdomain mail is evaluated under the parent's inherited policy.
Attributing every record in a report to the report's own domain (the naive
reading) folds all of that subdomain traffic permanently into the parent's
stats.
| Scenario | Where the record's volume ends up |
|---|---|
header_from matches a registered domain exactly |
That domain |
header_from is a subdomain of a registered domain, itself unregistered |
The nearest registered ancestor (visible under Detected Domains as a suggestion to register it) |
header_from matches no registered domain at all, no registered ancestor either |
Nowhere yet — surfaced as a detected domain |
Every record is matched by its own header_from at ingestion. The
report-level domain (policy_published/domain) is still tracked
separately, for report browsing and policy-stability calculations — just
not for per-record attribution.
A report addressed to example.com contains 100 records: 80 with
header_from: example.com, 20 with header_from: mail.example.com
(a registered subdomain). Attributed by report domain alone, all 100 would
count toward example.com's pass rate. Attributed by header_from
(what YADT does): 80 count toward example.com, 20 toward
mail.example.com — each domain's dashboard reflects its own traffic.
Before any of the above, a report has to be tied to an organization:
- An organization's own mailbox (Microsoft 365, connected in Settings): everything that arrives there belongs to that organization.
-
The operator-hosted mailbox (a
+tagaddress per domain, shared by every organization that uses one): each email is matched on the hosted address in itsTo:header. Report senders always put therua=address there — a record listing several addresses gets either one email with all of them inTo:or one email per address, and both match.
The one setup that doesn't match: forwarding reports from another
address to a hosted address. A forward keeps its original To:, so the
hosted address isn't in it and the report is skipped as unmatched (counted
in the worker log's hosted reports poll: … unmatched line). Point rua=
at the hosted address directly instead of forwarding to it.
Reporting addresses are public — they're published in DNS — so anyone can email a report to one. For every report email, three facts are recorded from the headers Exchange Online adds:
- Origin: whether it came from outside your Microsoft 365 organization. Mail from inside never gets Exchange's sender check.
-
DMARC result of the email itself (from the topmost
Authentication-Resultsheader, the one the receiving server adds). -
Sender matches reporter: whether the sender's domain belongs to the
reporter the report names (
noreply-dmarc-support@google.com→google.com). A few large senders use a different domain on purpose and are listed as known aliases, such as Yahoo (dmarc.yahoo.comforyahooinc.com).
Settings → General → Report sender check decides which reports count:
| Setting | Counts | Trade-off |
|---|---|---|
| Standard (default) | Everything except reports that failed DMARC, came from someone other than the reporter they name, or were sent from inside your organization | Genuine reports only drop out if they fail DMARC, which is rare |
| Strict | Only reports whose sender passed DMARC (and matches, from outside) | Best protection against fake reports; also drops genuine reports from senders without a DMARC record |
| Off | Every report | Nothing is left out; anyone who knows your reporting address can add fake data |
Changing the setting re-evaluates reports you already received. Reports ingested before v0.1.5-beta14 have no recorded facts and always count.
Left-out reports are kept, not deleted. Each domain's Reports and TLS reports pages show how many were left out, with a Review list saying why for each.
A counted report also replaces an earlier left-out one with the same report ID, so a forger can't block a genuine report by sending a fake copy first.
Report drill-down, and each domain's DMARC pass-rate feeding its domain rating.
- Report Ingestion Troubleshooting
- Detected Domains: Finding Unregistered Senders
- DMARC Subdomain Policy Inheritance
← Back to the README · Live demo · Report an issue · MIT licensed
- Quick Start: Docker Compose
- Deploying with Portainer
- Deploying on Azure
- Configuration Reference
- Onboarding an Organization
- IMAP Mailbox
- Google Workspace Mailbox
- Sign-in Providers
- Multi-Tenancy & RLS
- DMARC Subdomain Inheritance
- Report Attribution
- SPF Conditional Mode
- Detected Domains
- DNS Check Scheduling
- Domain Rating
🏗️ Architecture
🗺️ Roadmap