All posts

How to read a DMARC aggregate report, and why raw XML is painful

What is inside a DMARC aggregate report, how to read pass and fail by sending source, and why doing this by hand across dozens of receivers does not scale.

A DMARC aggregate report is a daily summary from one receiving mail provider of every message it saw claiming to be from your domain, and how each one fared against your checks. Read one and you can tell which of your senders are healthy and which are failing. The catch is that the reports arrive as raw XML, one file per receiver per day, and reading them by hand stops scaling almost immediately.

What an aggregate report is

When you publish a DMARC record with a rua= tag, receiving providers start emailing you aggregate reports, also called RUA reports. Each report covers what one provider saw over a period, usually a single day. It contains no message bodies and no personal content, just counts and results. Think of it as a tally sheet: for each server that sent mail as you, how many messages, and whether they passed.

Every report has two parts. First, some metadata about the report itself. Second, a set of rows, one per sending source, with the results.

The report metadata

At the top you get:

  • The reporting organization: which provider produced this report, say a large mailbox provider.
  • A date range: the start and end of the period the report covers, given as timestamps.
  • Your domain and the policy you had published at the time, so the report is self-describing.

This part tells you who is reporting and for when. It is the context for everything below it.

The per-source rows

The useful part is the rows. Each row is one sending source, and it carries:

  • The source IP: the address of the server that sent the mail.
  • A message count: how many messages came from that source in the period.
  • The SPF result: pass or fail. SPF (Sender Policy Framework) checks whether the sending server is on your list of authorized servers.
  • The DKIM result: pass or fail. DKIM (DomainKeys Identified Mail) checks a cryptographic signature that proves the message came from you unaltered.
  • The DMARC disposition: what the receiver actually did, which follows your policy (none, quarantine, or reject).
  • Alignment: whether the domain that passed SPF or DKIM matches the domain in the visible From line.

That last one, alignment, is the piece people miss. A source can pass SPF and still fail DMARC, because the domain it passed SPF for is not the domain your reader sees. DMARC only counts a check as a real pass when it is aligned with your From address.

How to read pass and fail by source

The way to use a report is to go source by source and ask one question: does this stream of mail pass DMARC, and should it?

For each row, you are sorting the sources into three buckets.

The first bucket is legitimate and passing. This is your mail provider or your invoicing tool, showing a pass on DKIM, aligned, with a sensible message count. Nothing to do.

The second bucket is legitimate but failing. This is a system you recognize, but it is failing SPF or DKIM, or it passes a check that is not aligned. These are the rows that matter most, because they are the ones that will get blocked when you tighten your policy. Each one is a sender to fix.

The third bucket is unknown or hostile. A source you do not recognize, failing everything. Some of these are forwarders mangling your mail; some are outright spoofers using your domain. You are not going to fix these, and you do not want to. Once your policy reaches enforcement, this is exactly the mail that gets refused.

A healthy domain, after some work, has everything in the first bucket except for spoofers sitting harmlessly in the third. Getting there means clearing the second bucket, one sender at a time.

What the XML looks like

The reports are XML, and the shape is roughly this, trimmed right down to show the structure rather than a real file:

report_metadata
  org_name: bigmailprovider.example
  date_range: begin ... end ...
policy_published
  domain: yourdomain.com
  p: none
record
  source_ip: 203.0.113.7
  count: 42
  policy_evaluated: dkim=pass spf=fail disposition=none
  auth_results: dkim aligned, spf not aligned

Real files are more verbose, wrap every value in tags, and repeat the whole record block once for every distinct source. A busy domain can have twenty or thirty sources in a single report from a single provider.

Why doing this by hand does not scale

Reading one report is manageable. The problem is that you do not get one report.

You get one report per receiver, per day. Every mailbox provider that received mail from you sends its own. So for a single day you might receive files from several large providers plus a long tail of smaller ones, and tomorrow you get another full set, and the day after that another. The volume is relentless and it never stops, because the reports are a continuous feed, not a one-off.

Each file is XML, which is built for machines to parse, not for people to read over coffee. To answer a simple question like “did my payroll system pass everywhere yesterday?” you would have to open every file from that day, find the row for that source in each, and cross-check the results. To spot a trend, say a sender that started failing this week, you would have to do that across days. By hand, this is hours of work that has to be repeated forever, and it is the single most common reason DMARC projects stall after the reports start arriving.

The natural next step

None of this means the reports are not valuable. They are the only real visibility you get into who is sending as your domain. The issue is purely that their raw form is hostile to human reading, and the volume compounds it.

This is the problem a DMARC monitoring service exists to solve. It ingests every report, parses the XML for you, groups the results by source across all receivers, and shows you a plain answer: here are your senders, here is what passes, here is what is failing and needs attention. Instead of opening files, you read a summary. We lay out why that is worth it in why use a DMARC service. If you just want to see your current record and what it is set to do, the free DMARC checker analyzes it live and explains it in plain English.