An IP you do not recognise in a DMARC report: vendor, forwarder or impersonator, narrowed by the holder and the alignment pair

A DMARC aggregate report hands you a source address with nothing attached to it: no header, no bounce, no session, just an IP, a count, the SPF and DKIM results and whether either aligned with your domain. Before the next report cycle you have to decide whether that address belongs to a vendor you forgot, a forwarder you can tolerate, or somebody using your domain, and the wrong call either blocks your own mail or leaves you with no dated record of an impersonator on the day you need one. The address cannot tell you which by itself, but its holder, its block and the network announcing it narrow the field, and the alignment pair read against them leaves most rows with one candidate to check against your own vendor list. This post is that read, in the order it pays to do it, ending with what a subnethistory report shows for a DMARC source address and what it cannot. Every RFC and provider page cited was read on 9 September 2026.

One aggregate report row, a source address with a count and an SPF fail beside a DKIM pass, narrowing after attribution towards the vendor door or the forwarder door, with the third, an impersonator, on a broken line because a row with an aligned signature does not reach it and it opens only where both results fail one row source_ip 203.0.113.25 count 412 spf fail dkim pass, aligned vendor confirm, then add forwarder tolerate, note it impersonator look it up, keep it
One aggregate row: a source address, a count and the alignment pair. The row alone cannot say which door it belongs to: with DKIM aligned this pair leaves the vendor and forwarder doors open, the holder narrows them and only your own vendor list and SPF record pick between them, and the third opens when both results fail, and also when an aligned pass turns out to be a message of yours resent by somebody else. An aligned signature that turns out to come from a subdomain you never delegated points at a subdomain to audit, not at a vendor. Each door forces a different action before the next report arrives: confirm before authorising, tolerate, or keep a dated read before the policy moves.

What an aggregate row gives you, and what it leaves out

DMARC was rewritten this year. RFC 9989, a Proposed Standard published in May 2026, is the mechanism and obsoletes RFC 7489 and RFC 9091, and RFC 9990, published the same month, is the aggregate report format; a third document, RFC 9991, covers the per message failure reports, which are a different thing and not what this post reads. An aggregate report describes one policy domain over one period, the date_range given as a beginning and an end in UTC, and RFC 9989 says receivers should send one at least once every 24 hours, so a row covers a period of messages, never a moment. Each record holds a row element carrying source_ip, which RFC 9990 defines as the connecting IP address, a count, and policy_evaluated with the disposition applied and the dkim and spf alignment results, each pass or fail, the two values this post calls the alignment pair, and, when that disposition does not match the policy you published, a reason with a type and a comment; then identifiers with the header_from domain; then auth_results with the raw checks, a dkim entry per signature with its domain, selector and result, and an spf entry with the domain checked and a result that can also read softfail, neutral or an error. The RFC keeps one record per combination of address, result and identifiers, so one address can occupy several records in one report, and the count is the number of messages the evaluated policy was applied to, whether or not something else later blocked them.

What is not there matters as much. There is no message header, no body, no subject, no recipient address, no per message time, and no name for the address: RFC 9990's schema has no element for a hostname or a reverse DNS name, and its privacy section says the reports contain no identifying characteristics about individual users. So the source_ip is the last hop into the receiver and nothing earlier, and a number is all you get. The reports arrive because your record asked for them and because the large mailbox providers now make them worth reading: Google's sender guidelines require senders of more than 5,000 messages a day to Gmail accounts to set up SPF, DKIM and DMARC and, for direct email, a From: header aligned with the SPF or DKIM domain, and the same page recommends DMARC reports so you can monitor mail sent from your domain, or that appears to have been sent from it; Yahoo's sender requirements ask bulk senders for both SPF and DKIM, a DMARC policy of at least p=none and DMARC alignment that passes, and say a rua tag set up to receive reports is strongly recommended. None of those pages uses the word aggregate; that term is RFC 9990's.

One tool most tutorials reach for is deliberately not in this post's kit. Reverse DNS is what the providers demand of a sending address, Google requiring a PTR that forward confirms to the sending IP and Yahoo requiring a valid forward and reverse record and recommending a meaningful one, but the report you are holding does not carry it, and a PTR is the network's own labelling of its address rather than identification of the sender, which the reading one Received line explains. The registry and routing read below is evidence written by the registry and the routing system rather than by the message.

Three answers and one decision

