stalwartlabs/mail-auth

Shouldn't dmarc results be fail if SPF or DKIM fail for a domain?

scsmith opened this issue · 5 comments

I'm currently testing this library and excuse me if this isn't correct but if SPF or DKIM fail for a message shouldn't the resulting output from verify_dmarc be a failure? Currently it looks like the default of None is returned.

Sorry if this isn't clear but I'm having some issues working through the logic of the dmarc verification and checking what's expected.

As an example the signature here is expired, but I think a similar thing happens if the SPF record is invalid (I change the IP address so it is a fail):

spf_result: SpfOutput { result: Pass, domain: "scsworld.co.uk", report: None, explanation: None }
dkim_result: [DkimOutput { result: Neutral(SignatureExpired), signature: ... x: 1699708744, t: 1699103944, r: false, atps: None, atpsh: None, ch: Relaxed, cb: Relaxed }), report: None, is_atps: false }]
dmarc_result: DmarcOutput { spf_result: Pass, dkim_result: None, domain: "scsworld.co.uk", policy: Reject, record: Some(Dmarc { v: V1, adkim: Relaxed, aspf: Relaxed, fo: Any, np: None, p: Reject, psd: Default, pct: 100, rf: 1, ri: 86400, rua: [URI { uri: ..., max_size: 0 }, URI ..., sp: None, t: false }) }

Shouldn't the output here actually be Fail not None?

Here's how DMARC evaluation typically works:

  • SPF and DKIM Checks: DMARC relies on the results of SPF and DKIM checks. Each of these checks will either pass or fail.
  • Alignment: DMARC checks if SPF and DKIM are aligned. Alignment means that the domain in the SPF authentication or the DKIM signature matches the domain in the "From" header of the email.
  • DMARC Result: The DMARC check passes if either SPF or DKIM (or both) pass and are aligned. If both SPF and DKIM fail, or if they pass but are not aligned, then DMARC should fail.

So, it is correct that DMARC passes but only if SPF is aligned.

I think my confusion here is that you are considering none to be a fail. I agree that this case is a pass, but if I was to make the SPF record fail then I would see none, none.

For example the domain scsworld.co.uk and an IP that is not googles and no DKIM signature at all:

spf_result: SpfOutput { result: Fail, domain: "scsworld.co.uk", report: None, explanation: None }
dkim_result: []
dmarc_result: DmarcOutput { spf_result: None, dkim_result: None, domain: "scsworld.co.uk", policy: Reject, record: Some(Dmarc { v: V1, adkim: Relaxed, aspf: Relaxed, fo: Any, np: None, p: Reject, psd: Default, pct: 100, rf: 1, ri: 86400, rua: ..., sp: None, t: false }) }

So here you are considering None, None for the spf and dkim results to be a fail?

Perhaps you are confusing the policy field with the DMARC evaluation result? The DmarcOutput struct does not include the results of the DMARC evaluation.

Ok, I have read through the mail server code where you evaluate and look for both items to pass so that makes sense. Again I think my confusion is that the SPF check has failed, it does not really matter if it is aligned or not I would still expect the DmarcOutput.spf_result to be fail rather than None, but I guess that is a matter of preference?

I think my confusion is that the SPF check has failed, it does not really matter if it is aligned or not I would still expect the DmarcOutput.spf_result to be fail rather than None, but I guess that is a matter of preference?

Yes, what really matters for DMARC evaluation is whether SPF has passed or not. But I'll double check once I have some time available if, according to the RFC, it is correct that the DMARC SPF evaluation result is set to None in the Authentication-Results header.