New guide: how to warm up a dedicated IP without hurting your reputation. Read now →
Log in
MigoSMTP
Domains and DNSUpdated 13 Oct 2026

How to Read DMARC Aggregate Reports and Safely Move to p=reject

A DMARC aggregate report is a daily XML file from each mailbox provider that lists every source sending mail as your domain and whether it passed SPF, DKIM and alignment. This guide shows how to read one, how to sort sources into legitimate, misconfigured and fraudulent, how to fix alignment failures and how to move from p=none to quarantine and reject without blocking real mail.

IR
Written by Ishita Rao
Email Authentication Engineer
Reviewed by Amara Okafor
  • Published17 Mar 2026
  • Read time7 min
  • Length1,373 words
Share this guide

DMARC aggregate reports are XML files that mailbox providers send you, usually once a day, listing every source that sent mail claiming to be your domain and whether it passed SPF, DKIM and alignment. Reading them is how you find every legitimate sender, fix the ones that fail and discover who is spoofing you, so you can move from p=none to p=reject without blocking real mail.

Dailyhow often providers send reports
2-4 weekstime to collect before enforcing
3 stepsnone, quarantine, reject

Start here. This guide assumes you already publish a DMARC record. If you do not, follow the guide to authenticate a sending domain first, then come back once reports start to arrive.

The short version

  1. Ask for reports. Add a rua address to your DMARC record while the policy is p=none.
  2. Wait and collect. Gather two to four weeks of reports, including any monthly sending.
  3. Sort the sources. Mark each source IP as legitimate and aligned, legitimate but failing, or unknown.
  4. Fix what fails. Give each legitimate service an aligned DKIM signature or Return-Path.
  5. Enforce in steps. Quarantine at a low percentage, raise it, then move to reject.

The DMARC record that requests reports

_dmarc.example.com.  3600  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; adkim=r; aspf=r"
TagMeaning
pPolicy for failing mail: none (monitor), quarantine or reject
ruaWhere to send aggregate reports, as one or more mailto: addresses
adkim, aspfAlignment mode: r for relaxed (a subdomain may match), s for strict (exact match)
spPolicy for subdomains if different from p
pctPercentage of failing mail the policy applies to

Use a dedicated mailbox. Reports are numerous and large. Send them to a dedicated address or to a report processing service, not to a person.

Sending reports to another domain

If the rua address is on a different domain from the one being reported, that other domain must publish a record that allows it. Otherwise providers will not send reports. For reports about example.com going to reports.example.net:

example.com._report._dmarc.reports.example.net.  3600  IN  TXT  "v=DMARC1"

What is inside a report

Reports arrive as an attachment, usually gzip or zip compressed. Open one and you will find three parts: information about the sender of the report, the policy the provider found, and a list of rows, one per source IP and result combination.

<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <report_id>1234567890</report_id>
    <date_range><begin>1759708800</begin><end>1759795199</end></date_range>
  </report_metadata>
  <policy_published>
    <domain>example.com</domain><adkim>r</adkim><aspf>r</aspf><p>none</p><pct>100</pct>
  </policy_published>
  <record>
    <row>
      <source_ip>203.0.113.10</source_ip>
      <count>1250</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>mail1</selector><result>pass</result></dkim>
      <spf><domain>bounce.example.com</domain><result>pass</result></spf>
    </auth_results>
  </record>
</feedback>
FieldWhat it tells you
org_nameWhich mailbox provider sent the report
date_rangeThe period covered, as Unix timestamps
policy_publishedThe DMARC policy the provider saw, so you can confirm your record is live
source_ip and countThe sending server and how many messages it sent in the period
policy_evaluatedThe result that counts for DMARC: dkim and spf here mean aligned pass or fail
auth_resultsThe raw SPF and DKIM results and the domains they authenticated, which may differ from the From domain
header_fromThe domain in the visible From address

Two different results. Inside policy_evaluated, pass means the check passed and aligned. Inside auth_results, pass means only that the check passed for whatever domain it used. A source can pass in auth_results and fail in policy_evaluated. That gap is an alignment problem.

Sort every source into one of three groups

GroupWhat you seeWhat to do
Legitimate and alignedA known service, DKIM or SPF aligned in policy_evaluatedNothing. Keep it that way
Legitimate but failingA known service whose auth_results pass but policy_evaluated failsSet up aligned DKIM or a custom Return-Path for that service
UnknownAn IP you do not recognise, often with many failuresInvestigate: a forgotten system, a forwarder or a spoofer. Do not authorise it until you know

How to identify a source

  • Reverse DNS: dig -x 203.0.113.10 +short often names the provider.
  • Authentication domains: the SPF and DKIM domains in auth_results usually reveal the service.
  • Your own inventory: list every tool that sends as your domain: marketing platform, helpdesk, CRM, billing system, website forms, HR tools and servers.
  • Volume and pattern: a small, steady count from a known service is normal; a sudden burst from an unknown IP is suspicious.

Summarise reports with a short script

For a first look at a folder of unzipped reports, this script totals messages by source IP and DMARC result:

import glob
import xml.etree.ElementTree as ET
from collections import defaultdict

