Sie sind auf Seite 1von 34

Mail Server Installation and Configuration

by rey on May.27, 2009, under Linux Tutorial



With all of the tutorials posted here, this is one of the most complex setup that I want to share
with you. If you haven’t read my previous post regarding “DNS Installation and Configuration”
please have a look at it because mail required a valid MX record. I am not saying that, you need
to install your own name server. You can use name server somewhere but the most important
thing is that, there must be an MX record pointing to the IP address of your mail server.

My mail setup consists of the following software:

1. Postfix – The SMTP Server;

2. Cyrus SASL – SMTP Authentication;
3. pam_pgsql – Pluggable Authentication Module, sits in between Cyrus SASL &
4. Spamassassin – Spam filter which is equipped with:
o DCC – Distributed Checksum Clearinghouses
o Pyzor
o Razor
5. ClamAV – Clam Antivirus;
6. ClamSMTP – An SMTP filter sits in between the SMTP Server and ClamAV;
7. Dovecot – POP3, POP3S, IMAP & IMAPS Server;
8. PostgreSQL – Domain and User database;
9. Squirrelmail – Webmail IMAP client;
10. And my very own cPanel web interface.

The mail server which I am going to build supports multiple domains. Each domain has their
own unique users which means that user@domain1 is totally different from user@domain2, they
have separate mailboxes.


1. Database Installation & Configuration;

Install the postgresql database server

# yum -y install postgresql postgresql-server postgresql-
Enable postgresql to start at boot in runlevel 2,3,4 & 5
# chkconfig ––level 2345 postgresql on

Start the postgresql server now

# service postgresql start

Modify postgresql.conf
# vi /var/lib/pgsql/data/postgresql.conf

listen_addresses = ‘localhost’
port = 5432
datestyle = ’sql, mdy’

Modify pg_hba.conf
# vi /var/lib/pgsql/data/pg_hba.conf

local all all trust

host all all trust
host all all ::1/128 trust

Disable selinux protection for postgresql otherwise it will

give us headache;
# setsebool -P postgresql_disable_trans=on

Restart the database server to activate the changes

# service postgresql restart

Create the database user “mail”

# createuser -U postgres mail
Create the database “mail”
# createdb -U postgres -E utf-8 mail

Download the database schema then load to the database

# wget -O –
content/uploads/2009/05/mail.sql | psql -U postgres -d mail
-f -

Create the admin user to be use for the cpanel web

interface. Please notice the password and changed it with
your own.
# psql -U postgres -d mail -c "INSERT INTO sysusers
(username,password,name) VALUES

Allow access to user admin with read/write permission to

the module “access” in cpanel web interface.
# psql -U postgres -d mail -c "INSERT INTO access
(username,module,read,write,mode) VALUES
2. Web server intallation and configuration and the cPanel web interface

Install the http server and other required softwares

# yum -y install httpd perl-DBI perl-DBD-Pg

Allow httpd to connect to the database server

# setsebool -P httpd_can_network_connect_db=on

Download and uncompress the cPanel

# wget -O –
content/uploads/2009/05/cpanel.tgz | tar -zxpf – -C /

Change some selinux attributes

# chcon -R -u system_u -t httpd_sys_content_t
# chcon -t httpd_unconfined_script_exec_t
# chcon -R -t httpd_sys_script_exec_t /usr/local/cpanel/bin/

The http configuration file for my webmail and the cpanel

# vi /etc/httpd/conf/httpd.conf

# At line 972 I put this line


# At line 211 I put this entry

Include vhost.d/*.conf

Create the virtual host directory

# mkdir /etc/httpd/vhost.d

Create my virtual host configuration

# vi /etc/httpd/vhost.d/
Allow http,https,mail,postgres,pop3 & imap traffic, Other
ports entry are:
# system-config-securitylevel-tui
Enable httpd to start at boot in runlevel 2,3,4 & 5
# chkconfig ––level 2345 httpd on

Start the httpd server

# service httpd start

3. cPanel is my custom web application to manage domain, users and mail aliases. You can
use this program at your own risk. I will not be liable if your server explodes due to the
use of this program. I want you to know that cPanel runs in suid mode as “root” which
means that even though httpd process is owned by user and group “apache” this program
has the access level as root which has access to everything in the server.

The cPanel login screen;

Setting up the access permission;
See the POSTFIX sub-menu as it appears when you click it.
Once you create a domain, cPanel will add it to the
database in “domains” table and will create a folder in
And here is the User Manager. If you create user on the
selected domain, it will add directory in /home/$(domain)/$
(user) and will served as the user’s mailbox.
4. Dovecot Installation and Configuration;

Install dovecot package with yum

# yum -y install dovecot

Enable dovecot to start at boot in run level 2,3,4 & 5

# chkconfig ––level 2345 dovecot on

Modify /etc/dovecot.conf
# vi /etc/dovecot.conf

Create /etc/dovecot-sql.conf
# vi /etc/dovecot-sql.conf
Start the dovecot daemon
# service dovecot start

My next step is to test dovecot. My nose bleeds struggling

dovecot and selinux because selinux prohibits dovecot to
authenticate user and to access user’s mailbox as well.
After writing and installed tons of semodule and yet keep
on failing, I have no choice but to disable it:
# setsebool -P dovecot_disable_trans=on && service dovecot

The final test for my dovecot. First is for POP3. Note if

telnet is not yet installed, use “yum -y install telnet”;
and then for IMAP.
5. Squirrelmail Installation and Configuration

You can download squirrelmail web client from but I have a
copy of squirrelmail which is built with MS Outlook skin and a password changer
designed to fit my PostgreSQL database. The following procedure is applicable if you use
the copy from here;

Download and extract the file;

# wget -O –
content/uploads/2009/05/squirrelmail.tgz | tar -zxf – -C /

Fix permissions;
# chown -R root:root /usr/local/squirrelmail/
# chown -R apache:apache /usr/local/squirrelmail/data
# chmod 0755 /usr/local/squirrelmail/data
# chcon -R -u system_u -t httpd_sys_content_t /usr/local/squirrelmail/

Modify the configuration file to fit my needs;

# vi /usr/local/squirrelmail/config/config.php
Install php and restart httpd
# yum -y install php php-pgsql php-pear php-pear-DB
# service httpd restart

Access the webmail now;

The login screen;

and the main screen.

6. We are almost 50% done. Next, we will install and configure ClamAV and ClamSMTP

The easiest way to install ClamAV is to install the

rpmforge repository;
# rpm -ivh

Then install clamav packages using yum;

# yum ––enablerepo=\* -y install clamav clamd clamav-db

Install the compiler and rpm builder;

# yum -y install rpm-build gcc make automake autoconf
Download ClamSMTP rpm source from Please always get the latest
# wget

Build the source rpm;

# rpmbuild ––rebuild clamsmtp-1.10-1.src.rpm

After successful build, there should be written file

/usr/src/redhat/RPMS/i386/clamsmtp-1.10-1.i386.rpm, If so,
then install it;
# rpm -ivh /usr/src/redhat/RPMS/i386/clamsmtp-1.10-

Configure clamd, normally the default configuration runs

perfectly. If you are curious, just take a look at that
# vi /etc/clamd.conf

Configure clamsmtpd;
# vi /etc/clamsmtpd.conf

# This is my working configuration

ClamAddress: /var/run/clamav/clamd.sock
Header: X-Virus-Scanned: ClamAV using ClamSMTP
Action: drop
User: clamav

Enable clamd & clamsmtpd at boot process;

# chkconfig ––level 2345 clamd on
# chkconfig ––level 2345 clamsmtpd on

I found no way to deal with selinux and clamav, the only

possible way is to disable protection for it;
# setsebool -P clamd_disable_trans=on
# setsebool -P clamscan_disable_trans=on
# setsebool -P freshclam_disable_trans=on

Start the service now

# service clamd start
# service clamsmtpd start

7. Postfix Installation;

Installing postfix is not just as simple as “yum -y install

postfix” because the default rpm build doesn’t compiled to
support pgsql though postfix does support it;

Here is the source RPM I’d been customized to support pgsql

otherwise, you have to download the source from the
distro’s repo and modify the spec file;
# wget

Before the build, we need to install all the required

# yum -y install db4-devel pkgconfig zlib-devel openldap-
devel cyrus-sasl-devel pcre-devel openssl-devel postgresql-

The actual build;

# rpmbuild ––rebuild postfix-2.3.3-3.src.rpm

Install postfix now;

# rpm -ivh /usr/src/redhat/RPMS/i386/postfix-2.3.3-

Disable selinux protection for postfix;

# setsebool -P postfix_disable_trans=on

8. Download, compile and install pam_pgsql;

Install the required dependencies;

# yum -y install pam-devel libmhash-devel libmhash

Change directory /usr/src;

# cd /usr/src

Download and extract the source, please check the site and
take the latest as possible;
# wget -O –
pgsql-0.7.tar.gz | tar -zxf -

Change directory pam-pgsql-0.7

# cd pam-pgsql-0.7

Start to compile;
# ./configure
# make
Install now;
# make install

Configure pam_pgsql;
# vi /etc/pam_pgsql.conf

host = localhost
database = mail
user = mail
table = users
user_column = userid
pwd_column = password
expired_column = expired
newtok_column = newtok
debug = 0
pw_type = crypt

Configure /etc/pam.d/smtp, use tabs to align;

# vi /etc/pam.d/smtp

#auth include system-auth
#account include system-auth

auth required

account required

Configure /usr/lib/sasl2/smtpd.conf;
# vi /usr/lib/sasl2/smtpd.conf

pwcheck_method: saslauthd
mech_list: login plain

9. Install, configure and test Cyrus SASL;

Install cyrus sasl package and its dependencies;

# yum -y install cyrus-sasl cyrus-sasl-plain

Configure saslauthd start-up config;

# vi /etc/sysconfig/saslauthd

Disable selinux protection for saslauthd;
# setsebool -P saslauthd_disable_trans=on && service
saslauthd restart

Enbale saslauthd to start at boot in run level 2,3,4 &5;

# chkconfig ––level 2345 saslauthd on

Start saslauthd now;

# service saslauthd start

Test SASL;
# testsaslauthd -u -p 1234 -s smtp

10. Postfix Configuration, the heart of the system. Please read the documents located in
/usr/share/doc/postfix*/ to learn more about postfix and to know how it works.

# cd /etc/postfix

Create/modify postfix main configuration file

# vi

# Postfix General Config

transport_maps = pgsql:/etc/postfix/
virtual_uid_maps = pgsql:/etc/postfix/
virtual_gid_maps = pgsql:/etc/postfix/
virtual_mailbox_base = /home
virtual_mailbox_maps = pgsql:/etc/postfix/
virtual_mailbox_domains =
virtual_alias_maps =

# Don’t just invent this one, If you’re using an

unregistered domain/hostname,
# you can simple add it to /etc/hosts bound to the IP
address of your
# network interface card.
myhostname =

myorigin = $myhostname
mynetworks = localhost.localdomain $myhostname
mydestination = localhost.localdomain $myhostname
mailbox_size_limit = 0
message_size_limit = 0
virtual_mailbox_limit = 0

#Cyrus SASL
smtp_sasl_auth_enable = no
smtpd_sasl_auth_enable = yes
smtpd_sasl_authenticated_header = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $mydomain
unknown_local_recipient_reject_code = 450

# SpamAssassin
strict_rfc821_envelopes = yes
disable_vrfy_command = yes
smtpd_helo_required = yes

# ClamAV
content_filter = scan:[]:10025
receive_override_options = no_address_mappings

# Others
header_checks = regexp:/etc/postfix/regexp_header

# Added by postfix
readme_directory = /usr/share/doc/postfix-
sample_directory = /usr/share/doc/postfix-2.3.3/samples
sendmail_path = /usr/sbin/sendmail
html_directory = no
setgid_group = postdrop
command_directory = /usr/sbin
manpage_directory = /usr/share/man
daemon_directory = /usr/libexec/postfix
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
queue_directory = /var/spool/postfix
mail_owner = postfix
unknown_local_recipient_reject_code = 450

# vi


# vi


# vi


# vi


# vi


# vi


As specified in “header_checks =

regexp:/etc/postfix/regexp_header” this file will decide to
those emails marked as Spam. For me, I have no time to
check those spam. My rule is to discard those emails
without informing the sender that his email was discarded.
# vi regexp_header

/^X-Spam-Flag: YES/ DISCARD

Modify the file

# vi

This is the beginning of the file. This tells postfix to

pass the email to the spamassassin content filter after
performing access check;
Then under the “spamassassin” service, we will do the
actual filtering by calling an external program
“/usr/local/bin/” passing all the required
parameters. Spamassassin job is to check and mark the email
either spam or not then send it back to postfix.

Postfix will then pass the email to the antivirus filter

service “scan” which is according to is on port
10025. Remember that, it is the ClamSMTP who is listening
on this port. ClamSMTP after receiving the email will
perform scan through the help of Clam Antivirus which is
listening on unix local socket
“/var/run/clamav/clamd.sock”. All infected emails will be
discarded immediately while clean emails will go out at
port 10026 which is again a postfix owned socket. The email
will then proceed to its final destination finally!.
Create /usr/local/bin/
# vi /usr/local/bin/

spamassassin -e | /usr/sbin/sendmail.postfix -i “$@”
exit $?

# chmod 0755 /usr/local/bin/

Install spamassassin using yum because postfix will cry

without it and it is not neccessary to start the daemon. We
will call spamassassin directly, this is for fastest
process as possible;
# yum -y install spamassassin

Add user & group spamassassin with uid/gid 106, this is for
security reasons;
# groupadd -g 106 spamassassin
# useradd -g 106 -u 106 spamassassin

Afterwards, we will start now the postfix mail server;

# service postfix start
# chkconfig ––level 2345 postfix on
If everything is done accordingly, postfix should be up and
running now and we need to test it;

First, we will generate an encoded base 64 string to be use

for smtp authentication;
# perl -MMIME::Base64 -e 'print

The above command is in the form of

"username\000username\000password" (\000 is a null byte and
\@ is a escape sequence for perl because perl interprets @
as an array. The output for this command is:


We can start the test now;

# telnet localhost 25
Checking the email in Squirrelmail, look at the mail
/etc/hosts – Plays an important part for your postfix mail
transport agent, it must be setup correctly. The above configuration file will work with /etc/hosts setup

# Do not remove the following line, or various programs

# that require network functionality will fail. mail localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6

Postfix should now working with the default spamassassin

rules. Our final step is to configure spamassassin to make
it smarter.

11. Spamassassin Configuration/Add-ons Installation and Configuration;

We need 2 terminals to accomplish this task. On first

terminal, we must switch to user “spamassassin” to be use
for testing. On the other terminal, we must stay as root to
do the compilation;

Download, compile and install DCC. Do it on the second

terminal with root user logged in;
# cd /usr/src
# wget -O –
| tar -zxf -
# cd dcc-1.3.105
# ./configure
# make
# make install
# chown -R spamassassin:spamassassin /var/dcc
# vi /etc/mail/spamassassin/v310.pre

Remove the comment “#”;

loadplugin Mail::SpamAssassin::Plugin::DCC

Switch on first terminal with “spamassassin” user;

# su – spamassassin
$ cdcc “delete″
$ crontab -e

0 5 * * * /var/dcc/libexec/cron-dccd

Download, compile & install Pyzor (on terminal 2);

# cd /usr/src
# wget -O –
-0.5.0.tar.bz2 | tar -jxf -
# cd pyzor-0.5.0
# python build
# python install

Switch to terminal 1;
$ pyzor discover

Download, compile & install Razor (on terminal 2);

# cd /usr/src/
# wget -O –
agents-2.84.tar.bz2 | tar -jxf -
# cd razor-agents-2.84
# perl Makefile.PL
# make
# make install
# cd ../
# wget -O –
agents-sdk-2.07.tar.bz2 | tar -jxf -
# cd razor-agents-sdk-2.07
# perl Makefile.PL
# make
# make install
Switch to terminal 1;
$ razor-admin -d -create
$ ls -la

This directories should be present;


Switch to terminal 2;
# vi /etc/mail/spamassassin/

# This is my required hits, change it according to

your requirements
required_hits 3.5

use_bayes 1
bayes_auto_learn 1
bayes_auto_learn 1
bayes_path /var/lib/spamassassin/bayes/bayes
bayes_file_mode 0666

use_razor2 1
use_pyzor 1

use_dcc 1
dcc_path /usr/local/bin/dccproc
dcc_body_max 999999
dcc_timeout 10
dcc_fuz1_max 999999
dcc_fuz2_max 999999
dcc_home /var/dcc

# mkdir /var/lib/spamassassin/bayes/
# touch /var/lib/spamassassin/bayes/bayes
# chown -R spamassassin:spamassassin

Test spamassassin on terminal 1;

$ spamassassin < /usr/share/doc/spamassassin-3.2.5/sample-
NOTE: Don’t forget to consult your log files if something
goes wrong or in any way your mail server is keep on
failing. It is a good practice to watch the logs while you
are configuring your system. In my case, I opened 2 ssh
sessions with PuTTY just for the log. On first session, I
execute the command:
# tail -f /var/log/messages

and on the other window:

# tail -f /var/log/maillog

I am so lazy to type those commands and I frequently use

them so, I added those commands in my .bashrc file.
# vi ~/.bashrc

# User specific aliases and functions

alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’
alias ls=’ls -Fa –color=always’
alias log=’tail -n 23 -f /var/log/messages’
alias maillog=’tail -n 23 -f /var/log/maillog’
Now, I can easily type “log” or “maillog” whenever I need

CONGRATULATIONS!!! You have now a complete and secured mail server.