#email #smtp #dns #domain #spf


Implementation of the Sender Policy Framework (SPF) protocol

4 releases

new 0.0.4 Sep 26, 2020
0.0.3 Aug 27, 2020
0.0.2 Jul 4, 2020
0.0.1 May 29, 2020

#26 in Email

35 downloads per month
Used in 3 crates (2 directly)




This library is experimental/in development. The API is now being stabilised, but may still change. Please try out the master branch, feedback on API and implementation is welcome!

The viaspf library is a complete implementation of the Sender Policy Framework (SPF) protocol, version 1, as specified in RFC 7208. It is written in the Rust programming language.

This library implements the core SPF protocol, but it does not itself do DNS queries and it does not depend on a DNS library. Users of this library must provide an implementation of a DNS lookup trait in order to perform SPF queries. That way, we hope to enable users to choose themselves which DNS resolver they want to use to implement their SPF verifier applications.

This library was first created in a ‘clean room’ setting. That is, it was written from scratch, referring only to the RFC, and following it to the letter. It can therefore be considered an independent alternative to existing SPF protocol implementations.

The minimum supported Rust version is 1.42.0.


This is a Rust library, for consumption through Cargo as usual.

The main purpose of the viaspf library is SPF verification, that is, checking whether a sending host is authorised to use some mail domain according to published SPF policy. For this end, this library provides the function evaluate_spf as the main API item. The function signature is as follows:

fn evaluate_spf(
    lookup: &impl Lookup,
    config: &Config,
    ip: IpAddr,
    sender: &str,
    helo_domain: &str,
) -> QueryResult;

Refer to the API documentation for a full description of the inputs and output, and suggested usage patterns.

The first argument, lookup, deserves brief elaboration. While viaspf contains a complete implementation of the SPF protocol, it does not itself include DNS resolution capabilities (which are, after all, a core component of SPF). Instead, DNS resolution is abstracted into the trait Lookup, and is thus ‘pluggable’. evaluate_spf requires to be passed an implementation of this trait, which it will then use as a DNS resolver through which all DNS queries are conducted. Consult the API documentation for implementation requirements for the Lookup trait, and the included example for a sample implementation.

Note that it is also possible to forgo the SPF evaluation functionality and only use the library’s data model. The data structures in viaspf::record constitute a faithful encoding of the grammar in section 12 of RFC 7208, and are mostly decoupled from evaluation.

Finally, we point again to the API documentation, which describes additional functionality, such as capturing a trace of the query execution. The trace provides programmatic access to the protocol processing steps after the fact.


A simple SPF verifier is included as an executable example: the command-line tool spfquery. This program uses the Trust-DNS DNS resolver to perform DNS lookups.

Pass an IP address and a domain as arguments to spfquery. The query is then evaluated and the result and a trace is printed out.

cargo run --example spfquery gluet.ch
Domain: gluet.ch
SPF result: pass
Mechanism: mx
  executing SPF query for domain "gluet.ch"
  looking up TXT records for "gluet.ch"
  evaluating SPF record "v=spf1 mx -all"
  evaluating directive "mx"
  evaluating mechanism "mx"
  incrementing global lookup count
  using target name "gluet.ch"
  looking up MX records for "gluet.ch"
  trying MX name "mail.gluet.ch"
  incrementing global lookup count
  looking up A records for "mail.gluet.ch"
  trying IP address
  incrementing per-mechanism lookup count
  mechanism matched
  evaluated directive to result "pass"


Copyright © 2020 David Bürgin

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.


~55K SLoC