Mac OS X Server offers all the power and flexibility you need to set up a sophisticated mail server with anti-spam and anti-virus technology. Yet, the GUI of Apple’s Server Admin is limited to basic mail server configuration.

As I looked for an overall mail solution based on Mac OS X Server I found two very helpful articles on the net that describe how to integrate virus filtering (‘Sanitizing Mail on Panther Server’ by Jason Deraleau) and how to implement the SpamAssassin (‘Fighting Spam on Mac OS X Server’).

Yet, there was no instruction how to put these things together, furthermore I found that there was more information needed to set up the whole thing than the two indeed really good articles offer. To help other admins who want to set up a similar system I decided to write this short manual that you are reading right now. If you find anything outdated or incomplete, please take a minute and drop me a note using my feedback formular.

So let’s see what this is all about:

Table of contents

Preface

Applications and tools

Intended audience

Copyright

Non-warranty

Overview

Basic setup

Using Procmail to add multiple filters

Step-by-step configuration

Activating Procmail

Activating Anomy’s Sanitizer and Virex

Activating SpamAssassin and Razor

Some thoughts about fine tuning

Associated topics

Email addresses firstname.lastname@domain.com

Sending emails to a group

Editing users’ mailbox quotas

Rebuliding a broken Cyrus database

Auxpropfunc -1

Dupelim: eliminated duplicate message to user.testuser

Receiving cron messages as email

Preface

Applications and tools

The applications and tools discussed in this short manual are:

  • postfix, as included with Mac OS X Server 10.3.4
  • procmail, as included with Mac OS X Server 10.3.4
  • Anomy Sanitizer version 1.68
  • Virex, included with .Mac accounts, version 7.2.1
  • Sophos Anti-Virus
  • SpamAssassin, version 2.63
  • Razor, version 2.61 (agents), 2.03 (agents sdk)

As you already might have seen, most of these tools are Open Source and free of charge, except from the command-line virus scanners Virex and Sophos Anti-Virus, which can be used alternatively.

 

Intended audience

The tools described in this document are quite powerful and you can configure them to adapt to any individual needs. Yet, most of the configuration work has to be done on the command-line, so that you should feel comfortable with using the Terminal.

If somebody else set up your mail server configuration according to this instruction (e.g. me :-D ), and you just need some help to do the daily administrative maintenance stuff afterwards, this file is meant for you, too.

If you want to set up your mail server from scratch without ever touching the Terminal, then have a look at some commercial mail server packages, which can be installed on Mac OS X Server: http://www.macworld.com/2004/03/reviews/emailservers. Especially the Kerio mail server is worth a closer look.

This article assumes, that your basic mail server setup is already up and running.

 

Copyright

This documentation is distributed under GNU LPGL. You may copy, adapt, and redistribute this document for commercial or non-commercial use. When copying, adapting, or redistributing this document in keeping with the guidelines above, you are required to provide proper attribution to André Aulich and andre-aulich.de. If you reproduce or distribute the document without making any substantive modifications to its content, please use the following attribution line:

Copyright 2004 André Aulich, andre-aulich.de, all rights reserved

 

Non-warranty

You are free to use this guide for setting up your Mac OS X Server, yet, there is no warranty, that the information provided in this document contains no mistakes or is up-to-date. If you encounter any problems, particularly any data losses, the author disclaims any responsibility.

 

Overview

Before we start to configure our new filters let’s first get an idea of what we are going to do, now.

 

Basic setup

When you use the basic mail configuration provided with Mac OS X Server, your incoming emails take the following route through your server:

 

Figure 1: Basic mail workflow in a standard Mac OS X Server configuration; Postfix sends incoming emails to Cyrus which then delivers mails to the recipients.

The two crucial files in this setup are /etc/postfix/main.cf and /etc/postfix/master.cf, which tell Postfix where to send incoming mails to. The basic setting is to send incoming mails to Cyrus, which then delivers your emails to server-based user mailboxes.

When a user connects his client machine to the server, Cyrus uses POP or IMAP as a protocol to transfer emails to the user’s computer.

 

Using Procmail to add multiple filters

