#dns-lookup #ip-address #spf

viaspf

Implementation of the Sender Policy Framework (SPF) specification

27 releases

0.7.0-alpha.2 May 6, 2024
0.7.0-alpha.1 Nov 28, 2023
0.6.0 Sep 12, 2023
0.6.0-alpha.1 Jul 12, 2023
0.0.2 Jul 4, 2020

#27 in Email

Download history 103/week @ 2024-07-15 25/week @ 2024-07-22 94/week @ 2024-07-29 30/week @ 2024-08-05 49/week @ 2024-08-12 15/week @ 2024-08-19 37/week @ 2024-08-26 39/week @ 2024-09-02 111/week @ 2024-09-09 44/week @ 2024-09-16 188/week @ 2024-09-23 112/week @ 2024-09-30 134/week @ 2024-10-07 55/week @ 2024-10-14 26/week @ 2024-10-21 11/week @ 2024-10-28

233 downloads per month
Used in 17 crates (4 directly)

GPL-3.0-or-later

230KB
4.5K SLoC

viaspf

The viaspf library contains a complete implementation of the Sender Policy Framework (SPF) specification, version 1, as described in RFC 7208. It provides an asynchronous API for checking an email sender’s authorisation according to the specification.

This library implements the core SPF protocol, but it does not directly depend on a DNS resolver. Instead, users of this library can provide an implementation of a DNS lookup trait, and so choose themselves which DNS resolver they want to use to implement their SPF verifier applications.

The implementation uses Tokio, but for the timeout logic only. If needed, it is possible to use a different async runtime for driving the library by toggling certain Cargo features.

This library was first created in a ‘clean room’ setting. It was written from scratch, referring only to the RFC, and following it to the letter. Extensive checking ensures correctness and conformance with RFC 7208.

The minimum supported Rust version is 1.67.0.

Usage

This is a Rust library. Include viaspf in Cargo.toml as usual. For ease of use, you may want to enable the feature hickory-resolver; see below.

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. The function evaluate_sender is provided as the main API item.

use std::net::IpAddr;
use viaspf::*;

let config = Default::default();
let ip = IpAddr::from([1, 2, 3, 4]);
let mail_from = "amy@example.org";

let spf_result = match mail_from.parse() {
    Ok(sender) => {
        evaluate_sender(&resolver, &config, ip, &sender, None)
            .await
            .spf_result
    }
    _ => SpfResult::None,
};

assert_eq!(spf_result, SpfResult::Pass);

The example above is straightforward. It demonstrates checking of the MAIL FROM identity amy@example.org.

The first argument, resolver, deserves a brief explanation. While viaspf contains a complete implementation of the SPF protocol, it does not itself include DNS resolution capabilities. Instead, DNS resolution is abstracted into the trait Lookup, and is thus ‘pluggable’. Provide an implementation of this trait using the resolver of your choice to control how DNS queries are done.

As a convenience, the Cargo feature hickory-resolver can be enabled to make an implementation of Lookup available for the Hickory DNS resolver.

Refer to the API documentation for details.

Examples

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

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

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

For interactive use of the viaspf library, please see the command-line utility spftrace.

Licence

Copyright © 2020–2024 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.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Dependencies

~1.2–8MB
~83K SLoC