mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 18:24:35 +03:00
add more documentation, examples with tests to illustrate reusable components
This commit is contained in:
61
spf/examples_test.go
Normal file
61
spf/examples_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
package spf_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"golang.org/x/exp/slog"
|
||||
|
||||
"github.com/mjl-/mox/dns"
|
||||
"github.com/mjl-/mox/smtp"
|
||||
"github.com/mjl-/mox/spf"
|
||||
)
|
||||
|
||||
func ExampleVerify() {
|
||||
ctx := context.Background()
|
||||
resolver := dns.StrictResolver{}
|
||||
|
||||
args := spf.Args{
|
||||
// IP from SMTP session.
|
||||
RemoteIP: net.ParseIP("1.2.3.4"),
|
||||
|
||||
// Based on "MAIL FROM" in SMTP session.
|
||||
MailFromLocalpart: smtp.Localpart("user"),
|
||||
MailFromDomain: dns.Domain{ASCII: "sendingdomain.example.com"},
|
||||
|
||||
// From HELO/EHLO in SMTP session.
|
||||
HelloDomain: dns.IPDomain{Domain: dns.Domain{ASCII: "mx.example.com"}},
|
||||
|
||||
// LocalIP and LocalHostname should be set, they may be used when evaluating macro's.
|
||||
}
|
||||
|
||||
// Lookup SPF record and evaluate against IP and domain in args.
|
||||
received, domain, explanation, authentic, err := spf.Verify(ctx, slog.Default(), resolver, args)
|
||||
|
||||
// received.Result is always set, regardless of err.
|
||||
switch received.Result {
|
||||
case spf.StatusNone:
|
||||
log.Printf("no useful spf result, domain probably has no spf record")
|
||||
case spf.StatusNeutral:
|
||||
log.Printf("spf has no statement on ip, with \"?\" qualifier")
|
||||
case spf.StatusPass:
|
||||
log.Printf("ip is authorized")
|
||||
case spf.StatusFail:
|
||||
log.Printf("ip is not authorized, with \"-\" qualifier")
|
||||
case spf.StatusSoftfail:
|
||||
log.Printf("ip is probably not authorized, with \"~\" qualifier, softfail")
|
||||
case spf.StatusTemperror:
|
||||
log.Printf("temporary error, possibly dns lookup failure, try again soon")
|
||||
case spf.StatusPermerror:
|
||||
log.Printf("permanent error, possibly invalid spf records, later attempts likely have the same result")
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("error: %v", err)
|
||||
}
|
||||
if explanation != "" {
|
||||
log.Printf("explanation from remote about spf result: %s", explanation)
|
||||
}
|
||||
log.Printf("result is for domain %s", domain) // mailfrom or ehlo/ehlo.
|
||||
log.Printf("dns lookups dnssec-protected: %v", authentic)
|
||||
}
|
@ -83,8 +83,8 @@ func quotedString(s string) string {
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// Header returns a Received-SPF header line including trailing crlf that can
|
||||
// be prepended to an incoming message.
|
||||
// Header returns a Received-SPF header including trailing crlf that can be
|
||||
// prepended to an incoming message.
|
||||
func (r Received) Header() string {
|
||||
// ../rfc/7208:2043
|
||||
w := &message.HeaderWriter{}
|
||||
|
@ -117,7 +117,7 @@ var timeNow = time.Now
|
||||
|
||||
// Lookup looks up and parses an SPF TXT record for domain.
|
||||
//
|
||||
// authentic indicates if the DNS results were DNSSEC-verified.
|
||||
// Authentic indicates if the DNS results were DNSSEC-verified.
|
||||
func Lookup(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, domain dns.Domain) (rstatus Status, rtxt string, rrecord *Record, authentic bool, rerr error) {
|
||||
log := mlog.New("spf", elog)
|
||||
start := time.Now()
|
||||
@ -186,7 +186,7 @@ func Lookup(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, domai
|
||||
// Verify takes the maximum number of 10 DNS requests into account, and the maximum
|
||||
// of 2 lookups resulting in no records ("void lookups").
|
||||
//
|
||||
// authentic indicates if the DNS results were DNSSEC-verified.
|
||||
// Authentic indicates if the DNS results were DNSSEC-verified.
|
||||
func Verify(ctx context.Context, elog *slog.Logger, resolver dns.Resolver, args Args) (received Received, domain dns.Domain, explanation string, authentic bool, rerr error) {
|
||||
log := mlog.New("spf", elog)
|
||||
start := time.Now()
|
||||
@ -869,7 +869,7 @@ func expandIP(ip net.IP) string {
|
||||
}
|
||||
|
||||
// validateDNS checks if a DNS name is valid. Must not end in dot. This does not
|
||||
// check valid host names, e.g. _ is allows in DNS but not in a host name.
|
||||
// check valid host names, e.g. _ is allowed in DNS but not in a host name.
|
||||
func validateDNS(s string) error {
|
||||
// ../rfc/7208:800
|
||||
// note: we are not checking for max 253 bytes length, because one of the callers may be chopping off labels to "correct" the name.
|
||||
|
Reference in New Issue
Block a user