What we are going to do, now, is to tell Postfix NOT to pipe emails to Cyrus but to Procmail, which is already preinstalled with Mac OS X Server and allows to add multiple instances for virus scanning, spam filtering, you name it.

After the mails passed through the instances that you configure in procmail, procmail forwards your emails to Cyrus, which then delivers the mails to the users’ mailboxes, like in the basic setup.

The general structure of your mail flow will then look something like this:

Figure 2: mail workflow using procmail

As soon as procmail is in the game, you can begin adding further instances. In this example we are going to set up Anomy’s Sanitizer, which strips unwanted mail attachments and sends suspicious files through a virus scanner (optionally Virex or Sophos Anti-Virus). The sanitizer adds its own headers to your mails to inform the recipient how it changed the email.

If your mails make it through these barriers, they will then be scanned by the SpamAssassin (SA), which gives further security by comparing your mails to an online Razor database. The SA also adds special headers to your emails to inform the recipient about what it found in the mail.

Depending on the spam rating assigned by the SA, procmail can invoke further actions like deleting mails with a very high spam rating.

After running through all instances defined in the file /etc/procmailrc the email will then be send to Cyrus which delivers to the final recipient, in the same way like in the basic configuration with Postfix and Cyrus only.

The final mail workflow might look something like this:

 

Figure 3: final mail workflow using procmail to invoke multiple filter instances

As you see, the final setup looks quite complicated. Yet, despite your emails’ long way through multiple filtering instances, a single CPU Power Mac G5 can still handle a couple of thousand emails per hour.

Step-by-step configuration

Activating Procmail

Now that we know what we are going to do, let’s get some work done. In the first step we gotta tell Postfix to pipe all emails through Procmail.

To do so open the Terminal and type the following:

sudo -s

Enter your password when asked. Now you got a root shell.

pico /etc/postfix/main.cf

opens one of Postfix’s config files in pico. Use the arrow keys or ctrl-V to navigate to the line in which you read

#mailbox_command = /some/where/procmail -a "$EXTENSION"

Change it to make it look like this:

mailbox_command = /usr/bin/procmail -t -a "$EXTENSION"

Now find the line

mailbox_transport = cyrus

and change it to

mailbox_transport = procmail

Save your changes by pressing ctrl-O and hit Enter to confirm.

Because Apple’s Server Admin will try to overwrite any manual changes whenever you use it to change some settings, we need to lock the file. Just type

chflags uchg /etc/postfix/main.cf

If you need to change some settings later on, first unlock the file by typing

chflags nouchg /etc/postfix/main.cf

Be aware that repairing Mac OS X’s permissions using disk utility unlocks this file, too. This means that after repairing permissions you have to lock this file again.

Okay. Now we have to add the Procmail transport to the file /etc/postfix/master.cf:

pico /etc/postfix/master.cf

Add

procmail unix - n n - - pipe
flags=R user=cyrus argv=/usr/bin/procmail -t -m USER=${user} EXTENSION=${extension} /etc/procmailrc

to the end of the file, but take care that lines two and three actually have to be written in one line. Then save your changes, and lock the file by typing

chflags uchg /etc/postfix/master.cf

Now you have to restart Postfix, because then it will read the new configuration it is going to use:

postfix reload

This will reload the configuration files. As you will see later, Server Admin might not start Postfix if you restart your mail server later on. To start Postfix manually type

postfix start

Now Postfix sends all incoming mails through procmail. So far so good. Let’s configure Procmail, now. Create the file /etc/procmailrc

touch /etc/procmailrc

open it in pico

pico /etc/procmailrc

and paste the follwing code into it:

#
# /etc/procmailrc – System-wide procmail recipes
#
LOGFILE=/var/log/procmail.log # this can be deleted after testing
VERBOSE=YES
HOME=/Users/$USER
DROPPRIVS=YES

# Default: Deliver mail that makes it to this point to the user's
# Cyrus INBOX
:0w
| /usr/bin/cyrus/bin/deliver -e -a $USER -m user/$USER

Save the file, now procmail is active.

