all repos — navani @ ab5222b70d5cb9f64cffeb0485a283040a1a657d

forlater's primary mail processing service

Improve SPF check logic
Anirudh Oppiliappan x@icyphox.sh
Mon, 20 Sep 2021 11:01:47 +0530
commit

ab5222b70d5cb9f64cffeb0485a283040a1a657d

parent

6a3b4b68a2ff0917e49e2eeb42f8d6b99281fb1d

1 files changed, 38 insertions(+), 11 deletions(-)

jump to
M mail/check.gomail/check.go

@@ -2,6 +2,7 @@ package mail

import ( "fmt" + "log" "net" "net/mail" "strings"

@@ -10,6 +11,20 @@ "blitiri.com.ar/go/spf"

"golang.org/x/net/idna" ) +func verifySPF(ips []net.IP, domain string, from string) (passes []spf.Result, err error) { + passes = []spf.Result{} + for _, ip := range ips { + result, _ := spf.CheckHostWithSender(ip, domain, from) + // if err != nil { + // return nil, fmt.Errorf("check spf: %w\n", err) + // } + if result == spf.Pass { + passes = append(passes, result) + } + } + return passes, nil +} + func VerifySPF(email string) (bool, error) { e, err := mail.ParseAddress(email) if err != nil {

@@ -27,24 +42,36 @@ if err != nil {

return false, fmt.Errorf("mx lookup: %w\n", err) } - passes := []spf.Result{} + mxPasses := []spf.Result{} + // Check MX IPs against SPF record. for _, mx := range mxs { ips, err := net.LookupIP(mx.Host) if err != nil { return false, fmt.Errorf("ip lookup: %w\n", err) } + passes, err := verifySPF(ips, domain, e.Address) + if err != nil { + return false, fmt.Errorf("mx spf: %w\n", err) + } + mxPasses = append(mxPasses, passes...) + } - for _, ip := range ips { - result, _ := spf.CheckHostWithSender(ip, domain, e.Address) - if result == spf.Pass { - passes = append(passes, result) - } + if len(mxPasses) == 0 { + // Check domain IP against SPF record. + ips, err := net.LookupIP(domain) + if err != nil { + return false, fmt.Errorf("ip lookup: %w\n", err) + } + passes, err := verifySPF(ips, domain, e.Address) + if err != nil { + return false, fmt.Errorf("domain spf: %w\n", err) + } + // If both MX IP and domain IP fail SPF, we return false. + if len(passes) == 0 { + return false, nil } } - if len(passes) > 0 { - return true, nil - } else { - return false, nil - } + log.Printf("spf passed: %s\n", email) + return true, nil }