ACL list

Regular Expression ACLs

Some ACLs just try to match simple text, so the have the exactly same behavior.

{i} sasl_username, sasl_method and sasl_sender require Postfix 2.2 or latter

This ACLs supports regular expressions, so you can use the full power of the Python Regular Expression library.

Some examples:

acl bad_sender sender
acl bad_domain sender

acl trap recipient trap@
acl other_trap recipient (sales|contact)

acl dyn_host client_name (.dynamic.|.dhcp.)


This ACL supports IPv4 and IPv6.

acl machine client_address
acl net1 client_address
acl net2 client_address
acl net3 client_address


This ACL can be evaluated at any time.

m - Monday
t - Tuesday
w - Wednesday
h - Thursday
f - Friday
a - Saturday
s - Sunday

acl weekend day sm


This ACL can be evaluated at any time.

acl work time 08:00-17:00


This ACL will query the RBL host supplied with the client IP address and it can be evaluated at any time.

acl spamhaus rbl


{i} Requires Postfix 2.2 or latter

The value of this ACL is specified in bytes and can be evaluated at smtpd_sender_restrictions. Note that it is possible to know the size of a message if the client is using the SIZE extension of the ESMTP protocol. Although, use this ACL as the last verification on your policy, after RBL checks, greylisting, helo and sender verifications, etc, because it is much more probable that a legit server uses ESMTP and the SIZE extension. Refer to this thread on the postfix-users mailing list about this topic, very good information: If you need 100% accuracy when controlling message sizes, then call the policy daemon from smtpd_end_of_data_restrictions.

acl 10mb size 10240000
acl 20mb size 20480000


For more information about greylisting, check the links below:

The value of the greylisting ACL is a list of parameters separated by commas.

This parameters are:

acl grey_1 greylisting

acl grey_2 greylisting time=2,lifetime=14400,backend=disk,root=/var/cache/apolicy/

<!> The root parameter must point to a directory owned by the user nobody, or the user specified by the parameter user in the main.conf configuration file.

Considering performance, both methods are good for a medium sized server, around 100k requests per day. We don't have any benchmark to measure how far they scale yet.

Keeping 100k entries in memory, the process will use around 15 to 18 megabytes, not that much considering how cheap 1 Gb of RAM is today. If you need higher persistence, consider using the disk backend, it can create 30k entries in a few seconds.

memcached backend

{i} Available in apolicy 0.73 and latter

memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load. Please read more about memcached on

One of the key advantages of using memcached is that you can share the greylisting database with many apolicy servers and keep memory usage under control, avoiding maintaining a relational database and reducing overhead.

To use a memcached daemon, configure a greylisting ACL like this:

acl grey greylisting time=2,lifetime=1440,host=,backend=memcached

Note that the host parameters is only used with the memcached backend and the format is IP:PORT. The default value is In case you use a memcached daemon on another server, specify the IP and port like this:

When apolicy starts it tries to store a test object on the memcached daemon, if it fails apolicy will exit immediately and log the error. While apolicy is running, if it is not possible to store objects in the memcached daemon, the ACL will return false and an error will be logged.

disk backend

The disk backend uses just files and directories to store the greylisting triplets (sender, recipient, client IP). Inside the root directory there is a structure like this:

[root@friends apolicy]# pwd
[root@friends apolicy]# ls -lR
total 0
-rw------- 1 nobody nobody 0 Apr 24 11:13 1097c1ccfeb492ce1a3dfe9f3d503d70
-rw------- 1 nobody nobody 0 Apr 26 13:52 93322022115a05a66f4688f3a815fe79

total 0
-rw------- 1 nobody nobody 0 May  6 02:28 74408c779e34b46e929117a410533d18
-rw------- 1 nobody nobody 0 May  5 17:49 d93dbf9d3fbe38a19d1505a9aadeac92

total 0
-rw------- 1 nobody nobody 0 Apr 21 19:23 53efc51cc0d0414bd0b343724804f819
-rw------- 1 nobody nobody 0 Apr 24 05:22 6278c0c068d06b659a8316f5657d40ee

Basically we get the first two octets of the client IP address and create two directories. So if the client IP is, inside the root directory given to the greylisting ACL, for example the default /var/cache/apolicy, this path will be created: /var/cache/apolicy/138/243. Then, inside this directory an empty file is created using as name a MD5 hash of the triplet like md5(sender + recipient + client_ip). Using the file creation time and the current time the difference is calculated and we have a working greylisting.

The disk backend uses very low disk space, read/write performance is very good, avoids the overhead of a relational database and is very simple to setup.

An example from a production server:

[root@friends apolicy]# pwd

[root@friends apolicy]# find . -type f | wc -l

[root@friends apolicy]# du . -hc --max-depth=1 | grep total
80M     total

To store more than 700.000 entries, just 80 Megabytes are needed.

There is no need to clean and delete old files. If the lifetime for an authenticated triplet is set to 5 days and a MD5 hash of a triplet is older then 5 days, the modified time is updated, instead of cleaning up the expired triplets and creating then again. We call this lazy expiration.


If the sender is authorized, neutral, or softfailed by and SPF record this ACL returns False.

If the sender is not authorized by an SPF record this ACL returns True.

For more information on how and why use SPF, check the links below:

The value of the spf ACL is a list of parameters separated by commas.

The parameters corresponds to the SPF qualifiers, and you can customize what to do with witch one. The SPF specification states that a neutral or softfail qualifier should not result a rejection, but lets say you want that every domain that declares itself neutral or softfail, even if the message is not authorized, must be rejected in case of a not authorized message.

Possible parameters, all of them must be reject or pass:

acl restrict_spf spf softfail=reject,neutral=reject

Or to use the default behavior:

acl normal_spf spf


{i} Available in apolicy 0.72 and latter

This ACL compares the current protocol used by the client, either SMTP, ESMTP and LMTP. Any value different from that will result in an error when apolicy starts.

acl smtp protocol_name SMTP
acl esmtp protocol_name esmtp

acl smtp protocol_name FOO # invalid value


{i} Available in apolicy 0.72 and latter

When this ACL is processed it generates a log event with the requested parameters.

acl log_sender_helo log content=sender:helo
acl log_rbl log prefix=RBL,content=client_address:helo:sender

The first line logs the sender and the HELO message used during the SMTP transaction.

The second line logs the client IP, the HELO message and the sender, prefixed by the string RBL. The prefix parameter can help identify the log event in the log files.

Possible parameters:


{i} Available in apolicy 0.73 and latter

This ACL will query the to geolocate client IP addresses.

acl italy country IT 
acl sud_america country PE,PY,UY,BR
acl china country CN http_proxy=http://user:password@,api_url=,timeout=2

<!> The country must be match with the value returned from Generally it's ISO3166. But there are specific cases where obsolete or invalid codes are used, largely because the source of the information (the various NICs or the netblock owner) don't validate or update it. You can find the complete list of country code at

Possible Parameters:


{i} Available in apolicy 0.73 and latter. Requires Postfix 2.5 or latter

This ACL detect server overload. See the STRESS_README document for further information.

acl overload stress

AclList (last edited 2014-08-27 10:09:05 by vic)