An unrecognised address resolves to one of three things. A vendor: mail you contracted for, sent from a platform you forgot or never registered, whose authorisation needs an SPF include or, better, a DKIM key signing with your domain. A forwarder: legitimate mail relayed by a recipient's mailbox provider, an alias or a list, which you tolerate and cannot fix, because the relay is not yours. An impersonator: mail you never sent, carrying your domain in the From: header, which is the reason DMARC exists. Each forces one decision before the next report cycle, and each wrong call has its own cost. Adding an include for an address that turns out to be an impersonator authorises them. Tightening the policy over a forwarder lets receivers reject your own mail once it has passed through that relay, which RFC 9989 says outright: mail relayed through a list with its From: header untouched is frequently rejected under p=reject, and a domain whose users post to lists should not publish p=reject at all. Leaving a vendor unaligned is fine under p=none and at risk of quarantine or rejection the day the policy moves.

The rule the row is scored against is short, and worth reading in the RFC's own terms rather than in a summary. RFC 9989 requires Identifier Alignment between the Author Domain, the domain of the RFC5322.From header, and an Authenticated Identifier for a message to pass, and defines two states: relaxed, when the Author Domain has the same Organizational Domain as the identifier, and strict, when the two are identical; both alignment tags default to relaxed. For DKIM the identifier is the d= domain of a signature that validates, and one aligned signature among several is enough; for SPF, DMARC relies solely on the MAIL FROM identity, so an SPF pass for some other domain proves nothing about yours. If any identifier aligns the message passes; if none exists or none aligns it fails. And a pass, the RFC says, indicates only that the use of the domain was authorised, with no value assertion about the message, which what the three records prove spells out. The receivers agree on the shape: Google's sender guidelines FAQ says the organizational domain in the From: header must align with either the SPF or the DKIM one, and Yahoo says relaxed alignment is acceptable.

Attributing the address: holder, block, origin

Look the source_ip up. The general method, read the registration and then distrust it, is in how to investigate an address, and what an address you found actually is covers the last hop problem from the header side; what follows is only the DMARC specific part. The report leads with the subject line, its chips and its tags, then the findings, one line each, such as Datacenter space or Part of something bigger, and the panels you want come below them, Routing about halfway down and the Autonomous system and Registration panels at the foot. The Registration panel's Organisation, Type and abuse contact rows are read in what a lookup shows for a listed address; the tables to open here sit beneath it, collapsed: Registry contacts, with role, name, organisation and email from the registry's entities, the last three reading n/a wherever the registry published nothing, and Enclosing blocks, which is where a sub assignment inside a mailbox provider's, a platform's or a cloud's allocation shows itself. The Routing panel's Origin AS row names the announcing network with its holder name where the source gives one, and the Autonomous system panel gives that network's own registration and its self declared profile.

Then match the names against your own vendor list and your own SPF record, which is the step only you can do: the site knows neither. The Enclosing blocks table is why you check the block and not just the address, because the commonest attribution error is the wrong boundary, blaming a whole provider for one customer or crediting one customer with a whole platform. A holder that reads as an email platform or a cloud is where legitimate vendors live, and also where anyone can rent an address for an afternoon, and on a platform's shared pool a listing on the address belongs to the pool rather than to any one sender, which what shared actually buys you sets out; a holder that reads as a consumer or mobile network is where a forwarding mailbox lives, and also where a compromised home box lives. Confirmed tags, the ones a person has applied with evidence, sharpen the reading; Hosting / datacenter, Cloud provider, Eyeball ISP, Mobile carrier and the abuse labels are among them, and absence of a tag is not a finding of innocence; the report also shows machine proposals, marked as not yet confirmed, and those are leads rather than findings.

The alignment pair, read against the holder

The attribution tells you what kind of holder it is; the alignment pair says what the mail did on the way. This is how to read one against the other. RFC 9989 explains the mechanics: mail relayed by an intermediary will most likely fail SPF unless the relay rewrites the MAIL FROM address, and a rewrite does not rescue the row either, because the pass it produces is for the relay's domain and does not align with yours, so the pair still reads spf fail, because the connecting address is the relay's and not one your record authorises, while DKIM signatures will generally remain valid in those relay situations, and a domain at p=reject must not rely on SPF alone for that reason. RFC 7960 adds the counterweight: content modification invalidates most DKIM signatures, many forwarding systems modify content, and mailing lists are a common example of such systems, though the RFC adds that other forwarding systems also make modifications. So read the pair like this. DKIM aligned and passing, with SPF failing, from a holder you recognise as a platform you contracted or a cloud you run on, reads as a vendor candidate whose SPF include may be the thing missing, and the aligned signature is the stronger evidence anyway: a signature that validates against the key you published was made by something holding the matching private key, which says more about who authorised the domain than the last hop does, while still asserting nothing about the message itself. DKIM aligned and passing, with SPF failing, from a holder that reads as a mailbox provider, a consumer network, a university or an association, reads as a forwarder candidate, and RFC 9989's own relay examples are a university and an association. Both failing, from a hosting or cloud holder you have no contract with, reads as an impersonation candidate. Both failing from a consumer network can be a compromised box sending as you, and RFC 7960 lists other legitimate senders that struggle to align at all, partially open relays at residential providers, embedded devices and devices sending on a user's behalf, so a both failing row is a candidate, not a verdict.

