Documentation ¶
Overview ¶
Package spf implements an SPF checker to evaluate whether or not an email messages passes a published SPF (Sender Policy Framework) policy.
It implements all of the SPF checker protocol as described in RFC 7208, including macros and PTR checks, and passes 100% of the openspf and pyspf test suites.
A DNS stub resolver is included, but can be replaced by anything that implements the spf.Resolver interface.
The Hook interface can be used to hook into the check_host function to see more details about why a policy passes or fails.
Index ¶
- Constants
- Variables
- func MacroIsValid(macroString string) bool
- type Checker
- func (c *Checker) CheckHost(ctx context.Context, ip net.IP, domain, sender string, helo string) Result
- func (c *Checker) ExpandDomainSpec(ctx context.Context, domainSpec string, result *Result, domain string, ...) (string, error)
- func (c *Checker) ExpandMacro(ctx context.Context, domainSpec string, result *Result, domain string, ...) (string, error)
- func (c *Checker) SPF(ctx context.Context, ip net.IP, mailFrom string, helo string) Result
- type DefaultResolver
- type Hook
- type Mechanism
- type MechanismA
- type MechanismAll
- type MechanismExists
- type MechanismInclude
- type MechanismIp4
- type MechanismIp6
- type MechanismMX
- type MechanismPTR
- type Resolver
- type Result
- type ResultType
- type SPFRecord
Examples ¶
Constants ¶
const DefaultDNSLimit = 10
DefaultDNSLimit is the maximum number of SPF terms that require DNS resolution to allow before returning a failure.
const DefaultMXAddressLimit = 10
DefaultMXAddressLimit is the maximum number of A or AAAA requests to allow while evaluating each "mx" mechanism before returning a failure.
const DefaultPtrAddressLimit = 10
DefaultPtrAddressLimit is the limit on how many PTR records will be used when evaluating a "ptr" mechanism or a "%{p}" macro.
const DefaultVoidQueryLimit = 2
DefaultVoidQueryLimit is the maximum number of DNS queries that return no records to allow before returning a failure.
Variables ¶
var ResolvConf = "/etc/resolv.conf"
ResolvConf holds the path to a resolv.conf(5) format file used to configure DefaultResolver.
var ResultChar = map[ResultType]string{
None: "",
Neutral: "?",
Pass: "",
Fail: "-",
Softfail: "~",
}
ResultChar maps between the spf.ResultType and the equivalent single character qualifier used in SPF text format.
Functions ¶
Types ¶
type Checker ¶
type Checker struct { Resolver Resolver // used to resolve all DNS queries DNSLimit int // maximum number of DNS-using mechanisms MXAddressLimit int // maximum number of hostnames in an "mx" mechanism VoidQueryLimit int // maximum number of empty DNS responses PtrAddressLimit int // use only this many PTR responses Hostname string // the hostname of the machine running the check Hook Hook // instrumentation hooks }
Checker holds all the configuration and limits for checking SPF records.
var DefaultChecker *Checker
DefaultChecker is the Checker that will be used by the package level spf.Check function.
func NewChecker ¶
func NewChecker() *Checker
NewChecker creates a new Checker with sensible defaults.
func (*Checker) CheckHost ¶
func (c *Checker) CheckHost(ctx context.Context, ip net.IP, domain, sender string, helo string) Result
CheckHost implements the SPF check_host() function for a given domain.
func (*Checker) ExpandDomainSpec ¶
func (c *Checker) ExpandDomainSpec(ctx context.Context, domainSpec string, result *Result, domain string, exp bool) (string, error)
ExpandDomainSpec expands a domain-spec as an SPF macro, then checks that the result is a valid-appearing hostname.
func (*Checker) ExpandMacro ¶
func (c *Checker) ExpandMacro(ctx context.Context, domainSpec string, result *Result, domain string, exp bool) (string, error)
ExpandMacro populates an SPF macro based on the current state of the check process.
func (*Checker) SPF ¶
SPF checks SPF policy for a message using both smtp.mailfrom and smtp.helo.
Example ¶
package main import ( "context" "fmt" "net" "github.com/wttw/spf" ) func main() { ip := net.ParseIP("8.8.8.8") c := spf.NewChecker() c.Hostname = "mail.example.com" result := c.SPF(context.Background(), ip, "steve@aol.com", "aol.com") fmt.Printf("Authentication-Results: %s\n", result.AuthenticationResults()) }
Output: Authentication-Results: mail.example.com; spf=softfail smtp.helo=aol.com
type DefaultResolver ¶
type DefaultResolver struct {
// contains filtered or unexported fields
}
DefaultResolver is the Resolver that will be used in default constructed Checkers.
type Hook ¶
type Hook interface { Dns(r *dns.Msg, m *dns.Msg, err error) // a dns record was looked up Record(record, domain string) // an SPF record is about to be processed RecordResult(domain string, result *Result) // an SPF record has completed processing Macro(before, after string, err error) // a macro has been expanded Mechanism(domain string, index int, mechanism Mechanism, result *Result) // an SPF mechanism has provided a result Redirect(target string) // an SPF redirect modifier is about to be executed }
Hook allows a caller to intercept the SPF check process at various points through it's execution.
type Mechanism ¶
type Mechanism interface { Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error) String() string }
Mechanism holds an SPF mechanism
func NewMechanism ¶
NewMechanism creates a new Mechanism from it's text representation
type MechanismA ¶
MechanismA represents an SPF "a" mechanism. It matches based on DNS lookups of A and AAAA records for it's domain-spec.
func (MechanismA) Evaluate ¶
func (m MechanismA) Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error)
func (MechanismA) String ¶
func (m MechanismA) String() string
type MechanismAll ¶
type MechanismAll struct {
Qualifier ResultType
}
MechanismAll represents an SPF "all" mechanism, it always matches.
func (MechanismAll) Evaluate ¶
func (m MechanismAll) Evaluate(_ context.Context, _ *Result, _ string) (ResultType, error)
func (MechanismAll) String ¶
func (m MechanismAll) String() string
type MechanismExists ¶
type MechanismExists struct { Qualifier ResultType DomainSpec string }
MechanismExists represents an SPF "exists" mechanism. It matches based on the existence of a DNS A record for the - macro-expanded - domain-spec.
func (MechanismExists) Evaluate ¶
func (m MechanismExists) Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error)
func (MechanismExists) String ¶
func (m MechanismExists) String() string
type MechanismInclude ¶
type MechanismInclude struct { Qualifier ResultType DomainSpec string }
MechanismInclude represents an SPF "include" mechanism, it matches based on the result of an SPF check on another host name.
func (MechanismInclude) Evaluate ¶
func (m MechanismInclude) Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error)
func (MechanismInclude) String ¶
func (m MechanismInclude) String() string
type MechanismIp4 ¶
type MechanismIp4 struct { Qualifier ResultType Net *net.IPNet }
MechanismIp4 represents an SPF "ip4" mechanism. It matches based on the connecting IP being within the provided address range.
func (MechanismIp4) Evaluate ¶
func (m MechanismIp4) Evaluate(_ context.Context, result *Result, _ string) (ResultType, error)
func (MechanismIp4) String ¶
func (m MechanismIp4) String() string
type MechanismIp6 ¶
type MechanismIp6 struct { Qualifier ResultType Net *net.IPNet }
MechanismIp6 represents an SPF "ip6" mechanism. It matches based on the connecting IP being within the provided address range.
func (MechanismIp6) Evaluate ¶
func (m MechanismIp6) Evaluate(_ context.Context, result *Result, _ string) (ResultType, error)
func (MechanismIp6) String ¶
func (m MechanismIp6) String() string
type MechanismMX ¶
type MechanismMX struct { Qualifier ResultType DomainSpec string Mask4 net.IPMask Mask6 net.IPMask }
MechanismMX represents an SPF "mx" mechanism. It matches based on DNS lookups of MX records for it's domain-spec, and DNS lookups for A and AAAA records for the results of those.
func (MechanismMX) Evaluate ¶
func (m MechanismMX) Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error)
func (MechanismMX) String ¶
func (m MechanismMX) String() string
type MechanismPTR ¶
type MechanismPTR struct { Qualifier ResultType DomainSpec string }
MechanismPTR represents an SPF "ptr" mechanism.
func (MechanismPTR) Evaluate ¶
func (m MechanismPTR) Evaluate(ctx context.Context, result *Result, domain string) (ResultType, error)
MechanismPTR represents the SPF "ptr" mechanism.
func (MechanismPTR) String ¶
func (m MechanismPTR) String() string
type Result ¶
type Result struct { Type ResultType Error error DNSQueries int VoidLookups int Explanation string UsedHelo bool // contains filtered or unexported fields }
Result is all the information gathered during checking SPF for a message.
func (*Result) AuthenticationResults ¶
AuthenticationResults displays a Result as an RFC 8601 Authentication-Results: header
type ResultType ¶
type ResultType int
ResultType is the overall SPF result from checking a message.
const ( None ResultType = iota Neutral Pass Fail Softfail Temperror Permerror )
func Check ¶
Check checks SPF policy for a message using both smtp.mailfrom and smtp.helo.
Example ¶
package main import ( "context" "fmt" "net" "github.com/wttw/spf" ) func main() { ip := net.ParseIP("8.8.8.8") result, _ := spf.Check(context.Background(), ip, "steve@aol.com", "aol.com") fmt.Println(result) }
Output: softfail
func ResultTypeString ¶
func ResultTypeString(s string) (ResultType, error)
ResultTypeString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.
func ResultTypeValues ¶
func ResultTypeValues() []ResultType
ResultTypeValues returns all values of the enum
func (ResultType) IsAResultType ¶
func (i ResultType) IsAResultType() bool
IsAResultType returns "true" if the value is listed in the enum definition. "false" otherwise
func (ResultType) String ¶
func (i ResultType) String() string