In the file /etc/procmailrc now is defined, that procmail maintains a log file at /var/log/procmail.log, that you can view using the program /applications/console. For the first testing phase we turned on verbose mode to get detailed information on anything procmail does. Very useful if you try to analyse why your mails disappear somewhere in the filtering process. If after some time everything is running fine, it’s better to turn off verbose mode as the log files easily grow to a couple of hundred MBs.

The last two lines of the file mean that all the mails that made it to the last instance will be delivered to the user. That’s it!

Activating Anomy’s Sanitizer and Virex

First, visit the anomy website to download the latest version of the Sanitizer, which at the time of this writing is 1.68.

Unpack the downloaded file and move the resulting folder from your desktop into the /opt directory:

mv ~/Desktop/anomy /opt/

Now the sanitizer is installed you can delete the anomy package on your desktop. Now go to the fine article in O’Reilly’s MacDevCenter and follow the instructions to create the folder /var/quarantine/ and the file /opt/anomy/sanitizer.cfg. I changed the sanitizer configuration file to make it look like this:

#
# /opt/anomy/sanitizer.cfg - Basic configuration for Anomy Sanitizer
# with Virex
#
# Active features.
feat_trust_pgp = 1 # trust signed or encrypted messages
feat_boundaries = 0
feat_files = 1
feat_forwards = 1
feat_html = 1
feat_lengths = 1
feat_log_inline = 1
feat_log_stderr = 0
feat_scripts = 1
feat_trust_pgp = 1
feat_uuencoded = 1
feat_verbose = 1
file_list_rules = 3

#
# Note: This directory must exist and be writable by
# the user running the sanitizer.
#
file_name_tpl = /var/quarantine/att-$F-$T.$$

# Files we absolutely don't want (mostly executables).
#
file_list_1_scanner = 0
file_list_1_policy = save
file_list_1 = (?i)(winmail\.dat
file_list_1 += |\.(vb[es]|c(om|hm)|bat|pif|s(ys|cr))
file_list_1 += (\.g?z|\.bz\d?)*)$

# Pure data, don't mangle this stuff (much).
#
file_list_2_scanner = 0
file_list_2_policy = accept
file_list_2 = (?i)\.(gif|jpe?g|pn[mg]|x[pb]m|dvi|e?ps|p(df|cx)|bmp
file_list_2 += |mp[32]|wav|au|ram?
file_list_2 += |avi|mov|mpe?g
file_list_2 += |t(xt|ex)|csv|l(og|yx)|sql|jtmpl
file_list_2 += |[ch](pp|\+\+)?|s|inc|asm|pa(tch|s)|java|php\d?
file_list_2 += |[ja]sp
file_list_2 += |can|pos|ux|reg|kbf|xal|\d+)(\.g?z|\.bz\d?)*$

# Archives and scriptable stuff - virus scan these.
# NOTE: There must be THREE groups of exit codes and FOUR policies,
# - the first three match the code groups, the fourth is default.
#
file_list_3_scanner = 0,1:2:3,4:/opt/anomy/bin/virex.sh %FILENAME
file_list_3_policy = accept:accept:save:accept
file_list_3 = (?i)\.(xls|d(at|oc)|p(pt|l)|rtf|[sp]?html?
file_list_3 += |class|upd|wp\d?|m?db
file_list_3 += |z(ip|oo)|ar[cj]|lha|[tr]ar|rpm|deb|slp|tgz
file_list_3 += )(\.g?z|\.bz\d?)*$


# Default policy: accept.
#
file_default_policy = accept

Basically this file accepts more incoming mails than the original configuration mentioned in the O’Reilly article does. The structure of this config file is quite simple. There are four blocks with rules: file_list_1, file_list_2, file_list_3, and file_default_policy. Each rule defines if the mails are scanned by the Sanitizer itself (file_list_x_scanner = 0) or by an external program (see file_list_3_scanner).

Furthermore you find the activity triggered if a file matches the rule: file_list_x_policy = accept, save, drop, or defang. Accept means, that the file passes a filter without being changed at all, save means, that the attachment will be saved in the folder /var/quarantine and that the recipient will be informed to get in touch with the administrator. Drop means that the attachment will be deleted, defang means, the attachment will be delivered to its recipient, yet, the filename and MIME type will be changed to prevent automatic opening of the file. If your users are all geeks you might use the config file mentioned in O’Reilly’s article, if your users are quite helpless when it comes to computers, better you use this more open rule, or you might permanently get unnecessary requests.

