Published April 26, 2026 ยท 15 min read
Set up DMARC reporting and start receiving data about who's sending email from your domain. Check your DMARC configuration first.
Free DMARC Check โDMARC reports are the most powerful โ and most underused โ tool in email deliverability. They tell you exactly which IP addresses are sending email from your domain, whether those emails pass SPF and DKIM authentication, and whether DMARC policy is being applied correctly. If you're not reading your DMARC reports, you're flying blind on email security.
This guide covers everything you need to know about DMARC reports: what they are, how to set them up, how to read the XML format, and what actions to take based on what you find.
DMARC (Domain-based Message Authentication, Reporting, and Conformance) generates two types of reports:
| Report Type | Tag | Frequency | Content | Value |
|---|---|---|---|---|
| Aggregate | rua | Daily (typically) | Summary statistics: IP, volume, SPF/DKIM pass/fail | ๐ด Essential |
| Forensic | ruf | Per failure | Individual message details: headers, delivery result | ๐ก Nice-to-have |
Aggregate reports (rua) are the primary tool. They provide daily summaries of all email received from your domain by each reporting provider. If you only set up one thing, make it rua reporting.
Forensic reports (ruf) contain individual message samples. They're useful for debugging specific failures but are increasingly rare โ Google stopped sending ruf reports in 2022, and most major receivers no longer support them.
Add the rua tag to your DMARC TXT record. Start with p=none so you can collect data without affecting delivery:
# DMARC record with aggregate reporting _dmarc.yourdomain.com TXT "v=DMARC1;p=none;rua=mailto:dmarc@yourdomain.com"
The rua tag tells receivers where to send aggregate reports. You'll typically receive reports within 24-48 hours.
Before receivers will send reports to your rua address, you must verify you own the reporting domain. If rua points to an address on the same domain (e.g., rua=mailto:dmarc@yourdomain.com on yourdomain.com), verification is automatic.
If rua points to a different domain, you need to add a verification record on that domain:
# On the reporting domain (reports.example.com) yourdomain.com._report._dmarc.reports.example.com TXT "v=DMARC1"
Reports arrive as compressed XML attachments (usually .gz or .zip) to your rua email address. You can:
curl https://korpo.pro/api/v1/check/yourdomain.comdmarc-reports@yourdomain.com) with enough storage โ reports can be 100KB-10MB each.
Let's walk through a real DMARC aggregate report. Here's what a typical report looks like:
<?xml version="1.0" encoding="UTF-8"?>
<feedback>
<report_metadata>
<org_name>google.com</org_name>
<email>noreply-dmarc-report@google.com</email>
<report_id>12345678901234567890</report_id>
<date_range>
<begin>1742918400</begin>
<end>1743004799</end>
</date_range>
</report_metadata>
<policy_published>
<domain>yourdomain.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<sp>none</sp>
<pct>100</pct>
</policy_published>
<record>
<row>
<source_ip>209.85.128.45</source_ip>
<count>847</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>yourdomain.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>yourdomain.com</domain>
<result>pass</result>
<selector>google</selector>
</dkim>
<spf>
<domain>yourdomain.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>45.33.32.156</source_ip>
<count>23</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>yourdomain.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>yourdomain.com</domain>
<result>fail</result>
</dkim>
<spf>
<domain>yourdomain.com</domain>
<result>fail</result>
</spf>
</auth_results>
</record>
</feedback>
<report_metadata>
<org_name>google.com</org_name>
<email>noreply-dmarc-report@google.com</email>
<report_id>12345678901234567890</report_id>
<date_range>
<begin>1742918400</begin>
<end>1743004799</end>
</date_range>
</report_metadata>
| Field | Meaning | What to Look For |
|---|---|---|
| org_name | Which receiver sent this report | Most reports come from Google, Microsoft, Yahoo |
| report_id | Unique ID for this report | Useful for deduplication |
| date_range | Time period (Unix timestamps) | Reports typically cover 24 hours |
<policy_published> <domain>yourdomain.com</domain> <adkim>r</adkim> <aspf>r</aspf> <p>none</p> <sp>none</sp> <pct>100</pct> </policy_published>
| Field | Meaning | Recommended Value |
|---|---|---|
| domain | The domain this policy applies to | Your sending domain |
| adkim | DKIM alignment mode (r=relaxed, s=strict) | r (relaxed) |
| aspf | SPF alignment mode (r=relaxed, s=strict) | r (relaxed) |
| p | Domain policy (none/quarantine/reject) | Start none, move to quarantine, then reject |
| sp | Subdomain policy | Match p or set reject for subdomains |
| pct | Percentage of messages policy applies to | 100 |
Each <record> represents a group of messages from the same source IP with the same authentication results. This is where you find actionable data.
none (delivered), quarantine (spammed), or reject (bounced)The source_ip field reveals who's sending email from your domain. Compare against your known sending IPs:
# Look up who owns an unknown IP whois 45.33.32.156 # Or use our API to check curl https://korpo.pro/api/v1/check/yourdomain.com
If you find IPs you don't recognize, it could be:
Check that your known sending services (Google Workspace, SendGrid, Mailchimp, etc.) appear in reports with dkim=pass and spf=pass. If legitimate senders are failing SPF or DKIM, your SPF or DKIM configuration needs fixing.
DMARC alignment means the domain in the From header matches the domain in the SPF or DKIM signature. Look at the policy_evaluated section:
If your policy is p=quarantine or p=reject, check the disposition field for failed messages:
disposition: none โ The message was delivered despite failing DMARCdisposition: quarantine โ The message was sent to spamdisposition: reject โ The message was bouncedp=none to p=quarantine or p=reject, ensure that 100% of your legitimate email passes DMARC. Check your rua reports for at least 2 weeks. Any legitimate email failing DMARC will be spammed or bounced under a stricter policy.
Sudden spikes in volume from unknown IPs can indicate a phishing campaign using your domain. Conversely, sudden drops in volume from known IPs may indicate delivery problems.
<row>
<source_ip>198.51.100.22</source_ip>
<count>156</count>
<policy_evaluated>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
Meaning: Someone is sending email from your domain from an IP address that's not authorized. This is likely email spoofing.
Action: If p=none, switch to p=reject to block these. Also check your SPF record to ensure it's not too permissive.
<row>
<source_ip>169.55.62.74</source_ip>
<count>34</count>
<policy_evaluated>
<dkim>pass</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
Meaning: A legitimate sending service (DKIM passes) but SPF fails โ you may not have included it in your SPF record, or there's an alignment issue.
Action: Add the sending service to your SPF record, or flatten your SPF record if you're hitting the DNS lookup limit.
<row>
<source_ip>209.85.128.45</source_ip>
<count>847</count>
<policy_evaluated>
<dkim>fail</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
Meaning: SPF authenticates the email, but DKIM signature is broken or using the wrong selector. This still passes DMARC (SPF aligns), but DKIM should be fixed for maximum protection.
Action: Check your DKIM configuration โ the selector may be wrong, the key may have rotated, or the service may not be signing correctly.
<identifiers>
<header_from>yourdomain.com</header_from>
</identifiers>
<auth_results>
<spf>
<domain>news.yourdomain.com</domain>
<result>pass</result>
</spf>
</auth_results>
Meaning: The From address is yourdomain.com but the SPF domain is news.yourdomain.com. Under relaxed alignment (aspf=r), this passes DMARC because the organizational domain matches. Under strict alignment (aspf=s), this would fail.
Action: Verify that relaxed alignment is appropriate for your setup. Most organizations use aspf=r.
Manually opening and reading XML reports is impractical beyond a few domains. Here are approaches for automation:
#!/usr/bin/env python3
"""Parse DMARC aggregate reports from zip/gz attachments."""
import xml.etree.ElementTree as ET
import zipfile, gzip, sys
def parse_dmarc_report(filepath):
"""Parse a DMARC aggregate report file."""
if filepath.endswith('.gz'):
with gzip.open(filepath) as f:
tree = ET.parse(f)
elif filepath.endswith('.zip'):
with zipfile.ZipFile(filepath) as z:
xml_files = [n for n in z.namelist() if n.endswith('.xml')]
tree = ET.parse(z.open(xml_files[0]))
else:
tree = ET.parse(filepath)
root = tree.getroot()
ns = {'d': 'urn:ietf:params:dmarc:dmarc-1.0'}
metadata = root.find('d:report_metadata', ns)
org = metadata.find('d:org_name', ns).text
results = []
for record in root.findall('d:record', ns):
row = record.find('d:row', ns)
source_ip = row.find('d:source_ip', ns).text
count = int(row.find('d:count', ns).text)
eval = row.find('d:policy_evaluated', ns)
dkim = eval.find('d:dkim', ns).text
spf = eval.find('d:spf', ns).text
disposition = eval.find('d:disposition', ns).text
auth = record.find('d:auth_results', ns)
spf_result = auth.find('d:spf/d:result', ns).text
results.append({
'source': org,
'ip': source_ip,
'count': count,
'dkim': dkim,
'spf': spf,
'spf_detail': spf_result,
'disposition': disposition
})
return results
# Print failing records only
for r in parse_dmarc_report(sys.argv[1]):
if r['dkim'] == 'fail' or r['spf'] == 'fail':
print(f"โ ๏ธ {r['ip']}: SPF={r['spf']} DKIM={r['dkim']} "
f"count={r['count']} from={r['source']}")
# Check your domain's DMARC status with our API
curl https://korpo.pro/api/v1/check/yourdomain.com
# Monitor multiple sending domains
curl -X POST https://korpo.pro/api/v1/batch \
-H "Content-Type: application/json" \
-d '{"domains":["yourdomain.com","news.yourdomain.com","mail.yourdomain.com"]}'
Several services parse DMARC reports and provide dashboards with trend analysis, alerts, and automated policy recommendations:
| Phase | Policy | Duration | What You're Looking For |
|---|---|---|---|
| 1. Monitor | p=none | 2-4 weeks | All legitimate senders identified, all passing auth |
| 2. Quarantine | p=quarantine | 2-4 weeks | Failed messages go to spam, no legitimate mail affected |
| 3. Reject | p=reject | Ongoing | Failed messages are rejected, spoofing is blocked |
At each phase, monitor your DMARC reports to confirm:
p=none phase. It typically reveals sending services you forgot about โ automated emails from CRMs, internal tools, or third-party services. Moving to p=reject too early blocks these legitimate emails.
Forensic reports (also called failure reports) contain individual message samples when authentication fails. They include:
If you do want forensic reports, add ruf to your DMARC record:
_dmarc.yourdomain.com TXT "v=DMARC1;p=none;rua=mailto:dmarc@yourdomain.com;ruf=mailto:dmarc-fail@yourdomain.com"
DMARC reports are your best early warning system for email spoofing. Here's how to identify spoofing attempts:
p=reject immediately to block spoofed messagesp=reject for stronger enforcementwhois to identify the attacker's hosting providerwhois or the hosting provider's abuse deskA DMARC aggregate report (rua) is an XML file sent daily by email receivers, summarizing all email they received from your domain. It includes counts of messages that passed or failed SPF and DKIM authentication, the source IP addresses, and the DMARC policy results.
rua (reporting URI for aggregate reports) are daily summary statistics. ruf (reporting URI for forensic reports) are individual failure reports sent per-message. rua is essential for monitoring; ruf provides detailed samples but is rarely supported by major receivers in 2026.
Add rua=mailto:dmarc@yourdomain.com to your DMARC DNS record. For forensic reports add ruf=mailto:dmarc@yourdomain.com. Most receivers send reports within 24 hours. Use our DMARC setup guide for step-by-step instructions.
Focus on: 1) IP addresses sending email that fail DMARC (potential spoofers), 2) SPF/DKIM failures from your legitimate sending services (configuration issues), 3) Volume trends over time, 4) New unauthorized senders appearing in reports.
Monitor for at least 2-4 weeks with p=none. You need enough data to identify all legitimate senders (including infrequent ones like quarterly email services). Once all legitimate email passes DMARC and only unauthorized email fails, move to p=quarantine for 1-2 weeks, then p=reject.
Check your DMARC configuration and set up aggregate reporting. Our free tool validates your DMARC record and shows you exactly what needs fixing.
Free DMARC Check โ