Three shapes hide from this read. The first is replay: RFC 6376 section 8.6, on replay and spam attacks, says a message can be resent by the recipient to other recipients and that DKIM signatures are not invalidated by this resending, so the signature will still be valid. A message of yours, signed and aligned, captured and resent by somebody else arrives as an aligned pass with SPF failing, from a holder that has nothing to do with you, which is the same pair as the vendor and forwarder rows. So an aligned pass from a holder you cannot place is a subdomain to audit or a replay to look for, and the row cannot tell you which: auth_results names the DKIM domain and selector, and only a failure report or a bounced sample carries the message that would settle it. A mailing list that rewrites the From: header to its own domain, which RFC 9989 says some lists now do, no longer uses your domain, so that traffic leaves your report altogether; a list that keeps your From: and modifies the body breaks the signature and shows as both failing, from a holder that looks like a list operator. And ARC, RFC 8617, still Experimental as of July 2019 with no update since, is the mechanism RFC 9989 names as a prominent example of the attempts to let lists work without rewriting, adding that no such method had become widely used; Yahoo tells forwarders to implement it, Google's sender guidelines page does not mention it and sends forwarders to a separate best practices page, and RFC 9990's base schema gives it no element of its own. What a row can carry instead is the receiver's reason for not applying the policy you published, typed mailing_list, trusted_forwarder or local_policy among others, with a comment; the first two are the receiver telling you it treated the source as an intermediary, and worth reading before the holder. One more counterweight on the pass side: under relaxed alignment anyone who controls the SPF or DKIM records of a subdomain can produce a pass for the organizational domain, which RFC 9989 warns about, so an aligned pass from a holder you do not recognise points at a subdomain to audit, not at a vendor.

The decision table

The pair reads The holder and origin read, against what only you know The chips and tags read Attribution Before the next report
dkim pass and aligned, spf fail An email platform, a cloud or a hosting holder you have a contract with datacenter chip, a Hosting / datacenter or Cloud provider tag where one is confirmed Vendor candidate Confirm the platform against your contract and its own published sending record, and if the DKIM domain in auth_results is a subdomain you did not delegate, audit that first. This row already passes DMARC on the aligned signature, so nothing is failing today. Read the SPF entry in auth_results before touching your record: where the domain checked is the platform's own, it is bouncing under its own return path, no include of yours can align it, and the change belongs to the platform's custom return path setting. Add an include only where the platform sends with a MAIL FROM in your domain, or the exact address of a host you run, never a cloud or hosting range
dkim pass and aligned, spf fail A mailbox provider, a consumer or mobile network, a university or an association, no contract Often no chips at all, or a mobile chip; an Eyeball ISP or Mobile carrier tag where one is confirmed Forwarder candidate Tolerate and note it; do not add it to SPF; count it before any move to quarantine
dkim fail, spf fail A hosting or cloud holder with no contract, and not a list, a gateway or a filtering service any of your recipients route through, or a consumer network at volume on N blocklists, abuser or proxy chips, or nothing at all Impersonation candidate Do not write an abuse report from the row alone: it carries no timestamp and no message, and a usable report needs both. Look the address up, keep the dated read, and read the policy move against the forwarder rows and against every both failing row you have not placed, because the mail a reject policy breaks is the mail whose signature a relay broke, and those rows sit here rather than in the forwarder rows; the abuse report waits for a message with a time, from a DMARC failure report where a receiver sends one or from a bounced sample
Any pair, a low count A holder you cannot place and an origin with no story No chips, no tags, n/a in the Per-source detail table Unsettled Look it up again when the next report arrives; two dated reads of a source you cannot place are worth more than one. This row is the fallback, not an override: where the pair and the holder already place a row above, follow that row, because targeted impersonation is exactly the low count case