The configuration in this file means the following: If there is any attachment with a file type mentioned in group one, the Sanitizer moves the attachment to the directory /var/quarantine and informs the recipient that it did so. I allow *.exe files to be delivered to the user, because some Windows recipients seem to need this. If you want to disallow this, add the *.exe file type to the group (see example file in the O’Reilly article).

If Virex finds a Virus in the email that it can not delete, the Sanitizer moves the attachment to /var/quarantine and informs the recipient about that. In any other case the Sanitizer delivers the mail back to procmail.

Now create the file /opt/anomy/bin/virex.sh as mentioned in the O’Reilly article.

After this step, we gotta tell Procmail to pipe all incoming messages through the Sanitzer. Open the Procmail config file

pico /etc/procmailrc

and edit the file to make it look like this:

#
# /etc/procmailrc - System-wide procmail recipes
#
LOGFILE=/var/log/procmail.log # this can be deleted after testing
VERBOSE=YES
HOME=/Users/$USER
DROPPRIVS=YES
# Run sanitizer on locally delivered messages
ANOMY=/opt/anomy/
:0fiw
|/opt/anomy/bin/sanitizer.pl /opt/anomy/sanitizer.cfg
# Default: Deliver mail that makes it to this point to the user's
# Cyrus INBOX
:0w
| /usr/bin/cyrus/bin/deliver -e -a $USER -m user/$USER

If you read the procmail man pages you will learn about file locking. In many example scripts you will find that people lock their files when sending them through Sanitizer or the SpamAssassin. As far as I have learned, you don’t need to lock anything that is piped to another program as the file is not available to Procmail as long as it is processed by another tool. So file locking won’t bring any advantage.

Reload Postfix, now:

postfix reload

and your system should be up and running, again.

Send yourself some emails to check if everything works just fine. Open the Console to watch the log files /var/log/procmail.log , system.log, and /var/log/mail.log.

Activating SpamAssassin and Razor

Go to Apple’s Developer page to read the basic article on installing SpamAssassin. After installing the SpamAssassin and downloading the razor-agents and razor-agents-sdk, DO NOT APPLY THE APACHE PATCH TO THE RAZOR FILES, as the recent razor versions get corrupted if you try to install the patch. Razor in its latest versions is already prepared to work fine with SpamAssassin.

Now build and install Razor as described on the Apple page.

To set up the SpamAssassin now open the file /etc/mail/spamassassin/local.cf by typing

pico /etc/mail/spamassassin/local.cf

and edit the file to look like this:

rewrite_subject 1
# change subject lines of spam
always_add_headers 1
# add SpamAssassin headers to both spam and nonspam
use_bayes 1
# enable the statistical filter
auto_learn 1
# allow the statistical filter to learn as it goes
rbl_timeout 4
razor_timeout 4
# set short timeouts for remote database checks
required_hits 5.0
# hits needed to qualify mail as spam

Compared to the original file mentioned on the Apple page, this configuration makes the SpamAssassin adding the line *****SPAM***** to the subject, if the spam level of your mail is five points or more.

Now proceed training the SA with ham and spam (both optional) and edit your watchdog config file to automatically run the SpamAssassin.

After testing if the SA works fine, you gotta tell procmail to send all incoming emails through it.

Because it takes quite some CPU power to check if a mail is spam, it is recommended to place the SA after the Sanitizer, which might already filter out attachments that don't have to be scanned by the SA again.

Open the file /etc/procmailrc by typing

pico /etc/procmailrc

and make it look like this:

#
# /etc/procmailrc - System-wide procmail recipes
#

LOGFILE=/var/log/procmail.log # this can be deleted after testing
VERBOSE=YES
HOME=/Users/$USER
DROPPRIVS=YES
# Run sanitizer on locally delivered messages
ANOMY=/opt/anomy/
:0fiw
|/opt/anomy/bin/sanitizer.pl /opt/anomy/sanitizer.cfg
:0fiw
* < 256000
| spamc
# call spamassassin
# Default: Deliver mail that makes it to this point to the user's
# Cyrus INBOX
:0w
| /usr/bin/cyrus/bin/deliver -e -a $USER -m user/$USER

