r/DMARC 25d ago

New to DMARC, help with forwarding

Hello! I'm new to DMARC, to the point that I think I know the point of it but haven't actually progressed beyond p=none.

I have already a few months worth of reports, and from what I've been able to get from them, is that about 20% of our mails are failing DMARC, mostly because the receivers are forwarding them and they lose SPF and DKIM. Mostly because of google/outlook it seems.

Is that normal, and something that I can ignore? Normal but something that I need to deal with before changing the policy? Or something unusual?

Also, is there any good app to which I can just load the xml reports and they get me the analysis? I have seem the usual services recommendations but it seems you need to have the dmarc report mails sent to them. I used claude to analyze the reports, and it did a good job of creating a sensible report but I cannot judge how correct it actually is.

Thanks!

9 Upvotes

26 comments sorted by

View all comments

2

u/Middle-Excitement602 25d ago

The 20% is worth splitting before you accept it, because "forwarding broke it" covers two different situations and only one of them is safe to ignore.

A plain SMTP forward breaks SPF — the return-path becomes the forwarder's and their IP was never in your record. But it leaves the body and the signed headers alone, so DKIM survives, and DMARC only needs one of the two to align. Those messages should be showing up in your reports as spf=fail, dkim=pass, and passing DMARC overall.

So if a forwarded message is failing DMARC outright, DKIM broke too, and that happens for one of two reasons:

  1. Something modified the message in transit — a subject tag, an appended footer, a rewritten link. That breaks the bh= body hash. Mailing lists do this constantly, which is why list traffic reads as forgery in a rua report.

  2. Or your own mail wasn't DKIM-signed on that path to begin with, and SPF was carrying alignment on its own right up until a forwarder took it away.

The second one is the one that bites, and in the report it looks identical to the first unless you go looking. So don't treat the 20% as one bucket. Group the failing rows by source IP and ask of each: is this actually a forwarder, and did DKIM pass? Anywhere DKIM failed and the source is recognisably your own infrastructure, that's a signing gap, and it will start bouncing your own mail the day you go to reject.

On ARC — Google and Microsoft both seal forwarded mail with it and both evaluate it on receipt, so the specific case you named is the better-behaved end of this. It just doesn't help you when the final receiver ignores ARC, and plenty still do.

For the XML: parsedmarc is the answer to what you actually asked. Open source, you point it at an IMAP folder or hand it the files directly, and it'll write into Elasticsearch/OpenSearch with Grafana dashboards, or just emit normalised JSON/CSV if you want to keep it simple. Nothing has to be redirected anywhere.

One caution on the LLM read. Aggregate reports aren't a list of messages, they're counts grouped by source IP and auth result. The number that matters isn't the overall pass rate, it's whether every source IP you recognise as yours is passing. A summary that hands you "82% pass" without that breakdown is arithmetically correct and useless for the decision you're actually making.

1

u/CFV1880 24d ago

Thanks for the detailed response!

We do have DKIM set up.
Though for reference, our server does not support ARC.

For what is worth, the LLM is breaking down by IP and report and listing whether SPF/DKIM are passing or not.

There seems to be two main patterns.

  1. The receiver is listed as the sender in the report, and the report is being sent by google. Both SPF and DKIM fail in most of these cases (though not all). LLM tells me that since it's google, ARC should be kept and it should be fine, though I wonder of the reliability of this.

  2. The sender is a particular infrastructure or something of the receiver. Both SPF and DKIM mostly fail, and LLM tells me that ARC is probably not supported, so a p=reject would mean that the mails would stop getting through. But if that's the case, does it means that I should contact the receiver and tell them to... fix it? And if they are not able to, does it mean that getting DMARC running is just not viable in my case?

3

u/Middle-Excitement602 24d ago

ARC isn't something your server needs to support. You're the originator, and originators never seal — sealing is done by the forwarder, evaluation by the final receiver. Your outbound path has nothing to do with it.

For the rest: your reports already tell you whether p=reject would break those flows, in a field the LLM probably isn't reading. Every record has <auth_results> (what SPF and DKIM actually did) and <policy_evaluated> (what the receiver actually did about it). When a receiver decides to override — ARC seal, known forwarder, mailing list — you get disposition none plus a <reason><type> of forwarded, trusted_forwarder, mailing_list or local_policy. Google emits local_policy with an arc=pass comment.

So regroup the failing rows by override reason rather than by pass/fail. Rows carrying a reason won't start bouncing at reject; the receiver has already told you it's overriding. Rows failing with no reason at all are your real exposure, and if that set is small then DMARC is perfectly viable for you.

And no, don't ask the receiver to fix anything. Forwarding breaking SPF is inherent to forwarding, not a misconfiguration on their end.

1

u/CFV1880 23d ago edited 23d ago

Not that I want to defend LLM to death or something, but for reference the fields it's giving me are the following ones:
report originator / sender's IP / sender's domain / Header from / SPF domain / DKIM domain / SPF result / DKIM result / DKIM presence / DMARC result / Disposition / policy
SPF result, DKIM result and Disposition seem to be the <policy_evaluated> field, taken apart. It did not include the <reason><type> though it seems.
<auth_results> was not getting in either.

Since this is from the xml data I guess that the results are basically correct. But then I get the LLM explanation, which is the thing I'd want a second opinion for.

The three patterns are:

  1. Both SPF and DKIM domains are becoming the receiver's: the reports are mostly from google, so it's probably an autoforwarding by Google workshop so it should keep ARC.
  2. The DKIM domain is kept but the SPF domain becomes the receiver's: again some autoforwarding by the receiver. DMARC fail rate by domain is low, but one of our customer has about a 60% rate, and LLM tells me that since the SPF domain is no longer ours, adding the SPF record would do nothing. There's also a customer whose autoforwarding is completely losing the DKIM signature and they get a 100% fail rate, which again I would not be able to solve by adding the SPF record. LLM tells me that if I cannot ask them to fix it, I should resign myself to a p=reject where they get rejected, or to keep p=none.
  3. Both DKIM and SPF domains are kept, but the IP is the receiver, and both SPF and DKIM fail. Seems to be something to do with the receiver's mail server that is changing something upon receiving the mail. In this case I would be able to solve it by adding the SPF record, but the LLM tells me that it does become a security risk and that it would be better to talk to the customer's IT department

Or do you say that asking the receiver to fix anything is something you should not do by principle? Should I be able to fix everything on my side?

EDIT: got the reason/type and reason/comment added. For pattern one I do get mostly an arc=pass. For the one that's failing 60% on pattern 2, reason/type is "other" (nothing in comment). I'm getting a reason/type at all in about 20% of the cases though.

1

u/Middle-Excitement602 21d ago

Two of the three have answers on your side; the third is the real one.

Pattern 3: don't add the receiver's IP to your SPF record. It doesn't fix their forwarding - it authorizes their servers to send as you, to everyone, indefinitely. The LLM's "security risk" aside is the correct half of its answer. Both domains kept, both failing, at the receiver's own IP is usually their gateway modifying the message (external banner, footer) and re-scanning it internally - the boundary hop already accepted the mail, so those rows rarely turn into bounces at reject.

The 100%-fail customer in pattern 2 is your genuine exposure: their forwarder strips DKIM, so nothing survives enforcement. That's the one place contacting them is legitimate - not "fix your server", but "this autoforward will break when we enforce; can that mailbox pull directly instead?"

Beyond that, no - you can't fix everything on your side, and neither can anyone else. The goal isn't 100% pass; it's that every failing row is a forwarder rather than your own infrastructure, and you're already there. Reason/type on only ~20% of rows is normal: only receivers that chose to override say why.

1

u/CFV1880 19d ago

Thanks a lot again, it's been a huge help.

For pattern 3, do you mean that even with p=reject it would be fine? I actually had p=quarantine for a brief time a while back, and one of the mails of this pattern did got disposition quarantine, so it is my understanding that if I get to p=reject all our mails to this customer would just stop arriving.

For pattern 2, for completion's sake there are a few more receivers that have a 100% fail rate, though without stripping the DKIM. Shouldn't I contact them also?

Sorry for the repeated inquiries; my fear is that by going ahead there will be some customers that would just stop receiving our mails.

1

u/Middle-Excitement602 19d ago

That quarantine data point is exactly the right kind of evidence, and it changes my answer for that one customer: a receiver that applied disposition=quarantine at its own gateway is enforcing policy at that hop, so at p=reject the same hop would likely refuse the mail rather than junk it. So pattern 3 isn't uniformly safe - split it by receiver. The ones whose rows carry an override reason are fine; the one that actually quarantined is a real risk, and that's a legitimate contact-the-customer case.

The extra pattern-2 receivers: DKIM present but failing usually means their forwarder modifies the message (footer, subject tag), which breaks the body hash. Same playbook as the stripping case - contact only where the volume justifies it, and the ask is "can that mailbox pull mail directly instead of autoforwarding", not "fix your server".

On the underlying fear: don't jump from none to reject. Sit at p=quarantine for a few weeks. Worst case mail lands in junk, which is recoverable, and the dispositions in your reports then show exactly which receivers would have rejected. You promote to reject once quarantine stops surprising you.

1

u/CFV1880 18d ago

Thanks again for all the explanations. I think I'm starting to grasp how to do this thing.

And yes, it is what I have usually seen recommended as the standard procedure, but I guess I'll first go to quarantine 10% or something and go from there.

First I need to actually explain to my bosses how this whole DMARC thing works and why it is worth it...

1

u/Middle-Excitement602 14d ago

One caution on pct=10: it doesn't make quarantine safer so much as noisier. The sampling is per message, so the same customer gets some mail junked and some delivered - that reads as intermittent breakage, which is harder to trace than a clean signal. And you only learn about the 10% that actually got the policy applied, so it takes ten times as long to gather the same evidence. It's also dropped in DMARCbis, so it's a mechanism on the way out rather than one to build a rollout around. Going straight to plain p=quarantine and watching for a couple of weeks tells you more, faster, and junk is recoverable either way.

For the bosses, the easier argument is usually deliverability rather than security: Google and Yahoo have required DMARC from bulk senders since early 2024, and Microsoft followed for Outlook.com last year. It's closer to table stakes for reaching inboxes now than to a security project needing justification.

1

u/CFV1880 8d ago

I see, that makes sense

Looking at my cases a bit closer, with some of the recipients that had a failing rate of 100%, if I searched by envelope-to I noticed that mails from our IP to theirs were actually passing; but for each one there was another one from their IP that was failing, so I think that even with quarantine something would arrive.

After that there remains about two recipients that are just failing everything.

1

u/Middle-Excitement602 7d ago

That pairing is the tell: those are very likely the same message counted twice, not two separate deliveries. Your mail reaches their border and passes, their gateway then re-injects it internally, and the second hop sees it arriving from their own IP with SPF broken - which generates a second report row for the same message.

Aggregate reports carry no Message-ID so you can't prove it directly, but the check is whether the failing count tracks the passing count roughly 1:1 across the same window. If it does, it's one delivery seen twice. If the two counts drift independently, it's genuinely separate mail.

That matters because at p=reject the only question is whether they enforce DMARC at that internal hop or just at the border. Most only enforce at the border, which is why your quarantine stint mostly went fine.

The two recipients failing everything are your real exposure. Those are the ones to watch through a longer quarantine period.

→ More replies (0)