SPF Why?
Explains your SPF checker results.
Check Result
Pass
Details
SPF check by mx1.xel.nl
for samy@ascha.org
in scope mfrom
has result pass
because 213.154.226.3
matches mx
in SPF record:
v=spf1 mx include:spf.xel.nl -all
Form
Use the form below if you want to do a manual SPF check:
Documentation
This tool can be used to explain SPF check results by including a parameterized link in logs and error messages, or by manualy querying the API. It copies the simple API at open-spf.org/Why and can be used as an alternative in e.g. policyd-spf.
API Usage
There is one endpoint: /.
It accepts a GET request with the following query parameters:
| Required | Name | Parameter | Default | Examples |
|---|---|---|---|---|
| Versions | v | 1 | v=1 | |
| Scope | s | mfrom | s=helo | |
| * | Identity | id | id=user@example.com, id=mta.example.com | |
| * | IP-address | ip | ip=169.254.0.7, ip=fe80::2a:7 | |
| Receiver | r | unknown | r=mx.example.com |
Example
GET /?id=user@example.net&ip=169.254.0.7&v=1&s=mfrom&r=mx.example.com
HEAD Request
Alternatively, you can send a HEAD request where the result code, and other details for the check, will be in the response headers as:
X-SPF-Why-Result-Code: fail X-SPF-Why-Result-Mechanism: -all X-SPF-Why-Query-Versions: 1 X-SPF-Why-Query-Scope: mfrom X-SPF-Why-Query-Id: user@example.net X-SPF-Why-Query-Ip: 169.254.0.7 X-SPF-Why-Query-Receiver: mx.example.com
Content Types
You can use other content types besides the default text/html. Specifically: application/json and text/plain.
Example JSON response:
{
"query": {
"versions": [
"1"
],
"scope": "mfrom",
"identity": "user@example.net",
"ip": "169.254.0.7",
"receiver": "mx.example.com"
},
"result": {
"code": "fail",
"mechanism": "-all"
}
}
Example plaintext response:
SPF check by mx.example.com for user@example.net in scope mfrom has result fail because 169.254.0.7 matches -all in SPF record: v=spf1 -all
About
This tool uses mlocati/spf-lib for SPF heavy lifting.
Hosting by xel.
Samy Ascha, samy@ascha.org.