Now the limit is your imagination, we have some nice ACLs that we can combine and make them work very nice. This tutorial will show some recipes, for more details look at AclList, there you can find a lot of information about the ACLs.

Basic example

acl foo sender foo@domain.com
acl bad_domain sender @spammer.com

action deny_spam REJECT Your domain is evil!
action nice_users OK

access foo nice_users
access bad_domain deny_spam

There is no big secret, when the sender is foo@domain.com, we accept the message, in case the domain of the sender is spammer.com, we reject it.

Protecting accounts

It is a common task to mail admins, to protect some accounts, like account bar@domain.com should not receive messages from users outside domain.com.

acl bar recipient bar@domain.com
acl domain sender @domain.com
action deny_intruder REJECT This email does not receive outside of domain.com
access bar !domain deny_intruder

This can be done with Postfix without problems, take a look at http://www.postfix.org/RESTRICTION_CLASS_README.html, the advantage of using apolicy is that you don't need do deal with the main.cf configuration file, creating restriction classes and more files, that is the point.

Message size limit by e-mail

We can create a nice control for message size limit:

acl foo recipient foo@domain.com
acl bar recipient bar@domain.com
acl 10mb size 10240000
acl 20mb size 20480000

action deny_max_10mb REJECT This user can not receive more than 10mb
action deny_max_20mb REJECT This user can not receive more than 20mb

access foo 10mb deny_max_10mb
access bar 20mb deny_max_20mb

Now if a message is sent to foo@domain.com and is bigger than 10 Mb, Postfix will reject, but if the message is for bar@domain.com, the message can have up to 20 Mb. Note that for this ACL work, you need at least Postfix 2.2 and the policy service be called from smtpd_end_of_data_restrictions, apolicy will test if the protocol state is END-OF-MESSAGE and in case it isn't, ACLs of type size will never match.

Multi-valued ACLs

When an ACCESS line is verified, all ACLs should return true, then the action specified will be returned to Postfix. An AND is done with all results. But it is possible that one ACL matches different types.

acl bar recipient bar@domain.com
acl bar sender bar@domain.com
action allow_bar OK
access bar allow_bar

This construction will test the recipient and sender inside the same ACL, but only one can match. It is done an OR, the first line that matches will return true. So, in this case, if actually the recipient is bar@domain.com, then the next part of the ACL will not be tested and the ACL bar will match. This feature can be used to create an ACL that matches various e-mails.

Redirecting messages

acl list recipient sales@domain.com
acl list recipient contact@domain.com
acl list recipient webmaster@domain.com
action destination_foo REDIRECT foo@domain.com 
access list destination_foo

If the recipient is sales@domain.com or contact@domain.com or webmaster@domain.com, it will be redirected to foo@domain.com.

Storing lists in files

Lets say you need to specify a huge number of senders, that would make the configuration too big, so lets separate the content.

acl list senders /etc/apolicy/senders.txt

Inside the file senders.txt there must be a value per line.

Verifying SPF

To verify SPF, you have to create a spf ACL, and make it available with the access statements.

acl restrict_spf spf

action deny_bad_spf REJECT Sender spoofing detected

access restrict_spf deny_bad_spf

The spf is special, because it doesn't need a value, instead, the ACL have parameters for configuration. Lets suppose you want a more restrictive configuration, where domains configured with softfail must be denied. It's possible to change the default behavior.

acl restrict_spf spf softfail=reject

action deny_bad_spf REJECT Sender spoofing detected

access restrict_spf deny_bad_spf

Now if a SPF check returns an softfail, instead of letting the message pass, the default behavior specified by the RFC, we can reject the message.

<!> If you have a server with high traffic, it's wise to use greylisting before checking SPF, because there is a huge amount of DNS servers that do not respond or are not configured properly. Querying DNS could be a big bottleneck.

You may have high traffic from domains that are known to do not publish SPF records, like Yahoo. So, you can skip the SPF verification in this case.

acl yahoo sender @yahoo.com
acl restrict_spf spf softfail=reject

action deny_bad_spf REJECT Sender spoofing detected

access !yahoo restrict_spf deny_bad_spf

<!> Notice that !yahoo appears before restrict_spf, so if the sender is from Yahoo, this ACL will return true, but we have ! there, so the value returned by the ACL is inverted, becoming a false. As soon an ACL returns false, the next ACLs will not be processed.

Controlling by day and time

Other nice ACLs that apolicy has is the day and time. With them, you can restrict or redirect the transport of a message based on the day of the week and the current time.

You have a support@domain.com address, and two people take care of this address in different shifts. With pure Postfix, support@domain.com can only be an alias to the e-mails of the workers, so one worker receives e-mails from the shift of the other, duplicating everything. Lets solve this.

acl support recipient support@domain.com
acl shift_one time 06:00-11:59
acl shift_two time 12:00-18:00

action to_worker_one REDIRECT worker1@domain.com
action to_worker_two REDIRECT worker2@domain.com

access support shift_one to_worker_one
access support shift_two to_worker_two

Sweet! Now they will only receive e-mails that arrive on their shift.

Lets say your company has some policy that requests a department to do not receive e-mails on weekends.

acl requests recipient requests@domain.com
acl weekends day as
action no_requests REJECT Sorry, no request can be accepted on weekends.

access requests weekends no_requests

Very nice. With the ACL day we specified that on Saturday and Sunday the requests@domain.com won't accept e-mails. The value as for the ACL weekends is a for Saturday and s for Sunday.


Greylisting in apolicy is not a default behavior like in other Policy Daemons, it must be combined with ACLs, Actions and Access statements.

acl grey_all greylisting time=5,lifetime=15,backend=memory

action to_greyslist DEFER_IF_PERMIT Greylisting, try in 5 minutes...

access grey_all to_greyslist

Just like the spf, the greylisting ACL does not have a value, instead is uses comma separated list of variables that configures the behavior os the ACL.

The basic values are:

For more details look at AclList, there you can find a lot of information about the ACLs.