Postfix itself works for handling mail receiving/sending only, besides that, we need other features like rate control, antispam etc. These additional features can be implemented by the third party jobs, such as services of policyd and milter.

Policyd is in light workload, it checks user's sending behavior, but doesn't check email content including body and header. While milter is mostly heavy job since it analyses email content using regex etc. In my regular postfix setup, I have used two policyd services, one is for SPF checking, another is for sending rate control.

The following URLs are their project addresses.



If you are using ubuntu 20+, then install them by apt,

 $ sudo apt install postfix-policyd-spf-python
$ sudo apt install policyd-rate-limit

After installation, the default configuration files are follows.


Please notice, you may want to change nothing in these two files. The default settings work just fine.

After installation, edit postfix's configuration file /etc/postfix/, put the sections below.

 policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
check_policy_service { unix:ratelimit/policy, default_action=DUNNO },
check_policy_service { unix:private/policyd-spf, default_action=DUNNO }

As you see, the first "check_policy_service" option defines the unix socket for connection to policyd-rate-limit, the second defines the unix socket for connection to postfix-policyd-spf-python.

And "policyd-rate-limit" is a regular system service, for which you can see the running status,

 # systemctl status policyd-rate-limit
● policyd-rate-limit.service - Postfix policyd rate limiter
Loaded: loaded (/lib/systemd/system/policyd-rate-limit.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2022-12-05 19:07:50 HKT; 41min ago
Main PID: 92180 (policyd-rate-li)
Tasks: 1 (limit: 1066)
Memory: 9.3M
CGroup: /system.slice/policyd-rate-limit.service
└─92180 /usr/bin/python3 /usr/bin/policyd-rate-limit

But "postfix-policyd-spf-python" is a script rather than a system service, it should be spawned up by Postfix itself. So put this option as the last line into /etc/postfix/

 policyd-spf  unix  -       n       n       -       0       spawn
user=policyd-spf argv=/usr/bin/policyd-spf

The last, let's restart related services,

 $ sudo systemctl restart policyd-rate-limit postfix

For SPF checks, you could telnet to SMTP port to send mail from a sender address which has the strictest SPF setup. For instance,

 $ telnet 25
Connected to
Escape character is '^]'.
220 ESMTP Postfix
helo localhost.locaodomain
mail from:<[email protected]>
250 2.1.0 Ok
rcpt to:<[email protected]>
550 5.7.23 <[email protected]>: Recipient address rejected: Message rejected due to: SPF fail - not authorized. Please see;[email protected];ip=xx.xx.xx.xx;r=<UNKNOWN>

This mail was rejected by systems since SPF failed.

For sending rate, you can send as many messages as possible from email clients such as Thunderbird. When it reaches the limit you can't send anymore. You will get the rejected message as,

 4.7.1 <[email protected]>: Recipient address rejected: Rate limit reach, retry later

When both processes are running, you will see the processes info as follows.

 # ps -efw|grep policyd|grep -v grep
policyd+ 92180 1 0 19:07 ? 00:00:00 /usr/bin/python3 /usr/bin/policyd-rate-limit
postfix 93859 92978 0 20:11 ? 00:00:00 spawn -z -n policyd-spf -t unix user=policyd-spf argv=/usr/bin/policyd-spf
policyd+ 93860 93859 1 20:11 ? 00:00:00 /usr/bin/python3 /usr/bin/policyd-spf

For now, all are working fine.