Skip to main content

DMARC Reports: How to Read Aggregate (rua) and Failure (ruf) Reports

By Tom Sather•Updated October 11, 2026•7 min read

DMARC aggregate reports are daily XML summaries of every IP sending as your domain and whether it passed. Here's how to read them and what to do with them.

On this page

DMARC aggregate reports (the rua reports) are XML files that receiving mail servers send you, usually once a day, summarizing every IP address that sent mail using your domain in the From line, how many messages it sent, and whether SPF, DKIM and DMARC passed. Failure reports (ruf) are per-message reports of individual failures, and most large providers don't send them. Read the aggregate reports by grouping rows by source, identifying each source, and checking whether its passes were aligned with your domain.

If you haven't published a DMARC record with a rua address yet, nothing gets sent. Start with What is DMARC? and the DMARC record generator.

Turning reports on

Reports go wherever your DMARC record's rua tag points:

v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com

A few things to get right:

  • Use a dedicated mailbox or a reporting service. A domain with real volume gets reports from many receivers every day. Don't point rua at someone's personal inbox.
  • Sending reports to another domain needs permission. If rua points outside your organizational domain (say, rua=mailto:reports@dmarc-vendor.example), receivers first look for a TXT record at example.com._report._dmarc.dmarc-vendor.example that starts with v=DMARC1. If the vendor hasn't published it, receivers won't send. Reporting services handle this for their customers, but it's the first thing to check if reports never arrive.
  • Give it a few days. Reports usually cover one UTC day and arrive the day after.

Not every receiver reports. Google sends aggregate reports daily. Microsoft 365 sends them for mail its own MX receives, and documents that it doesn't send them when a domain's mail is routed through another service first.

What an aggregate report looks like

Reports arrive as compressed XML attachments with a subject line like:

Report Domain: example.com Submitter: google.com Report-ID: 1234567890

Here's a trimmed example with one passing source and one failing source:

<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <report_id>1234567890</report_id>
    <date_range>
      <begin>1791158400</begin>
      <end>1791244799</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>example.com</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>none</p>
    <sp>none</sp>
  </policy_published>
  <record>
    <row>
      <source_ip>203.0.113.7</source_ip>
      <count>4210</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>pass</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>example.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>example.com</domain>
        <selector>s1</selector>
        <result>pass</result>
      </dkim>
      <spf>
        <domain>bounce.example.com</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
  <record>
    <row>
      <source_ip>198.51.100.24</source_ip>
      <count>312</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>fail</dkim>
        <spf>fail</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>example.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>crm-example.net</domain>
        <selector>k1</selector>
        <result>pass</result>
      </dkim>
      <spf>
        <domain>mail.crm-example.net</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>

The parts that matter

report_metadata says who sent the report (org_name) and the period it covers. The begin and end values are Unix timestamps in seconds.

policy_published is your DMARC record as the receiver saw it. If this doesn't match what you think you published, you have a DNS problem.

Each record is one row of traffic: a source IP and a message count, plus results.

policy_evaluated is the DMARC verdict. Its dkim and spf values are only pass or fail, and they mean aligned pass. disposition is what the receiver actually did: none, quarantine or reject. (Newer reports can also say pass, meaning "passed DMARC under an enforcing policy.") If the receiver overrode your policy, a reason element says why, with values like local_policy, mailing_list or trusted_forwarder.

auth_results shows the raw SPF and DKIM results and, crucially, which domain each one was for. This is where you see why something failed alignment.

Read the second record in the example again. In auth_results, DKIM passed and SPF passed. In policy_evaluated, both failed. That's not a contradiction: they passed for crm-example.net, not for example.com. That's the most common pattern you'll find, and it means a CRM is sending as you without custom DKIM. DMARC fail: why it fails and how to fix it covers the fix.

Reports produced under the new standard (RFC 9990) add an XML namespace and a few fields: np and testing in policy_published, discovery_method, and optional envelope_from and human_result elements. The structure above is otherwise the same.

How to work through your reports

Raw XML from dozens of receivers is not something to read by hand for long. Feed reports into a parser or reporting service that totals them by source. Then work through it like this:

  1. Sort sources by volume. Your top few sources account for most of your mail. Make sure they're clean first.
  2. Identify each source. Look up the reverse DNS of the IP, or which organization owns it. An IP that resolves to o1.mail.esp-example.net is your email provider. Group IPs by owner, since one service sends from many.
  3. Sort every source into one of four buckets:
BucketWhat it looks likeWhat to do
Yours, alignedpolicy_evaluated passes on DKIM (and ideally SPF)Nothing. Keep it that way
Yours, not alignedauth_results passes, but for the vendor's domainSet up custom DKIM and a custom Return-Path for that service
ForwardedKnown forwarders or university/alumni IPs; SPF fails, DKIM often still passesUsually nothing; aligned DKIM covers you
Not yoursUnrecognized IPs, failing everything, often low volume from many placesThat's spoofing. It's what your policy is for
  1. Fix the "yours, not aligned" sources one at a time. If a DKIM result shows fail for your own domain, the signature is breaking in transit; see DKIM fail: body hash did not verify. If SPF shows permerror, check your SPF lookup count.
  2. Watch for new sources. A source that wasn't there last month is either a new tool someone signed up for or a new spoofing campaign. Either way you want to know.
✨

Don't add unrecognized IPs to your SPF record to make failures go away. If you don't know what a source is, find out first. Authorizing a spoofer is worse than leaving it failing.

Once every legitimate source lands in the first bucket, you're ready to tighten your policy. See DMARC policy: none vs quarantine vs reject.

Failure (ruf) reports

Failure reports, sometimes called forensic reports, describe individual messages that failed. They're requested with the ruf tag:

v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-failures@example.com; fo=1

The fo tag controls when they're generated:

ValueGenerates a report when
0 (default)All mechanisms fail to produce an aligned pass
1Any mechanism fails to produce an aligned pass
dA DKIM signature fails, regardless of alignment
sSPF fails, regardless of alignment

Don't count on them. Google says Gmail doesn't support ruf, and Microsoft says Microsoft 365 doesn't send failure reports even when a valid ruf address is published. The receivers that do send them often redact parts of the message, because the reports can contain personal data: the failure reporting spec (RFC 9991) spends a good deal of space on privacy and recommends redacting message bodies and addresses.

When you do get them, they're useful for one thing aggregate reports can't show: the actual headers of a failing message, including the Subject and the full DKIM signature. That can identify a mystery source in minutes. Just be aware you're receiving other people's data and handle the mailbox accordingly.

When to get help

If your reports show significant volume from sources you can't identify, or you've fixed what you can and pass rates still won't move, it's worth having someone go through the reports with you.

FAQ

How often do DMARC reports arrive?

Usually once a day per receiver, each covering one UTC day. A domain with a lot of mail can get hundreds of reports a day from different receivers.

Why am I not getting any DMARC reports?

Check that your DMARC record parses and has a rua address, using the SPF, DKIM and DMARC checker. If rua points to another domain, that domain has to publish the _report._dmarc authorization record. And give it a couple of days.

Why does the report show DKIM pass in one place and fail in another?

auth_results shows whether DKIM passed for whichever domain signed. policy_evaluated shows whether it passed for a domain aligned with your From address. A pass for your provider's domain shows up as pass in the first and fail in the second.

Should I turn on ruf reports?

You can, but few large providers send them, and the ones that arrive may contain personal data. Aggregate reports are what you'll actually work from.

Sources

Related guides

Still stuck?

Some deliverability problems take an experienced eye to untangle. Tell me what you're seeing and I'll tell you what I'd check first. The first 30-minute call is free.