author | Matthias Schneider
<ms@wck.biz> 2022-08-16 14:01:52 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-08-27 16:49:25 UTC |
parent | 0017db6243c65c80ff4626f4a436958f6d26f4b8 |
spf.go | +7 | -1 |
spf_test.go | +22 | -0 |
diff --git a/spf.go b/spf.go index d36826a..5d5784c 100644 --- a/spf.go +++ b/spf.go @@ -789,7 +789,13 @@ func (r *resolution) mxField(res Result, field, domain string) (bool, Result, er r.count++ mxs, err := r.resolver.LookupMX(r.ctx, mxDomain) r.checkVoidLookup(len(mxs), err) - if err != nil { + + // If we get some results, use them even if we get an error alongisde. + // This happens when one of the records is invalid, because Go library can + // be quite strict about it. The RFC is not clear about this specific + // situation, and other SPF libraries and implementations just skip the + // invalid value, so we match common practice. + if err != nil && len(mxs) == 0 { // https://tools.ietf.org/html/rfc7208#section-5 if isNotFound(err) { return false, "", err diff --git a/spf_test.go b/spf_test.go index 65d1a86..a23a00f 100644 --- a/spf_test.go +++ b/spf_test.go @@ -335,6 +335,28 @@ func TestDNSPermanentErrors(t *testing.T) { } } +func TestMXWithInvalidRecord(t *testing.T) { + dns := NewDefaultResolver() + dnsError := &net.DNSError{ + Err: "permanent error for testing", + IsTemporary: false, + } + + // MX lookup on "dom2" will return an error and also some records. + // We expect the resolution to use the valid records, and ignore + // the error. + dns.Txt["domain"] = []string{"v=spf1 mx:dom2 -all"} + dns.Mx["dom2"] = []*net.MX{mx("oneoneoneone", 10)} + dns.Errors["dom2"] = dnsError + dns.Ip["oneoneoneone"] = []net.IP{ip1111} + defaultTrace = t.Logf + + res, err := CheckHost(ip1111, "domain") + if res != Pass { + t.Errorf("expected pass, got %v (%v)", res, err) + } +} + func TestMacros(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf