Test abd Debug SPF with command line

Testing SPF with command line
You can test SPF (sender policy framework) directly with spf.py script (python module). First, find a spf.py location:
~] find /usr -name "spf.py" -print
/usr/lib/python3/dist-packages/spf.py
Second, print a help and usage messages:
~] python3 /usr/lib/python3/dist-packages/spf.py
To check an incoming mail request:
% python spf.py [-v] {ip} {sender} {helo}
% python spf.py 69.55.226.139 tway@optsw.com mx1.wayforward.net
To test an SPF record:
% python spf.py [-v] "v=spf1..." {ip} {sender} {helo}
% python spf.py "v=spf1 +mx +ip4:10.0.0.1 -all" 10.0.0.1 tway@foo.com a
To fetch an SPF record:
% python spf.py {domain}
% python spf.py wayforward.net
To test this script (and to output this usage message):
% python spf.py
Test SPF record
We want test a heavy SPF record (with spf macro) for domain purestorage.com
~] dig txt purestorage.com | grep spf1
purestorage.com. 274 IN TXT "v=spf1 include:service-now.com include:purestorage.com._nspf.vali.email include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email include:stspg-customer.com ~all"
OpenDmarc with its own spf implementation has a big problem with spf macros:
2024-07-09T12:25:40.870137+02:00 mailin1 opendmarc[71798]: 4WJHFJ1TtJzsRC4: SPF(mailfrom): purestorage.com fail
2024-07-09T12:25:40.905392+02:00 mailin1 opendmarc[71798]: 4WJHFJ1TtJzsRC4: purestorage.com fail
2024-07-09T12:25:40.911064+02:00 mailin1 postfix/cleanup[853656]: 4WJHFJ1TtJzsRC4: milter-reject: END-OF-MESSAGE from smtp07-ia4-sp2.mta.salesforce.com[13.110.74.214]: 5.7.1 rejected by DMARC policy for purestorage.com; from=<support@purestorage.com> to=<my@email.com> proto=ESMTP helo=<smtp07-ia4-sp2.mta.salesforce.com>
So, we have all smtp sender information:
- ip: 13.110.74.214
- mail from sender email address: support@purestorage.com
- hello message from sender email server: smtp07-ia4-sp2.mta.salesforce.com
Further reading: SPF - Sender Policy Framework
For more verbose SPF check use a -v
~] python3 /usr/lib/python3/dist-packages/spf.py -v 13.110.74.214 support@purestorage.com smtp07-ia4-sp2.mta.salesforce.com
top: purestorage.com "v=spf1 include:service-now.com include:purestorage.com._nspf.vali.email include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email include:stspg-customer.com ~all"
include: service-now.com "v=spf1 a:b.spf.service-now.com a:c.spf.service-now.com a:d.spf.service-now.com ~all"
include: purestorage.com._nspf.vali.email "v=spf1 -all"
include: 13.110.74.214._ip.smtp07-ia4-sp2.mta.salesforce.com._ehlo.purestorage.com._spf.vali.email "v=spf1 include:_spf.salesforce.com -all"
include: _spf.salesforce.com "v=spf1 exists:%{i}._spf.mta.salesforce.com -all"
result: ('pass', 250, 'sender SPF authorized') include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email
Let's test if spf from the postfix-policyd-spf-python package tests spf authorization correctly.
~] python3 /usr/lib/python3/dist-packages/spf.py 13.110.74.214 support@purestorage.com smtp07-ia4-sp2.mta.salesforce.com
result: ('pass', 250, 'sender SPF authorized') include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email
('pass', 250, 'sender SPF authorized')
- result from SPF authorization (OK - SPF pass)include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email
- spf record from DNS TXT query responsible for SPF pass status
Change ip address from sender email server:
~] python3 /usr/lib/python3/dist-packages/spf.py 15.110.74.214 support@purestorage.com smtp07-ia4-sp2.mta.salesforce.com
result: ('softfail', 250, 'domain owner discourages use of this host') ~all
('softfail', 250, 'domain owner discourages use of this host')
- spf check return a softfail SPF status~all
- last item from TXT dns record for SPF record purestorage.com domain
Further reading: SPF macros explained
Another way is use a spf module directly:
~] python3
Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import spf
>>> spf.check(i='13.110.74.214', s='support@purestorage.com', h='smtp07-ia4-sp2.mta.salesforce.com')
('pass', 250, 'sender SPF authorized')