Now Procmail first sends incoming mails through the Sanitizer, after that it pipes them through to the SpamAssassin. If the mail makes it through these instances, it delivers them to the user’s inbox.

Same as with Anomy, you don’t need file locking as piping mails to another program avoids duplicate processing anyway. Compared to the suggested config file on the Apple page I added the line

* < 256000

to the recipe that invokes the SpamAssassin. This line says that Procmail should ONLY send emails through SpamAssassin, if the file is smaller than 256 KB, because spammers can usually not afford to send huge files (some people won't read huge spam mails due to download time using slow connections, and zombie machines were not able to send as many emails because of limited bandwidth). If you receive a couple of thousand emails per hour this restriction can save you quite some CPU power.

Now reload postfix:

postfix reload

and check if everythings works fine. That’s basically it! The Sanitizer, Virex, Razor, Procmail, and SpamAssassin are now up and running.

Some thoughts about fine tuning

The configuration described in this short documentation is just an example that has to be edited to better match your needs.

Let’s have a look again at the overall structure of our new server:

There are quite some configuration files that allow you to change and to improve your setup.

The first important file is /etc/postfix/main.cf. If you ever need to switch off the Sanitizer, Procmail, and the SpamAssassin to prevent any filtering, first unlock the file

chflags nouchg /etc/postfix/main.cf

open it

pico /etc/postfix/main.cf

and change the line

mailbox_command = /usr/bin/procmail -t -a "$EXTENSION"

to

# mailbox_command = /usr/bin/procmail -t -a "$EXTENSION"

and the line

mailbox_transport = procmail

to

mailbox_transport = cyrus

Now lock the file again

chflags uchg /etc/postfix/main.cf

Be aware that all commands have to be entered as root. To get a root shell type

sudo -s

and enter your password if asked.

After editing this file save it by hitting ctrl-O and reload postfix

postfix reload

Now your mail server uses its basic configuration you set up before you implemented the things described in this article.

The second important configuration file in the chain is the first one that allows you to adjust your filters. It’s /etc/procmailrc. You can find several recipes on the Internet to send mails with a high spam rating to /dev/null/ (meaning you delete them) or to deliver them to a spedific spam mailbox. Just ask your search engine of choice to look for ‘procmail recipe’, that will deliver quite some good stuff.

The next file is /opt/anomy/sanitizer.cfg, which defines how to deal with different types of attachments. The config file we use here already explains how to use the config file, yet, I recommend not to define too strict rules. Usually for users it’s more important not to lose imortant emails they need than to make 100 percent sure that they don’t get spam. That’s why I recommend ONLY to filter viruses, some file types almost nobody really wants in the mailbox, and probably spam with such a high rating, that it’s unlikely anybody wants it.

Yet, in the configuration described here, the SpamAssassin only adds special headers and marks spam mail with a rating of 5.0 or higher as ****SPAM****, which is added to the subject line (see /etc/mail/spamassassin/local.cfg). Like this your users can be sure to receive everything which is not absolutely surely containing a virus. Like this it’s easy to have a local rule on your users’ client machines that moves mails marked as ****SPAM**** to a special junk mail box. Then it’s up to your users to check if their mails get sorted into the right mailbox. Saves you as an administrator quite some time.

Procmail allows to add user specific .procmailrc files that contain individual policies. Using them, your users can set automatic replies if they are on holidays, and define their own rules how to deal with incoming mails. Usually you don’t want your users to take care for this as they might easily create mail loops that break down your server. Yet, you as an administrator can use these files to create auto replies. You find the example scripts if you enter the Terminal and type

man procmailex

Another point is the possibility to add personal SpamAssassin configuration files. As an email that one user considers to be spam can easily be a wanted email for another user (maybe one of your employees writes an article about spamming, viagra, etc.) it comes quite handy to define spam policies on an individual basis. Yet, if the user can do something wrong, you can be sure that it will happen. (“Oooops, I moved all my emails into the IMAP folder ‘Spam’ two weeks ago. And now I don’t receive emails anymore. Why is that?”)

That’s why I prefer to just use the SpamAssassin for marking possible spam mail. Then nothing gets lost and the user can still access emails that otherwise would be lost. If you use the setup described here, you don’t really need individual rules on the server-side, as the server is just filtering proved viruses and highlights possible spam to easily filter it out on the client-side.

Associated topics

Email addresses firstname.lastname@domain.com

In many companies email addresses look like this: firstname.lastname@domain.com. Mac OS X Server doesn’t support using firstname.lastname as a shortname to receive emails (okay, you CAN enter this as a second short name, but you will run into problems when connecting to the server later on).

So you need to create an alias in the form of firstname.lastname that points to a user’s short name. The procedure is already described in Apple’s server docs, yet, I wanted to put it here, too, as it is part of a standard installation like this one.

Open the file /etc/aliases

pico /etc/aliases

Add your aliases

# Put your local aliases here.
andre.aulich: aaulich

Save the file and type the following:

postalias /etc/aliases
newaliases
postfix reload

to make your changes become active. Be sure that the short name your alias is pointing at, already exists in your BerkeleyDB or your NetInfoDB.

Sending emails to a group

If you want to set up an email address in the form of group@domain.com that sends emails to multiple users, open the file /etc/aliases again

pico /etc/aliases

Add your aliases

# Put your local aliases here.

group: user1, user2, user3

Save the file and type the following:

postalias /etc/aliases
newaliases
postfix reload

to make your changes become active. Be sure that the short names your alias is pointing at, already exist in your BerkeleyDB or your NetInfoDB.

Editing users’ mailbox quotas

If your users store all their messages saved in years on your IMAP server, they might get a message that their user quota is exceeded, even while you increased their storage space using Workgroup Manager.

This seems to be a bug in Apple’s Workgroup Manager. What you have to do, now, is to change the user’s quota manually: open the Terminal, log in as root

sudo –s
cd /var/imap/quota/

then cd to the initial letter of the user name in question. Now type

pico user.username

(where ‘username’ has to be replaced with the username whose quota you are going to change) and edit the last number to fit the maximum size of the user’s mailbox (in KB). Save the file. It might be necessary to restart the mail service using Server Admin.

Rebuilding a broken Cyrus database

If your server crashes it can happen that your Cyrus database gets corrupt. To recover the database, an excellent description can be found at http://david.codebase.ca/index.cgi/os%20x/cyrus.writeback.

Auxpropfunc -1

If you read your system.log you will find an error message saying

Auxpropfunc -1

I haven’t found any explanation what this actually means, yet, as you can read in some forums, it seems to be harmless and can easily be ignored. (I know, that sounds bitter, but what can we do).

Dupelim: eliminated duplicate message to user.testuser

If you find messages like the one above in your system.log, you might have emails to mailings lists or group email adresses arriving at your server (or even spam). Your mail server automatically detects duplicates and prevents multiple delivery. This message is actually not an error message but a hint that your server is running properly. (See here).

Receiving cron messages as email

Cron regularly backs up your local NetInfo database at night, rotates your log files and does a lot of other maintenance stuff, too. To make sure that everything works fine, it’s quite helpful to check the log files from time to time. Yet, cron also informs you if anything goes wrong. In case of problems it automatically sends emails to root. Yet, you might not use root@yourdomain.com as your email address. What you have to do, now, to automatically receive emails in case of problems, is to forward root messages to your mailbox.

To do so open the file /etc/aliases

pico /etc/aliases

and edit the file

# Person who should get root's mail. Don't receive mail as root!
root: aaulich aaulich@mac.com

As you can see, you can use a local mail address (aaulich in this case) as well as an external email address.

Save the file and type the following:

postalias /etc/aliases
newaliases
postfix reload

to make your changes become active. Be sure that the short name your alias is pointing at, already exists in your BerkeleyDB or your NetInfoDB

Posted on by André Aulich. This entry was posted in Mac OS X Server.

Comments are closed.