9 "github.com/mjl-/mox/dns"
10 "github.com/mjl-/mox/smtp"
11 "github.com/mjl-/mox/spf"
15 ctx := context.Background()
16 resolver := dns.StrictResolver{}
19 // IP from SMTP session.
20 RemoteIP: net.ParseIP("1.2.3.4"),
22 // Based on "MAIL FROM" in SMTP session.
23 MailFromLocalpart: smtp.Localpart("user"),
24 MailFromDomain: dns.Domain{ASCII: "sendingdomain.example.com"},
26 // From HELO/EHLO in SMTP session.
27 HelloDomain: dns.IPDomain{Domain: dns.Domain{ASCII: "mx.example.com"}},
29 // LocalIP and LocalHostname should be set, they may be used when evaluating macro's.
32 // Lookup SPF record and evaluate against IP and domain in args.
33 received, domain, explanation, authentic, err := spf.Verify(ctx, slog.Default(), resolver, args)
35 // received.Result is always set, regardless of err.
36 switch received.Result {
38 log.Printf("no useful spf result, domain probably has no spf record")
39 case spf.StatusNeutral:
40 log.Printf("spf has no statement on ip, with \"?\" qualifier")
42 log.Printf("ip is authorized")
44 log.Printf("ip is not authorized, with \"-\" qualifier")
45 case spf.StatusSoftfail:
46 log.Printf("ip is probably not authorized, with \"~\" qualifier, softfail")
47 case spf.StatusTemperror:
48 log.Printf("temporary error, possibly dns lookup failure, try again soon")
49 case spf.StatusPermerror:
50 log.Printf("permanent error, possibly invalid spf records, later attempts likely have the same result")
53 log.Printf("error: %v", err)
55 if explanation != "" {
56 log.Printf("explanation from remote about spf result: %s", explanation)
58 log.Printf("result is for domain %s", domain) // mailfrom or ehlo/ehlo.
59 log.Printf("dns lookups dnssec-protected: %v", authentic)