Three notes on the table. The first row's subdomain clause is RFC 9989's warning, not a subnethistory report's: auth_results names the DKIM domain and selector, and a passing aligned signature from a subdomain you never set up is the thing to chase. The third row holds the abuse report back because an aggregate row is an address and a period and nothing else: what a usable report contains asks for exact timestamps with a time zone and raw evidence, and when a message with a time does arrive, find the right mailbox from the block that actually contains the address. And the policy move belongs to you: both providers accept p=none, Yahoo tells a domain with a spoofing problem to implement p=quarantine or p=reject, and RFC 9989 tells a domain whose users post to mailing lists not to publish p=reject at all, and tells one that means to anyway to run p=none for at least a month and p=quarantine for as long again while comparing dispositions, which is the forwarder rows being counted.

One report, many addresses

A report from a large receiver can list dozens of source addresses, often several inside one block, and RFC 9990 lets one address occupy several records, so count addresses rather than rows. When a handful of rows share a block, look the block up rather than each address: a CIDR lookup samples it and heads the panel Address sampling with how many of the block's addresses have been checked, prints a count chip for whichever of the VPN, proxy, Tor, datacenter, abuser and blocklisted verdicts the sample turned up, and groups the sample by behaviour with an example address per group; what a block level report shows walks the rest of the panel. Two limits travel with it: the sample is what has been checked so far and readings accumulate across lookups, so a block with four readings behind it says nothing about the addresses nobody has checked, and the docs' rule is that unsampled is not clean; and when the lookup hits its own row cap every count is a floor. Reading a range is the density argument in full.

For a whole report, the keyless JSON API answers the same three query shapes as the search box, an address, a block or an ASN; it takes the query and the three flags the docs list, shallow, offline and refresh, the last reserved for operators and ignored on a public request, and nothing else. It does not parse a DMARC report: you extract each source_ip from the XML yourself and look it up, and the request shape, the meta and sources fields to read before trusting an answer, and the pacing against a cold lookup are in monitoring your own ranges and its cadence section, not here. One address kind is answered instantly: a private or reserved source_ip, which a misconfigured internal relay can put in a report, comes back described as special use space with no holder, no history and no routing.

What a subnethistory report shows for a DMARC source address, and what it cannot

For the address: the subject line with its chips, VPN, proxy, Tor, datacenter, mobile, abuser and on N blocklists, a chip one feed asserts and another denies marked disputed, then the findings, then the address card repeating the same chips, with a red Blocklisted on line naming feed labels where a feed named any. None of those lists is a mailbox provider's own, so whether a receiver lists the address is not a question this report answers; a receiver's verdict reaches you as a bounce, and sorting a bounce into a branch is where the address branch, and whether the address is yours alone, is read. Beneath the card sits the collapsed Per-source detail table, one row per feed, with Source, Verdict, Risk, Blocklists and Checked: the Verdict cell prints the flags a feed set, no flags when a feed looked and found nothing, and n/a when it supplied no verdict, which is not the same thing, and when feeds disagree is the reading for a table that splits; both cells are read in what the Blocklists and Checked cells mean, and the Checked date is the age of the evidence, with the number of readings behind it. A Verdict changes we have recorded section appears below the table when a feed's reading for the address has changed between two reads, one dated line per change, naming the field and both values. Below that sit the panels the attribution section walked, Routing, Autonomous system and Registration, and the one it did not need: the origin history, every network that has announced the block and when.

What it cannot show, stated in the same breath. No reverse DNS and no PTR record, anywhere on the page or in the API. Nothing about your vendors, your SPF record or your DKIM selectors, so it cannot say an address is your vendor; it can only name a holder for you to recognise. No registry holder name history, and no dated record from any mail blocklist. Whether the message was legitimate, which is a question about content the site never sees. Whether a receiver will deliver from that address, which the site's own front page FAQ says plainly it does not predict; how receivers weigh the two together is why neither the pair nor the public record settles that one. A clean read means no feed the site reads reported anything on the day, and a clean result narrows risk without removing it. And it does not watch the address for you or notify anyone: readings accumulate across lookups, so what the page shows for a source only changes after a second lookup. Two limits on the aggregate report itself: a message a receiver refused before evaluating DMARC has no row to appear in, and RFC 9990 says the data in a report may be forged, so the row is a claim by the receiver, dated, like everything else here.

Take the row, look the address up, read the holder and the block, then read the pair. A platform you have confirmed against your contract and its own published sending record, under an aligned signature with SPF failing, is an authorisation to add, that platform's include or the exact address of a host you run; a mailbox provider under the same pair is a forwarder to count; a stranger failing both is a dated lookup to keep and a reason to count the forwarders before the policy moves. When the next report comes, look the address up again and keep both reads, because the row will still not carry a name, and the second dated read beside the first is the history of that row.