SPF configuration

Add SPF records to DNS

In order that receiving servers can check your SPF record it must be publicly visible. This means publishing it to the DNS server for the chosen domain(s). Go to their domain zone pages and add a new TXT record. For example, to allow mail from all hosts listed in the MX records for the domain:

v=spf1 mx -all

To allow mail from a specific host:

v=spf1 a:mail.somedomain.tld -all

Exact format may vary per DNS provider. Check the documentation for the exact style required.


The Python SPF policy agent adds SPF policy-checking to Postfix. The SPF record for the sender’s domain for incoming mail will be checked and, if it exists, mail will be handled accordingly.



/etc/postfix-policyd-spf-python/policyd-spf.conf looks something like:

debugLevel = 1
defaultSeedOnly = 1

HELO_reject = SPF_Not_Pass
Mail_From_reject = Fail

PermError_reject = False
TempError_Defer = False

skip_addresses =,::ffff:,::1
  • debugLevel controls the amount of information logged by the policy server. The default, level 1, logs no debugging messages, just basic SPF results and errors generated through the policy server.

  • The policy server can operate in a test only mode. This allows you to see the potential impact of SPF checking in your mail logs without rejecting mail. Headers are prepended in messages, but message delivery is not affected. This mode is not enabled by default. To enable it, set TestOnly = 0. This option was previously named defaultSeedOnly. This is still accepted, but logs an error.

  • The default HELO check rejection policy is SPF_Not_Pass, meaning reject if the SPF result is Fail, Softfail, Neutral, PermError. Not fully RFC 4408 compliant but HELO/EHLO is known first in the SMTP dialogue and there is no reason to waste resources on Mail From checks if the HELO check will already reject the message.

Postfix integration


In /etc/postfix/master.cf append:

policyd-spf unix -       n       n       -       0       spawn user=nobody


To increase the Postfix policy agent timeout, which will prevent Postfix from aborting the agent if transactions run a bit slowly

policyd-spf_time_limit = 3600

And append check_policy_service unix:private/policyd-spf after reject_unauth_destination, for example:

smtpd_recipient_restrictions = reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination,reject_non_fqdn_sender,reject_unlisted_recipient,check_policy_service unix:private/policyd-spf

Restart postfix

# systemctl restart postfix


  • Check the operation of the policy agent by looking at raw headers on incoming email messages for the SPF results header.

  • The SPF policy agent also logs to /var/log/mail.log. In the mail.log file you’ll see messages like this from the policy agent

Configuration resources