Mail server with Postfix & dovecot

1) Install basic system : MTA Postfix & Dovecot mail server

Mail is sent to SMTP Postfix server on port 25.
Then Postfix delivers mail to Mailboxes via procmail.
Finaly users get their mail thanks to IMAP/POP3 Dovecot server through their mail client.

User authentication will be done on local server user database (/etc/passwd). It will use SASL mechanism for MTA and pam for IMAP/POP server.

Adjust directory /etc/skel in order to have mailboxes in Maildir

root@vradis:/etc/skel# ls -lFA
total 24
-rw-r--r-- 1 root root 220 Apr 10 2010 .bash_logout
-rw-r--r-- 1 root root 3085 Feb 2 15:38 .bashrc
-rwxr-xr-x 1 root root 4639 Feb 2 15:38 .dovecot.sieve*
drwxr-xr-x 6 root root 4096 Feb 2 15:47 Maildir/
-rw-r--r-- 1 root root 675 Apr 10 2010 .profile

File .dovecot.sieve will be created later in this document.
In Maildir you have

root@vradis:/etc/skel/Maildir# ls -lFA
total 16
drwxr-xr-x 2 root root 4096 Jan 30 11:28 cur/
drwxr-xr-x 5 root root 4096 Feb 2 15:45 .Junk/
drwxr-xr-x 2 root root 4096 Jan 30 11:28 new/
drwxr-xr-x 2 root root 4096 Jan 30 11:28 tmp/

If not, create these directories with the following command:

mkdir -p /etc/skel/Maildir/{cur,new,tmp,.Junk}

Packages needed for Postfix:

apt-get install postfix mailutils procmail

Add in /etc/postfix/

# Option pour la bal:
home_mailbox = Maildir/

# Options for SASL
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_authenticated_header = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =

# Options pour renforcer la sécurité

# Règles pour accepter ou refuser une connexion :
# - on attend une seconde (pour piéger les zombies) ;
# - on interdit la parallélisation là où il n'est pas sensé y en avoir.
smtpd_client_restrictions =
permit_mynetworks, permit_sasl_authenticated,
sleep 1, reject_unauth_pipelining

# Règles pour accepter ou refuser un message, dès lors qu'on connaît le nom
# de l'hôte de l'expéditeur (par sa commande HELO ou EHLO) :
# - on refuse les noms d'hôte invalides.
smtpd_helo_restrictions = reject_invalid_helo_hostname

# Règles pour accepter ou refuser un message, dès lors qu'on connaît l'adresse
# de l'expéditeur :
# - s'il vient d'un expéditeur inexistant de notre domaine, on le rejette ;
# - si le domaine de l'expéditeur n'a pas d'IP ou de MX, on le refuse ;
# - s'il vient d'un client sûr ou d'un client authentifié, on l'accepte ;
# - si l'adresse de l'expéditeur n'est pas sous forme canonique, on le refuse.
smtpd_sender_restrictions =
reject_unlisted_sender, reject_unknown_sender_domain,
permit_mynetworks, permit_sasl_authenticated,

# Règles pour accepter ou refuser un message, dès lors qu'on connaît le
# destinataire (par la commande RCPT TO) :
# - s'il est destiné à un expéditeur forgé chez nous, on le rejette ;
# - s'il est destiné à un domaine forgé, on le rejette ;
# - s'il vient d'un hôte sûr ou d'un client authentifié, on l'accepte ;
# - si l'adresse de destination n'est pas sous forme canonique, on le refuse ;
# - finalement, s'il n'est pas destiné à un domaine que l'on gère ou pour
# lequel on relaie, on le refuse.
smtpd_recipient_restrictions =
reject_unlisted_recipient, reject_unknown_recipient_domain,
permit_mynetworks, permit_sasl_authenticated,

Modify file to user home directory Maildir instead of standard debian /var/mail/$USER directory

mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=$HOME/Maildir/ MAILDIR=$HOME/Maildir

Change file /etc/postfix/ to enable SASL authentication

smtps inet n - - - - smtpd
# pour logguer
# smtps inet n - - - - smtpd -v
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes

Optionaly create file /etc/postfix/transport in case you are having trouble to send mail to some ISP

Add a line in file


Take into account transport file:

postmap /etc/postfix/transport
/etc/init.d/postfix restart

To get log about procmail, create fil /etc/procmailrc

#Uncomment below for troubleshooting

Now let’s install Dovecot

apt-get install dovecot-imapd dovecot-pop3d

Dovecot will authenticate users on local system. Check file /etc/pam.d/dovecot:


# @include common-auth
# @include common-account
# @include common-session
auth requisite shadow
account requisite

Configure dovecot v2 file /etc/Fdovecot.conf

# listen only IPv4 (line 26)
listen = *

# Greeting message for clients (line 31)
login_greeting = Dovecot vradis ready.

Configure dovecot v2 file /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = yes
auth_mechanisms = plain login

Configure dovecot v2 file /etc/dovecot/conf.d/auth-system.conf.ext

passdb {
driver = pam
args = session=yes dovecot
args = max_requests=100
args = failure_show_msg=yes

userdb {
driver = passwd

Configure dovecot v2 file /etc/dovecot/conf.d/10-logging.conf

log_path = /var/log/dovecot.log

# Pour debugguer
mail_debug = yes
verbose_ssl = yes

Configure dovecot v2 file /etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:~/Maildir

Dovecot upgrade generates error like:
Mar 31 16:53:53 imap(manu): Error: user manu: Initialization failed: namespace configuration error: inbox=yes namespace missing
Add the following lines to 10-mail.conf to solve this error:

namespace inbox {
inbox = yes

Configure dovecot v2 file /etc/dovecot/conf.d/10-master.conf

# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
group = postfix

Configure dovecot v2 file /etc/dovecot/conf.d/10-ssl.conf

ssl = yes
ssl_cert = /etc/ssl/certs/dovecot.pem
ssl_key = /etc/ssl/private/dovecot.pem

Test local connection to smtps and imaps, pop3s

openssl s_client -connect
openssl s_client -connect
openssl s_client -connect

Do not forget to open TCP ports 465, 993, 995 for client to server connection and port TCP 25 for communication betwenn servers.

Check your server is not an open relay:

In case you want to disable non SSL ports 110 and 143, put 0 to ports in file /etc/dovecot/conf.d/10-master.conf

service imap-login {
inet_listener imap {
# port = 143
port = 0
inet_listener imaps {
# port = 993

service pop3-login {
inet_listener pop3 {
#port = 110
port = 0
inet_listener pop3s {
#port = 995
#ssl = yes

2) Mail analysis, antispam & antivirus

Mail is sent to SMTP Postfix server on port 25.
Then Postfix calls Amavis proxy server on port 10024.
Amavis will run Clamav antivirus and Spamassassin antispam filter against each mail. After Amavis gives the mail back to Postfix on port 10025.
Then Postfix delivers mail to Mailboxes via procmail.
Finaly users get their mail thanks to IMAP/POP3 Dovecot server through their mail client.

Be carefull with clamav AV: it uses a lot of memory, I was not able to have it running on a PI Raspberry box.

First check you have your server correctly defined inie file /etc/hosts, run the following command that must return:

hostname --fqdn


Get needed packages

apt-get install amavisd-new unrar-free ripole arj cabextract zoo unrar bzip2 ...

There might be some warning at amavis start: cannot open `/etc/mailname’. Create this file and put in it

echo > /etc/mailname

Run command

postfix-add-filter amavis 10025

This command will apened the following lines to file

# Added using postfix-add-filter script:
amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o smtp_tls_note_starttls_offer=no inet n - - - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=
-o smtpd_milters=
-o local_recipient_maps=
-o relay_recipient_maps=

Rajouter dans le fichier /etc/amavis/conf.d/50-user:

$myhostname = "";
@local_domains_acl = ( "" );

Sothat all mail go through amavis, add this line to /etc/postfix/

content_filter = amavis:[]:10024

OR if you want only to filter incoming mail modify /etc/postfix/

# content_filter = amavis:[]:10024
smtpd_sender_restrictions =
check_sender_access regexp:/etc/postfix/sender_access_catchall,

And create file /etc/postfix/sender_access_catchall

/^/ FILTER amavis:[]:10024

Restart the all thing

/etc/init.d/amavis restart
/etc/init.d/postfix restart

Now filter software setup

apt-get install clamav clamav-daemon spamassassin razor pyzor
adduser clamav amavis

Uncomment in /etc/amavis/conf.d/15-content_filter_mode:

@bypass_virus_checks_maps = (
%bypass_virus_checks, @bypass_virus_checks_acl, $bypass_virus_checks_re);

In case you cannot load clamav AV, keep this line commented sothat it does not load it in memory.

Modify /etc/amavis/conf.d/20-debian_defaults

$final_virus_destiny = D_BOUNCE;

Spamassassin configuration, file /etc/default/spamassassin


Update spamassassin rules


File /etc/spamassassin/ should be like this

report_safe 0
lock_method flock

# Bayes-related operations
use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1
bayes_auto_expire 1
bayes_path /var/lib/amavis/.spamassassin/bayes
bayes_file_mode 0777

# External network tests
dns_available yes
skip_rbl_checks 0
use_razor2 1
use_pyzor 1

# Use URIBL (
urirhssub URIBL_BLACK A 2
body URIBL_BLACK eval:check_uridnsbl('URIBL_BLACK')
describe URIBL_BLACK Contains an URL listed in the URIBL blacklist
tflags URIBL_BLACK net
score URIBL_BLACK 3.0

urirhssub URIBL_GREY A 4
body URIBL_GREY eval:check_uridnsbl('URIBL_GREY')
describe URIBL_GREY Contains an URL listed in the URIBL greylist
tflags URIBL_GREY net
score URIBL_GREY 0.25

# Use SURBL (
urirhssub URIBL_JP_SURBL A 64
body URIBL_JP_SURBL eval:check_uridnsbl('URIBL_JP_SURBL')
describe URIBL_JP_SURBL Has URI in JP at
tflags URIBL_JP_SURBL net
score URIBL_JP_SURBL 3.0

Login as user amavis and configure razor and pyzor

su - amavis
razor-admin -d --create
razor-admin -register
razor-admin -discover
pyzor discover

In file /etc/amavis/conf.d/20-debian_defaults add

$sa_spam_subject_tag = '***SPAM*** ';
$sa_tag_level_deflt = undef;
$sa_tag2_level_deflt = 6.00;
$sa_kill_level_deflt = 6.00;
$final_banned_destiny = D_BOUNCE;
$final_spam_destiny = D_PASS;
$final_bad_header_destiny = D_PASS;

Uncomment in /etc/amavis/conf.d/15-content_filter_mode:

@bypass_spam_checks_maps = (
%bypass_spam_checks, @bypass_spam_checks_acl, $bypass_spam_checks_re);

Take this conf into account

/etc/init.d/clamav-daemon restart
/etc/init.d/amavis restart

Have a look in /var/log/ to see how amavis works, you must see:

Feb 1 15:29:20 vradis amavis[29354]: ANTI-VIRUS code loaded
Feb 1 15:29:20 vradis amavis[29354]: ANTI-SPAM code loaded
Feb 1 15:29:20 vradis amavis[29354]: ANTI-SPAM-SA code loaded
Feb 1 15:29:20 vradis amavis[29354]: Using primary internal av scanner code for ClamAV-clamd

4) Extra stuff

Use dovecot LDA instead of procmail, change file /etc/postfix/

mailbox_command = /usr/lib/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"
# mailbox_command = /usr/bin/procmail -a "$EXTENSION" DEFAULT=$HOME/Maildir/ MAILDIR=$HOME/Maildir

Add in file /etc/dovecot/conf.d/10-mail.conf

mail_plugins = $mail_plugins quota

Add in file /etc/dovecot/conf.d/20-imap.conf

mail_plugins = $mail_plugins quota imap_quota

Add in file /etc/dovecot/conf.d/15-lda.conf

mail_plugins = $mail_plugins sieve quota

Manage quota, edit file /etc/dovecot/conf.d/90-quota.conf

plugin {
quota_rule = *:storage=10M
quota_rule2 = Trash:storage=+10M
plugin {
quota_warning = storage=80%% quota-warning 80 %u
quota_warning2 = storage=50%% quota-warning 50 %u
plugin {
#quota = dirsize:User quota
quota = maildir:User quota
#quota = dict:User quota::proxy::quota
#quota = fs:User quota

Install Sieve needed packages to sort mails

apt-get install dovecot-sieve dovecot-managesieved

Check file /etc/dovecot/copnf.d/90-sieve.conf

plugin {
# The path to the user's main active script.
sieve = ~/.dovecot.sieve
# Directory for :personal include scripts for the include extension.
sieve_dir = ~/sieve

Change file /etc/dovecot/conf.d/20-managesieve.conf

service managesieve-login {
inet_listener sieve {
port = 4190

Simple sample script that will put all SPAM messages in Junk folder. Put it in /home/$USER/.dovecot.sieve

require "fileinto";
if exists "X-Spam-Flag" {
if header :contains "X-Spam-Flag" "NO" {
} else {
fileinto "Junk";

5) Install Roundcube webmail

Needed packages

apt-get install roundcube roundcube-plugins roundcube-plugins-extra

Configure roundcube to meet your requirements, file /etc/roundcube/

$rcmail_config['default_host'] = '';
$rcmail_config['smtp_server'] = '';

Copy file /usr/share/roundcube/plugins/managesieve/ in /etc/roundcube/plugins/managesieve/

cp /usr/share/roundcube/plugins/managesieve/ /etc/roundcube/plugins/managesieve/

Modify /etc/roundcube/plugins/managesieve/ to meet your needs

$rcmail_config['managesieve_port'] = 4190;
$rcmail_config['managesieve_usetls'] = true;

Edit file /etc/roundcube/ and declare plugins

$rcmail_config['plugins'] = array('jqueryui', 'password', 'managesieve');

Finaly make a symlink like this:

ln -s /usr/share/roundcube /var/www/mail

Leave a Reply