DMARC aggregate reports (also called "rua" reports) are sent daily by receiving mail servers to the address specified in your DMARC record. They contain authentication results for all email they received claiming to be from your domain, grouped by source IP address. Reading these reports correctly is how you identify misconfigured sending services, detect spoofing attempts, and confirm that legitimate senders are authenticating correctly before advancing your DMARC policy toward enforcement.

RUA
aggregate report — sent daily, shows pass/fail per IP/domain
RUF
forensic report — per-message failure, contains email samples
XML
DMARC report format — parse with dmarcian or EasyDMARC
24h
typical report delivery delay after the reporting period

DMARC Aggregate Report — Pass/Fail Distribution Example (1 day, 45K messages)

38,200DKIM+SPF p…4,600DKIM pass …1,200SPF pass o…800Both fail200Policy none

What DMARC Aggregate Reports Contain

Each aggregate report covers one 24-hour reporting period and contains:

  • The reporting organisation (Gmail, Microsoft, Yahoo, etc.)
  • The date range covered by the report
  • Your domain and the DMARC policy they applied
  • One record per source IP that sent mail claiming to be from your domain
  • For each source IP: message count, disposition (what the ISP did), and authentication results (SPF pass/fail, DKIM pass/fail, alignment)

Reports arrive as ZIP-compressed XML files attached to email. Major ISPs that send DMARC aggregate reports: Google (Gmail), Microsoft (Outlook/Hotmail/Live), Yahoo, Comcast, Apple, and many others. You'll typically receive reports from 5–15 different organisations daily once your DMARC record is active.

XML Report Structure Decoded

<?xml version="1.0" encoding="UTF-8"?>
<feedback>
  <!-- Who sent this report and when -->
  <report_metadata>
    <org_name>Google Inc.</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <report_id>17564896223625039812</report_id>
    <date_range>
      <begin>1744588800</begin>  <!-- Unix timestamp = April 14 2026 00:00:00 UTC -->
      <end>1744675199</end>    <!-- April 14 2026 23:59:59 UTC -->
    </date_range>
  </report_metadata>

  <!-- Your DMARC policy at time of reporting -->
  <policy_published>
    <domain>yourdomain.com</domain>
    <adkim>r</adkim>   <!-- DKIM alignment: r=relaxed, s=strict -->
    <aspf>r</aspf>    <!-- SPF alignment: r=relaxed, s=strict -->
    <p>quarantine</p>  <!-- Policy: none, quarantine, reject -->
    <pct>100</pct>    <!-- Percentage subject to policy -->
  </policy_published>

  <!-- One record per source IP -->
  <record>
    <row>
      <source_ip>209.85.218.47</source_ip>   <!-- Gmail outbound IP -->
      <count>1,247</count>                    <!-- Messages from this IP -->
      <policy_evaluated>
        <disposition>none</disposition>       <!-- What ISP did: none/quarantine/reject -->
        <dkim>pass</dkim>                     <!-- DKIM aligned pass -->
        <spf>pass</spf>                       <!-- SPF aligned pass -->
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>yourdomain.com</header_from>  <!-- From: header domain -->
    </identifiers>
    <auth_results>
      <dkim>
        <domain>yourdomain.com</domain>  <!-- d= in DKIM signature -->
        <selector>mail</selector>        <!-- s= selector -->
        <result>pass</result>
      </dkim>
      <spf>
        <domain>yourdomain.com</domain>  <!-- Return-Path domain -->
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>

Key Fields: What Each Means

source_ip: The IP address of the server that delivered the message. Look up this IP with reverse DNS and whois to identify which service it belongs to. Google IPs (209.85.x.x, 74.125.x.x), Microsoft IPs (40.x.x.x, 52.x.x.x), SendGrid IPs (167.89.x.x), etc. If you see an IP you don't recognise, that's potentially spoofing — investigate.

DMARC aggregate report XML — key sections (annotated)
<?xml version="1.0"?>
<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <date_range>
      <begin>1743984000</begin>  <!-- Unix timestamp -->
      <end>1744070400</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>yourcompany.com</domain>
    <p>quarantine</p>  <!-- current policy -->
    <sp>quarantine</sp>
  </policy_published>
  <record>
    <row>
      <source_ip>52.218.x.x</source_ip>  <!-- Amazon SES IP -->
      <count>14823</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>pass</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <row>
      <source_ip>198.51.100.42</source_ip>  <!-- Unknown sender! -->
      <count>341</count>
      <policy_evaluated>
        <disposition>quarantine</disposition>
        <dkim>fail</dkim>
        <spf>fail</spf>
      </policy_evaluated>
    </row>
  </record>
</feedback>

count: Number of messages from this source IP during the reporting period. A legitimate high-volume sender will show large counts. A spoofing attempt often shows small counts (1–10 messages) from many different IPs.

