Sending logs and DMARC aggregate reports count different events. A sender may record an application submission, a recipient attempt or remote acceptance; a report groups receiver observations involving a domain. Choose a comparable population before subtracting one total from the other.
Write down what each counter means
References: RFC 9990 §3.1.1.8, RFC 9990 §3.1.
For the sender, document whether the count represents messages, recipient deliveries, attempts or successful SMTP transactions. Establish the time basis and handling of retries. For reports, preserve policy domain, header From domain, reporter, interval and row count. Sum row counts rather than counting XML rows as messages.
Reports are not restricted to mail your authorized services intended to send. Spoofed use of the domain and indirect routes can contribute observations, while non-reporting destinations and lost reports reduce visibility. A raw difference is therefore not a measure of lost legitimate mail.
Align scope before comparing
References: RFC 9990 §3.1.2, RFC 9990 §3.5.4.
Select the same author-domain scope and overlapping observation period. Separate policy-domain grouping from the actual header From domains within it. Use known destination relationships where available, but do not pretend an aggregate row maps to an individual outbound message.
Retain only one counted copy of known duplicate reports. Keep unresolved overlaps separate and note late arrivals. Record sender-log retention gaps and whether internal-only traffic is included. These details can change the comparison more than the authentication result itself.
Build an explanation bridge
Illustrative case: sender records show 1,000 recipient deliveries, but only 800 of those recipient deliveries target the receiver cohort represented in the collected reports. Reports contain 820 observations, including 20 observations not attributed to those approved deliveries. The naive comparison suggests a shortage of 180. The scoped comparison explains the difference as 200 unobserved deliveries and 20 additional reported observations. This is synthetic arithmetic, not a claim that aggregate data alone proves which 20 messages were abusive.
Use categories with evidence: outside receiver coverage, outside interval, duplicate receipt, suspected unauthorized traffic and unexplained. Do not force an unexplained residual into spoofing or delivery loss just to balance the spreadsheet.
Use the right evidence for the remaining question
For a missing customer message, investigate recipient-level delivery records and authorized message samples. For a new source in reports, investigate ownership and authentication identities. For a metric discrepancy, preserve the query definitions and raw inputs so another analyst can reproduce the totals.
Close the reconciliation with matched scopes, explained adjustments and an explicit residual. A nonzero residual can be an honest result when the systems do not observe the same population.
Retain the reconciliation worksheet
Keep one line per adjustment with its sign, unit, evidence and confidence. Avoid adding message-level counts to recipient-level counts even when both columns are called volume. Record whether a sender export reflects final outcomes or an intermediate snapshot, and preserve the export time. Ask a second analyst to reconstruct one small interval manually before relying on a recurring query. Where exact linkage is unavailable, state that limitation in the worksheet rather than implying that an arithmetic match proves identical underlying messages.
Continue the investigation
Use the aggregate-report walkthrough to interpret the underlying fields and the alignment diagnosis guide when a raw authentication pass does not satisfy DMARC.
Executed synthetic evidence
This locally rerun offline fixture makes the comparison population explicit. The input has two approved services and supplied recipient-coverage classifications; these classifications are synthetic facts, not conclusions drawn from source IP. Python sums the following retained rows and checks the bridge with assertions.
- Service: Billing; Sender recipient deliveries: 600; Covered receiver cohort: 500; Outside coverage: 100; Reported legitimate: 500; Unclassified observations: 10; Report total: 510; Residual: 0
- Service: Alerts; Sender recipient deliveries: 400; Covered receiver cohort: 300; Outside coverage: 100; Reported legitimate: 300; Unclassified observations: 10; Report total: 310; Residual: 0
- Service: Total; Sender recipient deliveries: 1,000; Covered receiver cohort: 800; Outside coverage: 200; Reported legitimate: 800; Unclassified observations: 20; Report total: 820; Residual: 0
Each residual is report total minus covered deliveries minus unclassified observations. The executed total is 820 - 800 - 20 = 0. The larger bridge is 1,000 - 200 + 20 = 820. The 20 are labelled unclassified, not confirmed spoofing. This clean synthetic match does not prove exact linkage in real aggregate data. A production worksheet needs actual recipient-unit logs, receiver-coverage evidence and verified service mappings. Retain any unmatched residual instead of borrowing the fixture's zero.
Keep the result within the tested scope
The supplied local demonstration verifies only its small synthetic parser, supplied stage inputs and calculations. No real DNS authorization, SMTP delivery, collector migration, provider participation or production database behavior was tested. Original inputs remain archived, and any live comparison needs its own protected evidence and accountable approval.