# spftrace The **spftrace** utility is a tool for executing, analysing, and displaying SPF queries. SPF is specified in [RFC 7208]. This utility executes an SPF query with IP address and domain and shows the result graphically as an evaluation tree. This utility uses the [viaspf] library to execute SPF queries. The viaspf library can trace a query as it executes and makes the trace available as structured data in its API. spftrace then analyses this data and displays it. Thanks to the underlying execution engine being a real, RFC-conformant SPF implementation, spftrace handles all SPF policies correctly. Less well-known features of SPF such as macros, dual CIDR prefix lengths, *exp* modifiers, or the void lookup limit are all evaluated according to spec. Internationalised email domains are equally supported. [RFC 7208]: https://www.rfc-editor.org/rfc/rfc7208 [viaspf]: https://crates.io/crates/viaspf ## Installation The spftrace utility is a [Rust] program; install it with Cargo as usual. For example, use the following command to install the latest version published on [crates.io]: ``` cargo install --locked spftrace ``` The minimum supported Rust version is 1.65.0. [Rust]: https://www.rust-lang.org [crates.io]: https://crates.io/crates/spftrace ## Usage Pass a sender identity (an email address or a domain name) and an IP address to spftrace. Use the unspecified IP address `0.0.0.0` (IPv4) or `::` (IPv6) to display the full evaluation tree of some SPF-enabled domain. ``` spftrace example.com 0.0.0.0 ``` ``` example.com │ "v=spf1 mx include:spf.example.com ~all" ├── mx → example.com (lookups: 1/10, nested: 2/10) │ ├── mx1.example.com │ │ ├── 216.58.192.0 │ │ ├── 65.55.52.224 │ │ └── 207.46.116.128 │ └── mx2.example.com │ └── 65.55.238.129 │ not-match ├── include:spf.example.com → spf.example.com (lookups: 2/10) │ spf.example.com │ │ "v=spf1 ip4:207.46.4.128/25 ip4:65.55.174.0/24 ip6:2c0f:fb50:4000::/36 │ │ ip6:2001:4860:4000::/36 ~all" │ ├── ip4:207.46.4.128/25 not-match │ ├── ip4:65.55.174.0/24 not-match │ ├── ip6:2c0f:fb50:4000::/36 not-match │ ├── ip6:2001:4860:4000::/36 not-match │ └── all match result=softfail │ not-match └── all match result=softfail softfail ``` The command shown above can be abbreviated to `spftrace example.com`: When no IP address is specified, `0.0.0.0` is assumed. For details, refer to the included manual page [*spftrace*(1)]. (You can view the manual page without installing by passing the file path to `man`: `man ./spftrace.1`) [*spftrace*(1)]: https://codeberg.org/glts/spftrace/src/tag/0.3.0/spftrace.1 ## Development Unit tests are in separate module `tests`. Specify a test name and pass the `--test-threads 1` test binary option to run and visually check some test (Cargo is unable to capture stdout, so limiting the number of threads at least avoids interleaved output). For example: ``` cargo test ptr -- --test-threads 1 ``` ## Licence Copyright © 2022–2023 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 .