1package smtpserver
2
3import (
4 "context"
5
6 "github.com/mjl-/mox/dkim"
7 "github.com/mjl-/mox/dns"
8 "github.com/mjl-/mox/mlog"
9 "github.com/mjl-/mox/publicsuffix"
10 "github.com/mjl-/mox/spf"
11 "github.com/mjl-/mox/store"
12)
13
14// Alignment compares the msgFromDomain with the dkim and spf results, and returns
15// a validation, one of: Strict, Relaxed, None.
16func alignment(ctx context.Context, log mlog.Log, msgFromDomain dns.Domain, dkimResults []dkim.Result, spfStatus spf.Status, spfIdentity *dns.Domain) store.Validation {
17 var strict, relaxed bool
18 msgFromOrgDomain := publicsuffix.Lookup(ctx, log.Logger, msgFromDomain)
19
20 // todo: should take temperror and permerror into account.
21 for _, dr := range dkimResults {
22 if dr.Status != dkim.StatusPass || dr.Sig == nil {
23 continue
24 }
25 if dr.Sig.Domain == msgFromDomain {
26 strict = true
27 break
28 } else {
29 relaxed = relaxed || msgFromOrgDomain == publicsuffix.Lookup(ctx, log.Logger, dr.Sig.Domain)
30 }
31 }
32 if !strict && spfStatus == spf.StatusPass {
33 strict = msgFromDomain == *spfIdentity
34 relaxed = relaxed || msgFromOrgDomain == publicsuffix.Lookup(ctx, log.Logger, *spfIdentity)
35 }
36 if strict {
37 return store.ValidationStrict
38 }
39 if relaxed {
40 return store.ValidationRelaxed
41 }
42 return store.ValidationNone
43}
44