stalwartlabs / mail-auth

DKIM, ARC, SPF and DMARC library for Rust
https://docs.rs/mail-auth/
Apache License 2.0
82 stars 13 forks source link

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

Closed scsmith closed 8 months ago

scsmith commented 8 months ago

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?

mdecimus commented 8 months ago

Here's how DMARC evaluation typically works:

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

scsmith commented 8 months ago

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?

mdecimus commented 8 months ago

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

scsmith commented 8 months ago

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?

mdecimus commented 8 months ago

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.