totals = defaultdict(int)
for path in glob.glob("reports/*.xml"):
    for rec in ET.parse(path).getroot().iter("record"):
        row = rec.find("row")
        ip = row.findtext("source_ip")
        ev = row.find("policy_evaluated")
        key = (ip, ev.findtext("dkim"), ev.findtext("spf"))
        totals[key] += int(row.findtext("count"))

for (ip, dkim, spf), n in sorted(totals.items(), key=lambda x: -x[1]):
    print(f"{ip:18} dkim={dkim:5} spf={spf:5} messages={n}")

Fixing alignment failures

Pattern in the reportCauseFix
SPF passes, DMARC failsSPF authenticated the provider domain, not yoursUse a custom Return-Path on your own domain
DKIM passes, DMARC failsThe signature uses the provider domain in d=Sign with your own domain: publish the DKIM selector for that service
Both fail for a known serviceThe service is not set up for your domainComplete its domain authentication
Fails only through a forwarderForwarding broke SPF, and DKIM was alteredExpect a small tail. Make sure DKIM is present and signs the body
Fails for a subdomainThe subdomain has no records of its ownPublish SPF and DKIM for that subdomain

Move to enforcement in steps

Once the legitimate sources are aligned and only unknown sources fail, raise the policy gradually. Wait at least a week at each step and read the reports before moving on.

StepRecordWhat it does
1p=noneMonitor only. Collect reports
2p=quarantine; pct=10Failing mail from 10 percent of messages goes to spam
3p=quarantine; pct=50Half of failing mail is quarantined
4p=quarantineAll failing mail is quarantined
5p=reject; pct=25A quarter of failing mail is rejected
6p=rejectAll failing mail is rejected. Keep the rua address

Do not stop at p=none. It satisfies the minimum rules of Gmail, Yahoo and Outlook.com for bulk senders, but it does not stop spoofing. Enforcement is what protects your domain and your recipients.

Keep monitoring after p=reject

  • Review weekly at first, then monthly. New tools that send as your domain will show up as failures.
  • Add a step to onboarding: any new system that sends email as your domain gets authenticated before it goes live.
  • Protect parked domains: publish p=reject and an empty SPF record on domains you do not send from.
  • Watch for BIMI readiness: an enforced DMARC policy is a prerequisite if you later want your logo to appear in the inbox.

Want a second opinion on your reports? Send us a sample report and the list of services that send as your domain, and we will help you work out what to fix.

Contact support

Further reading and sources

Frequently asked questions

What is a DMARC aggregate report?

It is an XML file, usually compressed, that a mailbox provider sends to the rua address in your DMARC record, normally once a day. It summarises the mail the provider saw claiming to be from your domain: the sending IP, how many messages, and whether SPF, DKIM and DMARC passed. It contains no message content.

Why am I not receiving DMARC reports?

Check that the rua address is correct and is written with the mailto: prefix, that the mailbox accepts large attachments, and that you have waited at least a day. If the report address is on a different domain, that domain must publish an authorisation record. Not every provider sends reports, and small domains may receive few.

What is the difference between rua and ruf?

The rua tag requests aggregate reports, which are summaries. The ruf tag requests forensic or failure reports about individual failed messages. Most large providers do not send forensic reports, because they can contain personal data, so plan around aggregate reports.

Can I read DMARC reports without a tool?

Yes for a handful of files, because they are plain XML. For anything beyond that, use a report processing service or a short script to total the results by source, because even a modest domain receives dozens of reports a day.

What does an alignment failure mean?

DMARC passes only when SPF or DKIM passes and the domain it authenticated matches the visible From domain. If a source passes SPF for the service provider domain but your From domain is different, DMARC fails even though SPF passed. The fix is to authenticate with your own domain, using a custom Return-Path or a DKIM signature with your domain.

How long should I stay at p=none?

Long enough to see every legitimate sender, which is usually two to four weeks and should include a month-end cycle if you send monthly mail such as invoices. Staying at p=none forever protects nothing, so set a date to move on.

What does the pct tag do?

The pct tag applies your policy to only a percentage of failing messages, for example pct=25. It lets you roll out quarantine or reject gradually. Support is common but not universal, so treat it as a soft control and keep watching the reports.

Will p=reject break my email?

It will block any message that fails DMARC, which is the point. Legitimate mail breaks only when a real sender is not authenticated and aligned. That is why you collect reports first, fix every legitimate source and move in steps.

What about forwarded mail and mailing lists?

Forwarding often breaks SPF because the forwarder is not in your record, and lists may change the message and break DKIM. Signed DKIM that survives, and ARC headers added by the forwarder, help receivers decide. Expect a small tail of failures from forwarding even in a healthy setup.

Do subdomains need their own DMARC record?

A DMARC record at your main domain also covers subdomains unless you override it. The sp tag sets a policy for subdomains, and a record at a subdomain overrides both. Unused subdomains are a spoofing target, so a strict policy for them is a quick win.

Topics#dmarc#rua#aggregate reports#p=reject#alignment#email authentication
Was this guide helpful?Your answer helps us improve our documentation.

Start sending in minutes.

Create an account, add your domain and send your first email.

Start free Talk to sales