| author | Alberto Bertogli
<albertito@blitiri.com.ar> 2026-08-23 12:02:26 UTC |
| committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2026-08-23 12:02:26 UTC |
| parent | d2b814bc9cdd8cb89726a72e8fc3ee8fff7124be |
| spf.go | +8 | -5 |
| spf_test.go | +13 | -3 |
| testdata/blitirispf-tests.yml | +0 | -1 |
diff --git a/spf.go b/spf.go index 9c302f8..ec83ea4 100644 --- a/spf.go +++ b/spf.go @@ -639,11 +639,14 @@ func (r *resolution) ptrField(res Result, field, domain string) (bool, Result, e return true, PermError, verr } if err != nil { - // https://tools.ietf.org/html/rfc7208#section-5 - if isNotFound(err) { - return false, "", err - } - return true, TempError, err + // Any DNS error here makes the mechanism fail to match, instead + // of the temperror that section 5 prescribes for the other + // mechanisms. The reverse zone is controlled by the operator of + // the connecting IP, not by the domain publishing the record, so + // errors in it must not affect the result. + // https://tools.ietf.org/html/rfc7208#section-5.5 + r.trace("ptr reverse lookup error, no match: %v", err) + return false, "", err } // Only take the first 10 names, ignore the rest. diff --git a/spf_test.go b/spf_test.go index 552110c..bc8a21d 100644 --- a/spf_test.go +++ b/spf_test.go @@ -424,8 +424,13 @@ func TestDNSTemporaryErrors(t *testing.T) { {"v=spf1 include:tmperr", TempError}, {"v=spf1 a:tmperr", TempError}, {"v=spf1 mx:tmperr", TempError}, - {"v=spf1 ptr:tmperr", TempError}, {"v=spf1 mx:tmpmx", TempError}, + + // "ptr" is the exception: a DNS error on the reverse lookup makes + // the mechanism fail to match, so we fall through to the end of the + // record and get neutral. + // https://tools.ietf.org/html/rfc7208#section-5.5 + {"v=spf1 ptr:tmperr", Neutral}, } for _, c := range cases { @@ -460,11 +465,16 @@ func TestDNSPermanentErrors(t *testing.T) { // RFC specifies that on any DNS error (other than NXDOMAIN), // we must return TempError. - // https://www.rfc-editor.org/rfc/rfc7208#section-5 + // https://tools.ietf.org/html/rfc7208#section-5 {"v=spf1 a:permerr", TempError}, {"v=spf1 mx:permerr", TempError}, - {"v=spf1 ptr:permerr", TempError}, {"v=spf1 mx:permmx", TempError}, + + // "ptr" is the exception: a DNS error on the reverse lookup makes + // the mechanism fail to match, so we fall through to the end of the + // record and get neutral. + // https://tools.ietf.org/html/rfc7208#section-5.5 + {"v=spf1 ptr:permerr", Neutral}, } for _, c := range cases { diff --git a/testdata/blitirispf-tests.yml b/testdata/blitirispf-tests.yml index e40196f..f68e7c3 100644 --- a/testdata/blitirispf-tests.yml +++ b/testdata/blitirispf-tests.yml @@ -1079,7 +1079,6 @@ tests: mailfrom: "foo@ptrerr.net" host: 1.2.3.4 result: softfail - skip: We return temperror instead of treating it as a no-match. zonedata: ptrerr.net: - SPF: v=spf1 ptr ~all