Ivar @ eRay, Manc, 17/1/2K5

How to set up a mail server on a GNU / Linux system.

Step by step guide, to install Postfix on a Mandrake server.

Postfix + MySQL + Courier + Pop-before-SMTP + Amavisd-new + SpamAssassin + ClamAV


This an easy step by step guide for computer literates, but not quite gurus. Initial steps will be to get a server up, before (over) extending it. And then starting to tighten it down for security and convenience purposes.

You should follow each step, to get an understanding so that you could tweak it to your needs.

All software used are Open Source and free (as in beer). Most are GPLed.

Feel free to link to this from any related websites. Please reference back any work based on this Howto.

Old Mandrake 9.x Guide

Click here for the new Ubuntu based howto, which has replaced this guide.

electric ray group:


Written by Ivar Abrahamsen of electric ray. Initial draft of this Howto started on the 22nd Februay 2004. Last modification was on 17th January 2005. Ivar is norwegian software engineer based in England.

Comments to me are welcome. Including bug reports, spelling mistakes, tweaks, questions, job offers or just plain comments.

If you find this guide usefull, then any donatation of a few quid (or more) will be much appreciated.


  1. Intro
  2. Author
  3. Contents
  1. Software
  2. Building
  3. Basic Server
  4. Advanced Server
  5. Tighter
  6. WebMail
  7. Send Mail
  8. Content Checks
  9. Further Extensions
  1. Quick Setup
  2. Software Links
  3. References
  4. Pre-Requisites
  6. Mail Clients
  7. Automating Proxy Interfaces
  8. Startup Scripts
  9. Mail Backup
  10. Sources
Go to top.

2: Software

Here is brief rundown of the software packages I use in this set up. Links and discussion on alternative software can be found in Appendix A.

OS: Mandrake Linux

The OS this tutorial is run on is a Mandrake Linux distribution. This is my chosen distribution, however with minor tweaking the guide should be compatible with other distribution, I just dont have access to a system with them on.

This was originally written based upon Mandrake 9.1, then update for 9.2 and now is based Mandrake 10 Official.

Any further future releases should be compatible with this tutorial with a few tweaks.

MTA: Postfix

Sendmail is the most famous MTA, email server, for *nix flavours. However it is a monster, which is where Postfix come in. It is designed as a capable but easier to use MTA.

Database: MySQL

A database is not essential for a mail server of this kind, but it does make it easier to maintaina and scale.

Pop/Imap: Courier IMAP

A stable Imap/Pop server that is often used with Postfix. Handles SSL as well and is easy to configure.

WebMail: SquirrelMail

Also a well supported application that is easy to configure. PHP based and sits in your web directory.

SMTP Authentication: Pop-Before-SMTP

If you need outsiders to send email via your server, you need to authenticate them some how. Pop-Before-SMTP is an easy way to do this, an requires no user configuration.

Content Check Interface: Amavisda-new

Amavisd-new a fork off Amavisd is an interface with several easy plug ins for content checking. Well supported, extensive configuration options.

AntiSpam: SpamAssassin

A well know spam detector. Often achieves 99% detection. Uses several techiniques: Signatures, blacklists and now Bayesian filters.

AntiVirus: ClamAV

A mature scanner with frequent signatures updates.

Go to top.

1: Building

Thankfully Mandrake 10 comes with most of the packages as binary RPMs on the CDs. Some later ones you have to download tar files, but none require compiling.

Make sure you have the pre-requisites in Appendix C.

Fetch the source/binary of the S/W we are going to use. Mandrake comes with several of the S/W used as RPMs, the others must be fetched from the links in Appendix A.

I recommened always get the latest stable versions and keep yourselves up to date. However this tutorial may not be fully compatible with future versions, so maybe use the ones mentione here then upgrade after you got it working.

If your distribution , does not come with a pre built Postfix, or in the case of Mandrake 9.x the prebuilt RPM does not include MySQL support, then you need to uninstall, rebuild the RPM and reinstall the rebuilt RPM. ( Appendix A has a link to a Mandrake 9.1 Postfix RPM with MySQL support. )

rpm --rebuild --with mysql postfix.xxxx.SRPM.

Go to top.

Basic server

Initial steps is to get a server up and running. For that we will install only Postfix, MySQL and Courier. Ive included the database, but you can have an even more basic server without it. I have included it as my further steps depend on it.


Install the Postfix RPM with MySQL support. If you are using Mandrake 10, you need to Postfix RPM and the Postfix-MySQL RPM( and their dependancies). This will do a lot of the neccessary step for you. It should create the user and groups required. It will create the init script for you and create the folder /etc/postfix where all the configuration files will be kept.

Make sure the rpm has created the correct users and groups. Postfix use a postfix user and a postdrop group.

You need to create the folder where the mails will be spooled to. This in my setup is /var/mail/virtual. And an owner to own the emails and the directory. Create this directory and change owner to virtual:

adduser -M -u 5000 virtual
mkdir /var/mail/virtual
chown virtual /var/mail/virtual

You may need to edit the aliases file, and towards the bottom replace a user (yours>?) with the dummy one user , so that all email to root goes to you. This may already have been set for you so this step may not be neccessary. But do it anyway and then create a hash of it with this command:

postalias aliases

Create backup copies of the main.cf and master.cf, and keep doing so throughout this tutorial for safety sake.

Postfix have a great security feature of running everything in chroot. This restricts all files that anyone can access through it to within /etc/postfix only.

However this is restrictive when you need to access other parts, and we may need to initially disable this options. Remember this step: First change nothing, only view your master.cf and notice what state each section onder chroot column is set to. If virtual is set to y, change this to n.

If some stages dont work, it often is the chroot step that is restricting it. You may often finding yourself turning the whole chroot column to n to test if it is the problem, then setting them back to y, where applicable.

( It is important you change these back to y later, once you can test if they are the source of problems or not. Otherwise you wont be utilising the chroot jail facility of Postfix.)

Set up a clean and basic main.cf. Mdk 10, comes with a basic main.cf that you can base your upon. These are example settings:

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/lib/postfix
mail_owner = postfix
unknown_local_recipient_reject_code = 450
alias_maps = hash:/etc/postfix/aliases
mail_spool_directory = /var/spool/mail
mailbox_command = /usr/bin/procmail -Y -a $DOMAIN
debug_peer_level = 2
debugger_command =
	 xxgdb $daemon_directory/$process_name $process_id & sleep 5
delay_warning_time = 4
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
setgid_group = postdrop
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.0.6/samples
readme_directory = /usr/share/doc/postfix-2.0.6/README_FILES
alias_database = hash:/etc/postfix/aliases
smtpd_banner = $myhostname ESMTP $mail_name (Mandrake Linux)
inet_interfaces = all
smtpd_recipient_restrictions = reject_unauth_pipelining, \
reject_unknown_recipient_domain, permit_mynetworks, \
smtpd_sender_restrictions = reject_non_fqdn_sender, \

Next add you ISPs smtp server or whichever SMTP server you normally use for sending emails through. You can once you have firewalls, dns and all settings tested leave this as blank, so that your server acts as the relayhost on its own. You are then in more control of the queues, although I feel more secure relaying through my ISPs smtp server.


Add the name of you server. Postfix is clever and may work it out anyway, but it is better to specify it. Postfix will workout domain name from it.


Next we need to tell Postfix we wont be using local users, but instead a database based virtual users.


local_recipient_maps =
mydestination =
virtual_mailbox_base = /var/mail/virtual
virtual_mailbox_maps = mysql:/etc/postfix/mysql_mailbox.cf
virtual_uid_maps = mysql:/etc/postfix/mysql_uid.cf
virtual_gid_maps = mysql:/etc/postfix/mysql_gid.cf
virtual_mailbox_domains = localhost.$mydomain $mydomain $myhostname

Next we need to create the files Postfix will use to query the MySQL database.

Create these three files in the postfix directory:







Obviusly, change the fields where applicable. If your mail database (dbname)/ MySQL username (user)/ MySQL password (password) or database server (hosts) is not correct change it it to your setup. However if you keep to my setup exactly only the password field needs adjusting.

Go to top.


MySQL is now a quite renowned database and was an easy choice.
( Firebird would have been the ideal choice, but is not supported by any of the apps we will use for this mail server. )

If it is not installed already, follow the instructions in Appendix: Pre-Requisites.

Create a mail user and set its password as well.

mysql -u root -p**** mysql
GRANT ALL PRIVILEGES ON *.* TO 'mail'@'localhost'
mysql -u mail -p****

If you mess up and lock yourselves out of MySQL, dont panic. There are several ways to recreate your users, look up in Google for ways to start MySQL without grant tables. Or if you dont have any data in other databases, reinstall it!

Create the mail database

create database maildb;
use maildb;

Create the tables required for Postfix.

CREATE TABLE `users` (
  `id` varchar(128) NOT NULL default '',
  `crypt` varchar(128) NOT NULL default 'sdtrusfX0Jj66',
  `name` varchar(128) NOT NULL default '',
  `uid` smallint(5) unsigned NOT NULL default '5000',
  `gid` smallint(5) unsigned NOT NULL default '5000',
  `home` varchar(255) NOT NULL default '/var/mail/virtual/',
  `maildir` varchar(255) NOT NULL default 'spam/',
  `quota` varchar(255) NOT NULL default '',
  `enabled` tinyint(3) unsigned NOT NULL default '1',
  `change_password` tinyint(3) unsigned NOT NULL default '1',
  `procmailrc` varchar(128) NOT NULL default '',
  `spamassassinrc` varchar(128) NOT NULL default '',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `id` (`id`)

id is the email field, a complete address which is the ids people use. crypt is the password field, encrypted with Unix Crypt(), and not MySQL's version. Its default password is ChangeMe. Obviously change these later. home is the path to where the folders are kept, and maildir is the directory where this users mail are kept. Multiple rows with same maildir will share emails. If maildir ends on a /, then Postfix will use the maildir mail spooling option and not the mail file spooling. I think Courier require maildir format. Ignore the other fields for now.

Go to top.

Courier IMAP

Pop3 and IMAP server is of course required. Otherwise getting access to mail is tricker. Courier has support for MySQL authenticaton among others and are used in many Postfix+MySQL+Courier setups.

Again the require RPMs are available on Mandrake's CDs

rpm -i courier-imap-1.7.0-3mdk courier-imap-pop-1.7.0-3mdk \
courier-imap-mysql-1.7.0-3mdk courier-imap-utils-1.7.0-3mdk

Configuration files are in /etc/courier. Edit authdaemonrc and modify this line to:

authmodulelist="authmysql authpam"

Edit authmysqlrc:

MYSQL_SERVER         localhost
MYSQL_PORT           0
MYSQL_DATABASE       maildb
MYSQL_WHERE_CLAUSE      enabled=1

The last setting is optional, if you want to be able to disable accounts.

Edit imapd and set this to 2 then change to 0 later when working:


Then edit imapd again edit this line to YES


Depending on what you want running you can turn the others, pop3,


imapd-ssl and/or pop3-ssl on as well:

If you plan to have many connections per client, ie. perhaps you want to login to 20 mailboxes at once,then you need to increase the connections limit in the different files. E.g in imapd

Go to top.


Not many systems are any good without any data in them. You need to comply to some RFC by adding abuse and postmaster as valid email addresses. Also a root user is a good idea. In MySQL insert these statements

INSERT INTO users (id,maildir) VALUES
('[email protected]','post/'),
('[email protected]','post/'),
('[email protected]','post/'),
('[email protected]','post/'),
('[email protected]','post/');

You need to insert the users you require on top of this. Naturally start with one and add more when working ok.

INSERT INTO users (id,maildir) VALUES \
('[email protected]','yourname/');

Addresses such as info, support and sales are very common addresses and you may find them usefull, however they will also fill up with junk mail quite quickly.

Test it

The basic server is now configured. Remember to turn all debugging on. Start/Restart the servers:

/etc/init.d/mysql start
/etc/init.d/courier-imap start
/etc/init.d/postfix start

Send an email to one of the users configured. Watch the /var/log/syslog for any activity. Now set up an email client to read the email. Read Appendix E: for a some examples.

Go to top.

Advanced Server

When you have the basic server up and running it is worth extending it into an advanced server. This adds a few usefull options, and makes maintaining it simpler as well.


In the basic setup, domains are hardcoded into main.cf. To be more flexible, you can use the database to supply the domains used.

Modify the virtual_mailbox_domains line:

virtual_mailbox_domains = mysql:/etc/postfix/mysql_domains.cf

Create a new file in postfix folder: mysql_domains.cf


Create the table in MySQL:

CREATE TABLE domains (
pkid smallint(6) NOT NULL auto_increment,
domain varchar(120) NOT NULL default '',
transport varchar(120) NOT NULL default 'virtual:',

Populate the table

insert into domains (domain) values

Now next time you want the mail server to receive mail from a domain, just insert it into this table. Apperently you need to have local: for at the real domain name of the server. However I can not verify this.

Go to top.


Instead of creating loads of records in the users table, you could implement Aliases. This means you can forward loads of accounts to one address. Handy if you have multiple of domains. It also makes it easier to manage the users table, and controlling who can access and who receives what.

Append this line to main.cf:

virtual_alias_maps =mysql:/etc/postfix/mysql_alias.cf

Create this file: mysql_alias.cf


Then import this into MySQL:

CREATE TABLE aliases (
pkid smallint(3) NOT NULL auto_increment,
mail varchar(120) NOT NULL default '',
destination varchar(120) NOT NULL default '',
PRIMARY KEY  (pkid),
UNIQUE KEY mail (mail)

Populate the table, remember you need to alias the aliased address to itself as well.

insert into aliases (mail,destination) values
('[email protected]','[email protected]'),
('[email protected]','[email protected]'),
('[email protected]','[email protected]');

If you add a @domain.tld as mail field, then all mails not matching others for that domain will go that destination. Handy sometimes, spamfest other times.

Go to top.


Another advantage of using the aliases option, is that you can then forward email outside your domains. E.g:

insert into aliases (mail,destination) values
('[email protected]','[email protected]');

This will now forward that email to that persons other address not hosted by you. Handy for friends who want an email address, but prefer to use other email servers.

Go to top.


Another feature to avoid email addresses like this: [email protected], you can masquerade it into: [email protected]. Append these lines to main.cf.

masquerade_domains = server.domain.tld !notlocalname.domain.tld
masquerade_exceptions = root
Go to top.

Backup MX

Emails are today an important tool of communication. And loosing emails can be very annoying and with significant implications sometimes. So when your server goes down (which mine does every night!), you dont want to loose any emails. Luckily by default most email servers will keep trying to send to your server for ~ 5 days. But you can not be sure of this.

Postfix can work as a backup server. If the primary MX server is down, and this server is the secondary, Postfix will spool all emails for that domain. It will try at intervals if the primary is up again and if so forward the backed up emails to it. This gives you the confidence that fewer emails will be lost.

But the flipside is that you may want people to be notified if the urgent email they sent has been delayed? It is a choice you have to make.

To enable back up, of you own domain you dont do anything, however to enable backup on your server of other's domain emails append this to Postfix's main.cf

proxy_interfaces =
relay_domains = mysql:/etc/postfix/mysql_domains.cf \
transport_maps = mysql:/etc/postfix/mysql_transport.cf
maximal_queue_lifetime = 16
minimal_backoff_time = 1000
maximal_backoff_time = 54000

Replace the with your external IP if behind a NAT. This can be tricky if your IP keep changing. See Appendix F for tips on how to automate this. The Queue Lifetime is how many days the server keeps the emails. Default is 5, however 16 should cover a holiday etc.

For your server to connect directly to the primary server when it comes online again, you need the transport field. It contains the SMTP server address, wrapped in :[], which indicate ignore its mx settings, just use it.

And replace smtpd_recipient_restrictions with this:

smtpd_recipient_restrictions = permit_mynetworks, \
reject_unauth_destination, check_relay_domains

This will generate some errors as check_relay_domains is being faded out, but I am not 100% reject_unauth_destination works the same when using back up relays.

You need to create this file mysql_backups.cf:


and this file as well mysql_transport.cf:


And then create this table in the database:

CREATE TABLE backups (
  pkid smallint(6) NOT NULL auto_increment,
  domain varchar(128) NOT NULL default '',
  transport varchar(128) NOT NULL default ':[]',
  PRIMARY KEY  (pkid),
  UNIQUE KEY domain (domain)

Then you would insert records like this:

insert into backups (domain,transport) values
Go to top.


The next step is restricing who can use your server, to protect it and stop crackers and spammers abusing it. The basic server does restrict where mails can go and where they can send them from. But not much protection beyond that. This step is important, and should be followed.

Error Limits

Error limits stops spammers trying millions of email addresses on your server before it gets fobed off. E.g. [email protected],[email protected]. Recipient Limit will stop spammers CCing 100s of people if they get to your server.

smtpd_soft_error_limit = 3
smtpd_hard_error_limit = 12
smtpd_recipient_limit = 16

Proper Headers

To protect yourselves againts spammers or bad clients. And make sure that the headers it will need has not been corrupted.

smtpd_helo_required = yes

And replace smtpd_recipient_restrictions with this:

smtpd_recipient_restrictions = permit_mynetworks, \
reject_unknown_recipient_domain, reject_non_fqdn_recipient, \
reject_unauth_destination, check_relay_domains


A number of sites keep a list of know open relay server, which are easily abused by spammers. By blocking these you keep a lot of spam out, and also help in convincing people to not have open relays.

smtpd_client_restrictions =  \
reject_rbl_client bl.spamcop.net, \
reject_rbl_client sbl.spamhaus.org, \
reject_rbl_client relays.ordb.org, \
reject_rbl_client blackholes.easynet.nl, \
reject_rbl_client dnsbl.njabl.org, \
reject_rbl_client cbl.abuseat.org

I initially included reject_rbl_client dnsbl.sorbs.net as well. However it blocks my ISPs SMTP server (NTL), which must have been an open relay at some point, but blocking it would be problematic for me!


In Postfix's master.cf we disabled the chroot jail when setting up this server. For security sake it is a good idea to reenable this. However it will be some trial and error to get this working. One issue is that the MySQL socket is outside this jail. This can be overcome with using TCP/IP traffic by setting in your mysql .cf files

where server.domain.tld is your server name.

Go to top.

Web Mail.

A webmail is an easy front end to test and to use for all. It does not replace your normal email client usage, but it enables quick access from other locations. It also enables less computer liturate to use email as well.

I have chosen SquirrelMail as my webmail package. It is not the prettiest, but it is easy to manage and setup. It is well supported and used, and has many usefull plugins.

Make sure you have the correct Pre Requisites installed. If you get a DB.php error, then you have not installed Berkeley DB support that comes with PHP-Pear.

See Appendix A on how to get it, and extract it to your web directory. It is all PHP and does not need compiling. Follow the INSTALL direction in its folder, and then run ./config/conf.pl from the folder. Change your settings as required. Dont enable any plug ins at this stage.

In the database section change 1 . DSN for Address Book to


Then change 3 . DSN for Preferences to


Then create these tables in MySQL

CREATE TABLE address (
  owner varchar(128) NOT NULL default '',
  nickname varchar(16) NOT NULL default '',
  firstname varchar(128) NOT NULL default '',
  lastname varchar(128) NOT NULL default '',
  email varchar(128) NOT NULL default '',
  label varchar(255) default NULL,
  PRIMARY KEY  (owner,nickname),
  KEY firstname (firstname,lastname)
) ;
CREATE TABLE userprefs (
  user varchar(128) NOT NULL default '',
  prefkey varchar(50) NOT NULL default '',
  prefval varchar(255) default NULL,
  modified timestamp(14) NOT NULL,
  PRIMARY KEY  (user,prefkey)

There will be no need for data in these tables. You need to configure your web server to point to SquirrelMail. Either you have addedd SM as folder inside an existing site, or you will be using it as a virtual host, so change webserver's conf ig files if needed. That should be it. Try it. Login name is the id in the users table. A user need to have a mail for the maildirectories to be created before log in so send the user an email first.

Further extensions via plugins are discussed in Further Extensions.

Go to top.

Send Mail.

If you have followed my basic-advanced-tighter server setup, your server now is now fairly well configured. However only your local network, or perhaps just the mail server can send emails out via your server. Anyone else whom tries will get a polite fob off message.

That is okay if everyone can use their local ISP as mail relay. But not everyone can or want to, and what happens when you are traveling, and not got access to your normal ISP. So you need to allow people the ability to send email via SMTP from anywhere.

But simply allowing access to outside world is dangerous, and quite likely will be abused. So we need some way of authenticate the users.

SASL, a way of securely authenticate users, is an option many uses, but I dont. The only reason is that I couldnt get it to work. I may add it to the extensions section later.

Pop-Before-SMTP is my chosen option, and does not actually involve any specific authentication. As the name indicates the server records the IP numbers of people who authenticated okay for Pop or with IMAP. It stores their IP for a brief moment, and if traffic from that address request SMTP shortly afterwards, they will be accepted.

Pop-before-SMTP is available as an RPM in Mdk 9.x. However it did not seem to install the config file, so I retrieved the latest tar file instead.

Untar it and test its dependencies with this command:

./pop-before-smtp --config=./pop-before-smtp-conf.pl \
--debug --nowrite --reprocess

If okay: copy the binary file to /usr/sbin, copy the init file /etc/rc.d/init.d copy the pl file to /etc

cp pop-before-smtp /usr/sbin/
cp pop-before-smtp.init /etc/rc.d/init.d/pop-before-smtp
cp pop-before-smtp-conf.pl /etc

Modify /etc/pop-before-smtp-conf.pl, file_tail should be like this:

$file_tail{'name'} = '/var/log/mail/info';

Also incomment the courier lines.

Modif y this line again in Postfix's main.cf:

smtpd_recipient_restrictions = permit_mynetworks, \
reject_non_fqdn_recipient, \
check_client_access hash:/etc/postfix/pop-before-smtp, \
reject_unauth_destination, check_relay_domains

The limitation of Pop-Before-SMTP is that people have to check mail before sending. Some clients send before read. So some users need to send/receive twice.

Go to top.

Content checks

When you start receiving emails you will notice how much of it is junk. And if you run M$ Windows especially you are vulnarable to computer viruses. Postfix can be adjusted to check the contents of emails whether they are valid and what to do about it.


For this you need a content check interface and that is what amavisd-new is. It is itself built upon amavisd but is now much more mature and feature rich than the original.

If you are installing this from Mandrake 10.0, be ware MDK ship with amavisd and amavisd-new, but only amavisd is listed as recommended rpm. As I prefer amavisd-new, you will have to search for amavisd.

The RPM would do all the automatic steps here, but check that they are all done.

If you are able to, install from RPM (MDK 10.0) or if you desire obtain the tar.gz file from the site in Appendix: Software and extract it. Amavisd-new is Perl based, and dont need compiling, but do need other modules. If you install from RPMs using e.g. RPMDrake the dependencies will be automatically installed. Otherwise There should be INSTALL file to read in the folder. It will contain a list of modules that you need. They all come with the Mdk CDs so just check if they exist. They will all be named perl-xxxxxx as they are all Perl modules. You may do an install like this.

rpm -i perl-Archive-Tar-x.xx \
perl-Archive-Zip-x.xx perl-Compress-Zlib-x.xx \
perl-Convert-TNEF-x.xx perl-Convert-UUlib-x.xxx \
perl-IO-stringy-x.xxx perl-MailTools-x.xx  \
perl-MIME-Tools-x.xxxx perl-Net-Server-x.xx \

Where as usual you replace the xs with version availble. perl-MIME-Base64, perl-libnet, perl-Time-Hires and perl-Digest-MD5 are not RPMs with Mandrake, as they comes with the standard Perl install, so it is not required to install seperatly.

Create an user and group to run the daemon. This will be used for antispan & virus as well, so make it a good un. Then create a folder for amavisd-new to use, and the make it owned by the user created.

adduser amavis
mkdir /var/local/amavis
chown amavis:amavis /var/local/amavis
chmod 750 /var/local/amavis

Copy the amavisd from the source to /use/local/sbin, the conf file to /etc/amavis and the init file to /etc/rc.d/init.d.

cp amavisd /usr/local/sbin
chown root /usr/local/sbin/amavisd
chmod 755  /usr/local/sbin/amavisd
mkdir /etc/amavis
cp amavisd.conf /etc/amavis
chown root /etc/amavis/amavisd.conf
chmod 644  /etc/amavis/amavisd.conf
cp amavisd_init.sh /etc/rc.d/init.d/amavisd

Create a folder to store the quarantined emails

mkdir /var/local/quarantine
chown amavis:amavis /var/local/quarantine
chmd 750 /var/local/quarantine

Edit /etc/amavis/amavisd.conf. There are so many settings in there, so it is wise to:

  1. Make a backup
  2. Change one thing at a time
But first you need to set these settings:

$MYHOME = '/var/local/amavis';
$mydomain = 'yourdomain.tld';
$daemon_user  = 'amavis';
$daemon_group = 'amavis';
$LOGFILE = "$MYHOME/amavis.log";
$log_level = 2;
$QUARANTINEDIR = '/var/local/quarantine';
$forward_method = 'smtp:';
$notify_method = $forward_method;  
$inet_socket_port = 10024; 

Edit /etc/postfix/main.cf and add/modify this line:

content_filter = smtp-amavis:[]:10024 

In /etc/postfix/master.cf, make sure this line is there at the top:

smtp  inet  n  -  n  -  -  smtpd

Then add these line further down:

smtp-amavis unix        -       -       n       -       2       smtp
        -o smtp_data_done_timeout=1200
        -o disable_dns_lookups=yes inet    n       -       n       -       -       smtpd
         -o content_filter=
        -o local_recipient_maps=
         -o relay_recipient_maps=
        -o smtpd_restriction_classes=
        -o smtpd_client_restrictions=
        -o smtpd_helo_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o strict_rfc821_envelopes=yes

When everything is working you can set these settings in /etc/amavis/amavisd.conf back to:

$log_level = 0;

That is the base install of the interface. Next you need to install the anti-spam & anti-virus.

Go to top.

Anti Spam: Spam Assassin.

SpamAssassin is possibly the most well known spamdetector available. It can be run as a server or client. The version I use is easy to install, as it is Perl based. To install it, run rpmdrake and pick it or do this:

rpm -i perl-Mail-SpamAssassin-x.xx-xmdk

There are furher tools and plugins to choose if you like as well. It creates a file /etc/mail/spamassassin/local.cf which can be tweaked when using it on its own.

To edit the options used with Amavisd-new, open the amavisd.conf file again. There is a number of settings to tweak, but the defaults are fine. Amavisd-new recognises SpamAssassin by default.

Go to top.

Anti Virus: Clam AV

Amavisd-new has preconfigured options for a range of scanners, and particular this option that you should choose the one(s) you want. ClamAV, a free open source virus scanner, was my chosen product. It has an auto update option, large userbase, and since it is easy to setup, I am sold. If you prefer others, free or commercial then choose the one you trust. McAfee and Norten's command line scanners work fine with Amavisd-new.

Once again an RPM for ClamAV is available by Mandrake 9.1, however was failry outdated, as Anti-Virus software moves quicly on. So I prefered to get the latest MDK RPM of Rpmfind.net. Install the main, the lib and the latest virus database.


rpm -i clamav-x.xx-xmdk \
libclamav1-x.x-xmdk clamav-db-x.xx-xmdk

The conf file /etc/clamav.conf, should be okay, but change it neccessary. Amavisd has support for it to call the daemon and the command line version of clamd. I could not get the daemon to work, but the command line was fine. Edit amavisd's conf file again and comment out all other virus scanners at the av_scanner,/i> section, and then only leave i>ClamAV in the @av_scanners_backup section.

@av_scanners = ();
@av_scanners_backup = (
  ['Clam Antivirus - clamscan', 'clamscan',
    '--stdout --disable-summary -r {}', [0], [1],
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],

That should be it for content checking. As there as so many options in the amavisd conf file, you should go through it more throughly.

Go to top.

Further Extensions


Go to top.

Content Checks

Go to top.


Go to top.


Go to top.

Web Admin

A web based front end to administer the email server. This simplifies viewing and modifying the email settings. While this mostly targets the email addresses, domain names etc, and not actual Postfix settings, some can be extended to enabled those to also be administered online.

A number of projects already exist which can be used. A quick search of Source Forge reveales several such projects. E.g. CourierAdmin, MyPFXAdmin, myWebHosting etc. ( All phpMyAdmin inspired names...).

But as I am stuborn, I've decided to write my own. It is not ready for public release yet though, as it has few features, needs more debugging and definetly needs someone to do some fluffing over it.

Click here to Download PostfixAdmin. It is simple Java Web Application that I wrote to administer my postfix box. It is not a WAR file, as you need to tweak the WEB-INF/apes.xml and the context if needed.

Go to top.

Appendix: Quick Setup


Files modified in Basic Server setup.

Dont finish with this, it is too unsafe.

Install Postfix, Courier-IMAP, MySQL.

File List:


Download(Not Available)

Read the shell script postfix_basic_setup.sh, verify I am not corrupting your server, tweak anything non standard, and then execute it.

Go to top.


Files modified in Advanced Server setup.

A powerfull server, but not recommended due to security issues.

File List in addition of Basic:


Download(Not Available)

Read the shell script postfix_adv_setup.sh, verify I am not corrupting your server, tweak anything non standard, and then execute it.

Go to top.


Files modified in Tighter Server setup.

A reliable solution.

File List in addition of Advanced:


Download (Not Available)

Read the shell script postfix_tight_setup.sh, verify I am not corrupting your server, tweak anything non standard, and then execute it.

Go to top.


Files modified in Webmail, Send mail and Content Checks setup.

Advanced Tight Server with webmail, send support and content check.

Install Amavisd-new, SpamAssassin, ClamAV.

File List in addition of Tighter:


Download (Not Available)

Read the shell script postfix_comp_setup.sh, verify I am not corrupting your server, tweak anything non standard, and then execute it.

Go to top.

Appendix: Software Links

Go to top.

Appendix: References

My own initial server was based on a set of tutorials by John Lock on the TechRepublic web site.

It was then extended with a mixture of HowTos from the Postfix website.

Among some read were:

has now updated their documentation. So refer to it for commands and set up issues as well. (RTFM).

Other Guides:

I also read the Postfix: The Definitive Guide, and O'Reilly book written by Kyle D. Dent. Its a thorough book, and worth a read if you want to know every bit of all the options available with Postfix.

Buy it here from Amazon UK if you are in their catchment area.
Go to top.

Appendix: Pre-Requisites


Firstly install the OS. Mandrake is easy to install to what ever you require for it to do.


Enable SMTP, POP3, IMAP, POP3S, IMAPS on your firewall. If you use the MDK's supplied Shorewall simple add this line to /etc/shorewall/rules and restart Shorewall:

ACCEPT  net     fw      tcp     25,80,143,443,993,995       -

You may however restrict this to only local net while testing:

ACCEPT  net:     fw      tcp     25,80,143,443,993,995       -

Source Packages

Aquire all the souce files needed. See Appendix: Sources, download the ones not on your distribution CD (or URPMI). Then install MySQL and PHP as they are not described anywhere else.


Install MySQL with the RPMs that mandrake supplies. Use these commands, or use rpmdrake and search for mysql.

rpm -i MySQL-x.x.xxx-x.xmdk MySQL-common-x.x.xxx-x.xmdk \
libmysql12-x.x.xxx-x.xmdk libmysql12-devel-x.x.xxx-x.xmdk \

Start the server and test it

/etc/init.d/mysql start

Debug logging of mysql command is possible by creating /etc/my.cnf:


Make sure root has a password. Default is not!

mysqladmin -u root password ****


PHP is require for webmail and myPHPAdmin

rpm -i apache2-mod_php-x.x.xx_x.x.x-xmdk \
libphp_commonxxx-xxx-xx.xmdk php-mysql-x.x.x-xmdk \

MySQL Client

You need to a client to create and manipulate the database. The default command line client is fine.

rpm -i MySQL-client-x.x.xxx-x.xmdk

However a better interface is desirable. phpMyAdmin is a web interface that has become a standard for MySQL administration. Fetch the php tar file from phpmyadmin.sf.net and install into a web folder. Then read INSTALL file.

Go to top.

Appendix: Comments

Send comments to me.

Name: Ivar
Date: 2004-03-06
Subject: Etiquette
I will post comments made by people here. Bux fixes, better tweaks, and helpfull messages etc. Comments like "You use package A, but package B is way better, as that is what I use." wont be posted as it is not relevant. Some of the comments will be parafrased and edited. If you do not want comments here, then place state so.

Name: James
Date: 2004-05-17
Subject: Postfix Howto
First I would like to say "Thank You!" for the guide you put up at http://home.eray.biz/sites/postfix/. I have not gotten any of it work quite yet but am trouble shooting as I go. I did notice a couple of small things so far, that I wanted to point out: First: In the mysql_gid.cf file you have select_field=uid and I believe it should read select_field=gid

Second: unless I missed it, we never create the DB for the users table. This is not a big deal to do however, since your how-to is very step by step, it may be confusing to some. Honestly I have not moved past the basic setup yet.

I am having some permission problems (although Fetchmail grabs the mail alright, the system is unable to create the /var/mail/virtual/foo/bar/ dir.) I am sure that this is a small issue perhaps with the way the APT packages are set up for Debian vs the RPM's you used in Mandrake. Anyway, although I have used postfix quite a bit in the past, this is the first time I have used it with MySQL and Courier. The setup you end up with is pretty much exactly what I want to eventually have so it will be worth a bit of troubleshooting.

Thanks again; James


Name: Bob
Date: 2004-06-03
Subject: Email Server Setup

I followed the techrepublic article on email server setup for postfix,
courier-imap and squirrelmail and your article appears to be very similar.
I ran into an issue with squirrelmail preferences not working that I
finally traced to the mysql userprefs table having user set to only 20
characters, while one of my email addresses was slightly longer. This
seems like something that would affect quite a few people. I'd suggest

CREATE TABLE userprefs (
user varchar(20) NOT NULL default '',


CREATE TABLE userprefs (
user varchar(128) NOT NULL default '',

to match the id length given in the users table.

The big problem that I have is that I would like to do filtering on the
email as it comes in, but procmail is only used for local users and not
virtual users as we have set up. I see that the users table has
procmailrc as one of the fields, but I don't know how I would use it.
Everything that I find on the internet seems to say that procmail can not
be used with virtual users. Do you know of a way? Squirrelmail has a
nice plugin called serversidefilters that I would like to use to configure
the user procmailrc, I just haven't figured out how or if it can be done
with virtual users.



Name: Bob
Date: 2004-06-08
Subject: Email Server Setup

I installed maildrop and it works great with virtual users as well as with
the serversidefilter plugin in Squirrelmail. Now each user can create
filter rules easily from within Squirrelmail using a simple interface. I
would strongly suggest going with maildrop when using virtual users over
using procmail if you should ever need per user filtering.

Thanks for the reply and providing a great install document.



Name: Antti
Date: 2004-06-07
Subject: Postfix


Thank's for your great post system install manual!
I have one problem: I cannot login my account. Crypt is problematic.
How it works?
When I try to login, I get error that password is wrong.

Can you help me, please?

(sorry my poor english)

- Antti


Name: Antti
Date: 2004-06-12
Subject: Postfix


Thank's for help... but I have other problem now.

When I send email to my address, email come back and log say:

postfix/smtpd[17664]: NOQUEUE: reject: RCPT from
xxxx.xxxx.fi[###.###.###.###]: 554 <[email protected]>: Relay access
denied; from=<[email protected]> to=<[email protected]>
proto=ESMTP helo=<xxxx.xxxx.fi>

Maybe I have to use mynetworks variable in main.cf ?

- Antti


Name: Ken
Date: 2004-06-08
Subject: Question on your Postfix Tutorial

Hi Ivar:

I hope this email finds you doing well.

I've been following your tutorial on Postfix + Mysql
at http://home.eray.biz/sites/postfix/.

Thank you for taking the time to outline all of these
steps, without your tutorial, I'd be completely lost!

I've got postfix working using the basic
configuration, where is will accept mail to people
listed in the users table in the MySQL database.
However, the creation of mail in the virtual directory
is failing with a permission denied error.

I did a ps, and see that "virtual" is running as the
user "postfix" but the /var/mail/virtual directory is
owned by virtual, as you instructed. I'm wondering
where the virtual account is used, I don't see it in
any of your sample config files.

Please advise. Thanks again for your tutorial and help!


Go to top.

Appendix: Mail Clients

Here are some setup tips to read/send email via some familiar email clients.

Mozilla Thunderbird

Adding New Account.

Click File/New/Account. Select Email Account and click Next, Enter you name and email address and click Next, Select IMAP(Recommended) or Pop and enter your servername as server and click Next, Enter as username the full email address you insert into the database, into both fields and click Next, Enter an Account name and click Next then Finish.


Step by Step guide.

Outlook Express

Novell Ximian Evolution


Go to top.

Appendix: Automating Proxy Interfaces

  1. Hardcoded replace: Ian Newby wrote this script to


touch history.ip
dig  yourserver.domain.tld | grep ^yourserver.domain.tld \
| awk '{print $5}' > current.ip
if cmp current.ip history.ip >/dev/null
	# they are the same
	cp current.ip history.ip -f
	date >> current.ip
	tr '\n' '\t' < current.ip > temp
	echo >> temp
	cat temp >> iphistory.txt
	stuff=`cat history.ip`
	sed -e "s/^proxy_interfaces=.*$/${stuff}/g" < /etc/postfix/main.cf > temp
	mv temp /etc/postfix/main.cf -f
	postfix reload
Go to top.

Appendix: Startup Scripts

To wrap things up, you need to set the servers up to start automatically. Make sure that in /etc/rc.d/init.d there are: a postfix, courier-imap, spamassassin, amavisd, pop-before-smtp and maybe a clamd. then check that they are linked from rc3, 5 and 6. If not do something like this.

cd /etc/rc.d/rc3.d
ln -s ../init.d/amavisd S79amavisd
ln -s ../init.d/clamd S77clamd
ln -s ../init.d/courier-imap S81courier-imap
ln -s ../init.d/pop-before-smtp S82pop-before-smtp
ln -s ../init.d/spamassassin S78spamassassin
ln -s ../init.dpostfix S80postfix
cd /etc/rc.d/rc5.d
ln -s ../init.d/amavisd S79amavisd
ln -s ../init.d/clamd S77clamd
ln -s ../init.d/courier-imap S81courier-imap
ln -s ../init.d/pop-before-smtp S82pop-before-smtp
ln -s ../init.d/spamassassin S78spamassassin
ln -s ../init.dpostfix S80postfix
cd /etc/rc.d/rc6.d
ln -s ../init.d/amavisd K31amavisd
ln -s ../init.d/clamd K33clamd
ln -s ../init.d/courier-imap K29courier-imap
ln -s ../init.d/pop-before-smtp K28pop-before-smtp
ln -s ../init.d/spamassassin K32spamassassin
ln -s ../init.dpostfix K30postfix
cd /etc/rc.d/rc0.d
ln -s ../init.d/amavisd K31amavisd
ln -s ../init.d/clamd K33clamd
ln -s ../init.d/courier-imap K29courier-imap
ln -s ../init.d/pop-before-smtp K28pop-before-smtp
ln -s ../init.d/spamassassin K32spamassassin
ln -s ../init.dpostfix K30postfix

This should start the server up every time. Or use chkconfig to set up the links for you.

Go to top.

Appendix: Mail Backup

Postfix's Maildir type email can be backed up. Limitation are than only delivered mail can be easily backed up. The spool files of queued mails are more tricky. Set up a cronjob to include something like this:

tar -czf mail.tgz /var/spool/mail

I would advice a backup plan for the mysql database as well. Utilise the mysqldump program and backup your mail database.

mysqladmin -d -B maildb -u mail -p**** > maildb_schema.sql	
mysqladmin -n -t -B maildb -u mail -p**** > maildb.data.sql
Go to top.

Appendix: Sources

These were the source packages used.


Use the ones supplied with your distrubution, if not then download these RPMs and Tar files:

Go to top.
eRay © 2004. Last Mod: 23/06/2004 - IEA