Reading a DMARC aggregate roof
Once DMARC asks for reporting, the world of the aggregate roof begins: every large receiver seeing mail for your domain periodically sends an XML report — bundled in a zip or gzip. In it stands not the content of messages, but who was travelling as your domain, via which routes, and with which authentication result.
The DMARC report reader unpacks that roof and reads it in your browser: reporter, policy, the dispositions (under which policy the mail fell), the authentication combinations and the source IPs where SPF and DKIM failed together. The roof itself is the document; what stands in it says what the reporter reported, not what the world is.
This article explains the columns and the order in which you read a roof — because a roof from p=none is something other than a roof after p=reject, and percentages without a denominator are noise.
What stands in it, and what rarely stands in it
A roof is an aggregate: counts per source IP, per header-from, per authentication combination, per disposition. Individual messages and headers do not stand in it — it is a count-list of traffic, not an inbox. That also means: what the roof does not report (mail that never reached a reporting receiver) is not zero, it is unknown.
Dispositions: the policy that held at that moment
Every line in the roof carries the disposition the receiver gave: none, quarantine, reject, or one of the specials (p_subcase, sp, fo). Under p=none you see the traffic; under p=reject you see which mail would then be blocked. The crossing between the two — and the counts under it — is exactly the material with which you close DMARC.
Authentication combinations: where it really fails
The fields `spf` and `dkim` per line show whether both layers computed, one failed or both failed. One failing layer is often a legitimate forwarding route; both failing is usually foreign mail. The meeting of both failers, grouped per source IP, is the list you want to see before you set p=reject — and (SPF, DKIM and DMARC explained stacks those layers again).
The roof as starting point, not as truth
Percentages in a roof are part of what the reporting receivers saw, not of what exists. A high reject-disposition after a policy change can be an old cache — therefore the report date stands in the report and not the date of today. See something strange, then test the records themselves (SPF recomputation, Mail security) before you widen or withdraw a policy.