Get Zimbra users into nospam (postfix)

So, lets say you have a nospam server, and that server forwards mail to a zimbra server. What you would like to do is have the user list from the zimbra server appear in a list on the postfix server, and only accept mail for the users that are contained in that list. In this way, you reduce the amount of mail hitting the zimbra server. Well, I have a crude setup doing  just that, and this is how I did it.

This method can also be setup to read from a Micro$oft exchange server, but you need a few tools on the nospam server to do it. I will perhaps show how to do that in another post, as I have actually done that also.

The main reason for this operation is stopping mail before it gets to the zimbra server. For example, mail for probably does not correlate to a real user, but spam people send out mail for bogus users all the time. If nospam does not have a current list of users on your system, it will blindly forward that mail. If that mail passes by the spam filter (which happens from time to time), then your zimbra server is going to waste bandwidth (in absolute and compute terms) looking at this mail and finally rejecting it as the user is not known in the domain.

There are two distinct parts to this setup. First, there is a script on the zimbra box that will read the account names, and strip out the duplicates and junk. Then this file will be sent to nospam. Nospam will format it for postfix and then make the db with postmap and reload postfix.

On the zimbra server, you need a bash script, lets call it /usr/local/bin/ and in it place the following:


/opt/zimbra/bin/zmprov  sa  -v ‘(|(objectClass=zimbraDistributionList)(objectClass=zimbraAccount))’ | egrep ‘^(# name |# distributionList|zimbraMailAlias)’ | cat -s  | sed ‘s/^zimbraMailAlias:/     /; s/^# name /\nMailbox: /; s/^cn: /Name: /; s/^#distributionList /\nMailingList: /’ |sed ‘s/memberCount.*//’ |sed ‘s/Mailbox://’ |sed ‘s/MailingList://’ |grep -v archive |sort |sed ‘/^$/d’ |sed ‘s/^[ \t]*//’ |grep -v distributionList |grep -v ham |grep -v restored |grep -v backup |grep -v spam |grep -v lf1 > /tmp/aliases.txt


Save and exit that file, then make it executable (like chmod +x /usr/local/bin/ for example, if you do not like numbers) You also need to make it owned by zimbra, so do


chown zimbra:zimbra /usr/local/bin/

Now, we also need to send that file to the nospam server. Look up how to gen RSA keys and share them under ssh and setup the ssh keys between the zimbra server and the nospam server. Done? Great, lets make a small file to send the aliases, lets call it /usr/local/bin/ and in that file put:


scp /tmp/aliases.txt root@

We are assuming your nospam box is at, please change this to be your nospam internal IP address. Again, save and exit that file, then make it executable.

We need to add both of those to cron. I like separate cron files, so sue me and do something like this:


vi /etc/cron.d/get_aliases

and add:


0 08-18 * * 1-5 zimbra /usr/local/bin/


vi /etc/cron.d/send_aliases

and add:


5 08-18 * * 1-5 root /usr/local/bin/


Great, in 0mins to 31mins you should see the aliases.txt file appear in /root on nospam. Let us now go to the nospam server, where we need to add a script and a cron job. First, let us do the script:


vi /usr/local/bin/

and in that file add:


if [ -f /root/aliases.txt ]
/bin/sed ‘s/$/ OK/’ /root/aliases.txt  > /root/relay_temp
/usr/bin/sort /root/relay_temp |/usr/bin/uniq > /etc/postfix/relay_recipients
/usr/sbin/postmap /etc/postfix/relay_recipients
postfix reload

Save and exit that file. Also make it executable. Now:


vi /etc/cron.d/mkaliases

and add:



10 08-18  * * 1-5 root /usr/local/bin/


You will note that the first cronjob on the zimbra server goes off on the hour, from 8am until 6pm. You will note the second job, which sends the file goes off 5mins later, and finally the cronjob on nospam goes off 5mins after that job. Note further that there is very little error checking here, so you might want to check this a few times and check the files. One final thing to do is add this to postfix:


vi /etc/postfix/

and add:


relay_recipient_maps = hash:/etc/postfix/relay_recipients


In my I added that line before any checks or restrictions lines. You can restart postfix now or wait for your script to do it for you. That should be it. You can of course test this by sending a legit email to a bogus recipient at your domain while you tail the mail log.


This entry was posted in Servers. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *