Spf.Context (Spfcheck v0.10.0) View Source
Functions to create, access and update an SPF evaluation context.
Many functions take and return an evaluation context whose purpose is to store information gathered during the evaluation. This includes a dns cache, an ip lookup table that maps prefixes to SPF terms that named them, a stack for recursive evaluations, as well as some statistics around DNS mechanisms seen and void DNS responses seen.
Link to this section Summary
Types
A {qualifier, nth, term} tuple, where nth is the nth SPF record where term was
found.
An SPF evaluation context.
An SPF evaluation result.
Functions
Updates context with given error, reason and verdict.
Returns a previous SPF string given either its domain of nth-tracking number.
Updates context's message queue and, if available, calls the user supplied log
function.
Returns true if new_domain constitues a loop for given context, false
otherwise.
Returns a new Spf.Context.t/0 for given sender.
Pop the previous state of given context from its stack.
Push the current state of given context onto its stack and re-init the context.
Reinitializes current context for given domain of a redirect modifier.
Given a current context and a range, return the SPF term in that range.
Split an email address into a local and a domain part.
If test is true, logs the given msg with its facility and severity.
Adds delta to counter and returns updated context.
Link to this section Types
Specs
iptval() :: {Spf.Lexer.q(), non_neg_integer(), binary()}
A {qualifier, nth, term} tuple, where nth is the nth SPF record where term was
found.
The context's ip lookup table stores these tuples thus tracking which term in which SPF record provided a qualifier for a prefix. Since an evaluation may involve multiple SPF records, each prefix actually stores a list of these tuples.
Once the sender's ip has a longest prefix match, the qualifier will tell how the mechanism at hand matches.
Specs
prefix() :: Pfx.prefix()
A Pfx.prefix/0.
Specs
t() :: %{
ast: list(),
atype: :a | :aaaa,
contact: binary(),
depth: non_neg_integer(),
dns: map(),
dns_timeout: non_neg_integer(),
domain: binary(),
duration: non_neg_integer(),
error: nil | atom(),
explain: nil | tuple(),
explain_string: binary(),
explanation: binary(),
helo: binary(),
ip: binary(),
ipt: Iptrie.t(),
local: binary(),
log: nil | function(),
map: map(),
max_dnsm: non_neg_integer(),
max_dnsv: non_neg_integer(),
msg: list(),
nameservers: nil | list(),
nth: non_neg_integer(),
num_checks: non_neg_integer(),
num_dnsm: non_neg_integer(),
num_dnsq: non_neg_integer(),
num_dnsv: non_neg_integer(),
num_error: non_neg_integer(),
num_spf: non_neg_integer(),
num_warn: non_neg_integer(),
owner: binary(),
reason: binary(),
sender: binary(),
spf: binary(),
spf_rest: binary(),
spf_tokens: list(),
stack: list(),
t0: non_neg_integer(),
traces: map(),
verbosity: non_neg_integer(),
verdict: verdict()
}
An SPF evaluation context.
Field notes:
astis a list of SPF terms to be evaluated as produced bySpf.Parseratypeis set according to the sender's IP addresscontactis gleaned from the soa record fordomainunder evaluationdepthis the nested depth during recursion, used to print a tree of log messagesdnsis the DNS cache, used to report on DNS information gathered during evaluationdurationis the time (in milliseconds) it took to evaluate the SPF policyerrorset by eitherSpf.ParserorSpf.Evaland halts evaluation if setexplainis the token for theexp=-modifier, if any (not needed for actual evaluation)explain_stringis the explanation after all expansions (when available and applicable)heloas set by the:helooption given toSpf.check/2ipis the sender IP, as set by the:ipoption given toSpf.check/2(default127.0.0.1)iptis anIptrie.t/0used to record addresses and/or prefixes authorized to send mailslocalis the local part of thesenderlogis the user callback log function as provided by the:logoption toSpf.check/2mapis used to recordnth=> domain and domain => spf-stringmax_dnsmis the max of dns-mechanisms allowed (default 10), if it took more => permerrormax_dnsvis the max of void dns-responses allowed (default 2), if it took more => permerrormsgthe list of logged messages by the Spf modulesnameserversa list of nameservers to use or nil (uses system default)nthis the nth SPF record being evaluatednum_checkscounts how many checks were performed during evaluationnum_dnsmcounts the number of dns-mechanisms seen during evaluationnum_dnsqcounts the number of dns queries performed during evaluationnum_dnsvcounts the number of void DNS responses seen during evaluationnum_errorcounts the number of errors seen during evaluationnum_spfcounts the number of SPF records evaluatednum_warncounts the number of warnings seen during evaluationownershows the SOA zone for the original SPF domain being evaluatedreasonshows the reason for the verdict, usually in the form of an SPF termsenderis the sender as given toSpf.check/2spfis the SPF string of thedomainbeing evaluated (if any)spf_restis the remainder of the SPF string (should always by "")spf_tokensis theSpf.Lexer's result of lexing the SPF string (last seen)stackis used to push/pop the evaluation state during recursive callst0is the Unix Epoch time the evaluation startedtracesis a map used to detect loops in an SPF policyverbositycontrols the level of logged messages to stderrverdictis the final result of the SPF evaluation bySpf.check/2
Other notes:
max_dnsmandmax_dnsvare only checked after evaluating the entire policy- this allows to debug most of the SPF policy under consideration
Spf.Parsermay set an syntaxerror, in which case the SPF record results in a permerror- the
astis produced by the parser by processing allspf_tokens - whitespace tokens are used to report on repeated whitespace in an SPF string
- whitespace tokens donot end up in the AST
v=spf1-modifier is checked and if not present, results in an error- by processing all tokens, any
errorset reflects the last error seen
- the
Spf.Evalmay set an evaluationerror, which may result in an overall permerror- a void DNS response is either a
NXDOMAINorZERO ANSWERS
Specs
token() :: Spf.Lexer.token()
Specs
verdict() :: :fail | :neutral | :none | :pass | :permerror | :softfail | :temperror
An SPF evaluation result.
Link to this section Functions
Specs
Updates context.ipt with one or more {prefix/0, iptval/0}-pairs.
When given a list op ip's, they all will be be updated with given
iptval/0 which records the SPF record and term (including the qualifier)
that attributed the ip or ip's.
The dual parameter contains the dual-cidr lengths to apply to the given
ip addresses.
Specs
Updates context with given error, reason and verdict.
When verdict is nil, context.verdict is not updated. This
allows for setting error conditions whose impact is to be evaluated
at a later stage.
Specs
Returns a previous SPF string given either its domain of nth-tracking number.
Used for reporting rather than evalutation an SPF record.
Specs
Updates context's message queue and, if available, calls the user supplied log
function.
The log/4 is called with:
contextthe current context/state of the evalutionfacilityan atom denoting which part of the program emitted the eventseverityan atom describing the severitymsga binary with event details
Specs
Returns true if new_domain constitues a loop for given context, false
otherwise.
Loops may occur when two SPF records (eventually) include or redirect to each other and is considered a permanent error.
Specs
Returns a new Spf.Context.t/0 for given sender.
Options include:
:dns, filepath or binary with zonedata (defaults to nil):helo, sender's helo string to use (defaults tosender):ip, sender ip to use (defaults to127.0.0.1):log, user supplied log function (defaults to nil):verbosity, log level0..5to use (defaults to4):nameserver, IPv4 or IPv6 address of a nameserver to use instead of the default
The initial domain is derived from given sender. The default for
ip is likely to traverse all SPF mechanisms during evaluation, gathering
as much information as possible. Set :ip to a real IPv4 or IPv6 address
to check an SPF policy for that specific address.
The context is used for the entire SPF evaluation, including during any
recursive calls. When evaluating an include mechanism, the current state (a
few selected context properties) is pushed onto an internal stack and a new
domain is set. After evaluating the include mechanism, the state if
popped and the results are processed according to the include-mechanism's
qualifier.
When evaluating a redirect modifier, the current state is altered for the
new domain specified by the modifier.
Specify more than one recursive nameserver by repeating the :nameserver
option in the Keyword list. They will be tried in the order listed. Mainly
useful when the local default recursive nameserver is having problems, or
when an external nameserver is to be used for checking an SPF policy instead
of an internal nameserver. As an example, use in opts [nameserver: "2001:4860:4860::8888", nameserver: "2001:4860:4860::8844"] to use the IPv6
dns.google servers.
Specs
Pop the previous state of given context from its stack.
Before evaluating an include mechanism, the current SPF's record state is pushed onto the stack. This function restores that state from the stack.
Specs
Push the current state of given context onto its stack and re-init the context.
The details of the current SPF record are pushed onto a stack and the context
is re-initialized for retrieving, parsing and evaluate a new included
record.
Specs
Reinitializes current context for given domain of a redirect modifier.
When a redirect modifier is encountered it basically replaces the current SPF record and the context is modified accordingly.
Specs
Given a current context and a range, return the SPF term in that range.
Retrieves a slice of the current SPF record being evaluated. Used for logging events.
Specs
Split an email address into a local and a domain part.
The local part is left to the left-most @, if there is no local
part it defaults to "postmaster". Note that splitting an empty
string yields {"postmaster", ""}.
Specs
If test is true, logs the given msg with its facility and severity.
A convencience function to quickly check some test and, if true, log it as well in one go.
Specs
Adds delta to counter and returns updated context.
Valid counters include:
:num_spf, the number of SPF records seen:num_dnsmthe number of DNS mechanisms seen:num_dnsqthe number of DNS queries performed:num_dnsvthe number of void DNS queries seen:num_checksthe number of checks performed:num_warnthe number of warnings seen:num_errorthe number of errors see (may not be fatal):depththe current recursion depth