Test abd Debug SPF with command line

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')

Sources

SUBSCRIBE FOR NEW ARTICLES

@
comments powered by Disqus