policy_evaluated → disposition: What the receiving ISP actually did with the messages from this IP. Values: none (delivered normally), quarantine (sent to spam), reject (hard rejected). Even if your DMARC policy is p=quarantine, the disposition might still be "none" if the receiving ISP doesn't honour the policy fully.

policy_evaluated → dkim: Whether DKIM passed and aligned (the DKIM signing domain matched your From: header domain). "pass" = DKIM authenticated and aligned. "fail" = either no DKIM signature, signature failed verification, or domain didn't align.

policy_evaluated → spf: Whether SPF passed and aligned (the Return-Path domain matched your From: header domain). "pass" = SPF authenticated and aligned. "fail" = SPF failed, or passed but didn't align.

auth_results → dkim/spf: The underlying authentication results, separate from alignment. A DKIM result of "pass" here means the signature is cryptographically valid — but if the signing domain doesn't match the From: header domain, policy_evaluated → dkim will still show "fail" due to alignment failure.

Interpreting Failure Patterns

Pattern 1: Large count from known ESP, DKIM pass but SPF fail

source_ip: 167.89.0.45 (SendGrid)
count: 5,000
policy_evaluated: dkim=pass, spf=fail
auth_results: 
  dkim: domain=yourdomain.com result=pass
  spf: domain=sendgrid.net result=pass  <-- SPF passes for sendgrid.net, not yourdomain.com

Diagnosis: SPF alignment failure — your ESP's Return-Path domain is sendgrid.net, not yourdomain.com. DMARC passes because DKIM is aligned. This is fine if DKIM is configured, but you should also configure a custom bounce domain to achieve SPF alignment for defence-in-depth.

Pattern 2: Unknown IP, small count, both fail

source_ip: 5.188.210.34 (Russian hosting provider)
count: 12
policy_evaluated: dkim=fail, spf=fail
disposition: quarantine (or reject if p=quarantine/reject)

Diagnosis: Spoofing attempt. Someone is sending email using your domain in the From: header without your authentication. With p=quarantine or p=reject, these messages are being handled correctly. This is the DMARC policy working as intended — document it and continue.

Pattern 3: Your own IP, DKIM fail

source_ip: 203.0.113.10 (your sending IP)
count: 850
policy_evaluated: dkim=fail, spf=pass
auth_results:
  dkim: result=fail  <-- signature failed verification

Diagnosis: DKIM signing is broken on this IP. Either the DKIM key doesn't match the DNS record, the signing configuration is wrong, or a message modification in transit is breaking signatures. Investigate immediately — your mail from this IP is at DMARC risk if SPF alignment also fails.

Pattern 4: Known service, count=0 for DMARC pass

source_ip: 198.21.0.30 (your email marketing platform)
count: 2,100
policy_evaluated: dkim=fail, spf=fail
auth_results:
  dkim: result=none   <-- no DKIM signature at all
  spf: domain=emailplatform.com result=pass  <-- SPF passes for platform, not your domain

Diagnosis: Your email marketing platform is not DKIM-signing with your domain, and SPF alignment fails because they use their own Return-Path. This means all mail from this platform fails DMARC. If your DMARC policy is p=quarantine or p=reject, this mail is being filtered or rejected. Fix: Configure DKIM signing with your domain in the platform settings.

Tools to Visualise DMARC Reports

Reading raw XML is tedious and error-prone at scale. These tools aggregate and visualise DMARC report data:

  • Postmark DMARC (free): dmarc.postmarkapp.com — simple, clean dashboard, unlimited domains, free tier, excellent for getting started
  • dmarcian (paid, industry standard): dmarcian.com — most detailed source analysis, traffic sources identified by name, policy advancement recommendations
  • Google Postmaster Tools (free, Gmail only): postmaster.google.com — Gmail-specific DMARC data plus spam rate and reputation dashboards
  • EasyDMARC (tiered pricing): easydmarc.com — broad ISP coverage, automated alerts, good for teams
  • Valimail (enterprise): valimail.com — enterprise-grade, automated sender discovery and policy management

For most organisations starting DMARC implementation, Postmark DMARC (free) plus Google Postmaster Tools (free) covers the essential visibility without cost. Once you're moving toward enforcement and need detailed source identification, dmarcian or EasyDMARC add significant value.

What to Look For Every Week

Weekly DMARC report review checklist:

  • Any new source IPs appearing for the first time — identify them and determine if they're legitimate senders or spoofing attempts
  • Failure counts from known legitimate senders — if a service you use is failing DMARC, fix the authentication configuration before advancing policy
  • Disposition showing "quarantine" or "reject" for your own IPs — means your policy is blocking your own mail
  • Total DMARC pass percentage — should trend upward as you fix failing sources; target 95%+ before advancing to p=quarantine
  • Small-count entries from unknown IPs — may be spoofing attempts; note them but don't over-investigate individual entries