Virtual Users And Domains With Postfix, Courier, MySQL And SquirrelMail (Ubuntu 10.04) - Page 3

9 Install amavisd-new, SpamAssassin, And ClamAV

To install amavisd-new, spamassassin and clamav, run the following command:

aptitude install amavisd-new spamassassin clamav clamav-daemon zoo unzip bzip2 libnet-ph-perl libnet-snpp-perl libnet-telnet-perl nomarch lzop pax

Because this command installs AppArmor again as a dependency, we must disable it again:

/etc/init.d/apparmor stop
update-rc.d -f apparmor remove
aptitude remove apparmor apparmor-utils

Afterwards we must configure amavisd-new. The configuration is split up in various files which reside in the /etc/amavis/conf.d directory. Take a look at each of them to become familiar with the configuration. Most settings are fine, however we must modify three files:

First we must enable ClamAV and SpamAssassin in /etc/amavis/conf.d/15-content_filter_mode by uncommenting the @bypass_virus_checks_maps and the @bypass_spam_checks_maps lines:

vi /etc/amavis/conf.d/15-content_filter_mode

The file should look like this:

use strict;

# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.

# Default antivirus checking mode
# Please note, that anti-virus checking is DISABLED by
# default.
# If You wish to enable it, please uncomment the following lines:

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

# Default SPAM checking mode
# Please note, that anti-spam checking is DISABLED by
# default.
# If You wish to enable it, please uncomment the following lines:

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

1;  # ensure a defined return

And then you should take a look at the spam settings and the actions for spam-/virus-mails in /etc/amavis/conf.d/20-debian_defaults. There's no need to change anything if the default settings are ok for you. The file contains many explanations so there's no need to explain the settings here:

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

$QUARANTINEDIR = "$MYHOME/virusmails";
$quarantine_subdir_levels = 1; # enable quarantine dir hashing

$log_recip_templ = undef;    # disable by-recipient level-0 log entries
$DO_SYSLOG = 1;              # log via syslogd (preferred)
$syslog_ident = 'amavis';    # syslog ident tag, prepended to all messages
$syslog_facility = 'mail';
$syslog_priority = 'debug';  # switch to info to drop debug output, etc

$enable_db = 1;              # enable use of BerkeleyDB/libdb (SNMP and nanny)
$enable_global_cache = 1;    # enable use of libdb-based cache if $enable_db=1

$inet_socket_port = 10024;   # default listening socket

$sa_spam_subject_tag = '***SPAM*** ';
$sa_tag_level_deflt  = 2.0;  # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.31; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 6.31; # triggers spam evasive actions
$sa_dsn_cutoff_level = 10;   # spam level beyond which a DSN is not sent
$final_virus_destiny      = D_DISCARD;  # (data not lost, see virus quarantine)
$final_banned_destiny     = D_BOUNCE;   # D_REJECT when front-end MTA
$final_spam_destiny       = D_BOUNCE;
$final_bad_header_destiny = D_PASS;     # False-positive prone (for spam)

Finally, edit /etc/amavis/conf.d/50-user and add the line $pax='pax'; in the middle:

vi /etc/amavis/conf.d/50-user

use strict;

# Place your configuration directives here.  They will override those in
# earlier files.
# See /usr/share/doc/amavisd-new/ for documentation and examples of
# the directives you can use in this file


#------------ Do not modify anything below this line -------------
1;  # ensure a defined return

Afterwards, run these commands to add the clamav user to the amavis group and to restart amavisd-new and ClamAV:

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

Now we have to configure Postfix to pipe incoming email through amavisd-new:

postconf -e 'content_filter = amavis:[]:10024'
postconf -e 'receive_override_options = no_address_mappings'

Afterwards append the following lines to /etc/postfix/

vi /etc/postfix/

amavis unix - - - - 2 smtp
        -o smtp_data_done_timeout=1200
        -o smtp_send_xforward_command=yes inet 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 mynetworks=
        -o strict_rfc821_envelopes=yes
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_bind_address=

Then restart Postfix:

/etc/init.d/postfix restart

Now run

netstat -tap

and you should see Postfix (master) listening on port 25 (smtp) and 10025, and amavisd-new on port 10024:

root@server1:/etc/courier# netstat -tap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 *:mysql                 *:*                     LISTEN      17431/mysqld
tcp        0      0 *:www                   *:*                     LISTEN      3543/apache2
tcp        0      0 *:ssh                   *:*                     LISTEN      532/sshd
tcp        0      0 *:smtp                  *:*                     LISTEN      21581/master
tcp        0      0 localhost.localdo:10024 *:*                     LISTEN      20454/amavisd (mast
tcp        0      0 localhost.localdo:10025 *:*                     LISTEN      21581/master
tcp        0     52      ESTABLISHED 624/0
tcp6       0      0 [::]:pop3               [::]:*                  LISTEN      17891/couriertcpd
tcp6       0      0 [::]:imap2              [::]:*                  LISTEN      17831/couriertcpd
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN      532/sshd
tcp6       0      0 [::]:imaps              [::]:*                  LISTEN      17864/couriertcpd
tcp6       0      0 [::]:pop3s              [::]:*                  LISTEN      17924/couriertcpd


10 Install Razor, Pyzor And DCC And Configure SpamAssassin

Razor, Pyzor and DCC are spamfilters that use a collaborative filtering network. To install Razor and Pyzor, run

aptitude install razor pyzor

DCC isn't available in the Ubuntu 10.04 repositories, so we install it as follows:

cd /tmp
tar xzvf dcc-dccproc.tar.Z
cd dcc-dccproc-1.3.126
./configure --with-uid=amavis
make install
chown -R amavis:amavis /var/dcc
ln -s /var/dcc/libexec/dccifd /usr/local/bin/dccifd

Now we have to tell SpamAssassin to use these three programs. Edit /etc/spamassassin/ and add the following lines to it:

vi /etc/spamassassin/

use_dcc 1
dcc_path /usr/local/bin/dccproc

use_pyzor 1
pyzor_path /usr/bin/pyzor

use_razor2 1
razor_config /etc/razor/razor-agent.conf

use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1

Then we must enable the DCC plugin in SpamAssassin. Open /etc/spamassassin/v310.pre and uncomment the loadplugin Mail::SpamAssassin::Plugin::DCC line:

vi /etc/spamassassin/v310.pre

# DCC - perform DCC message checks.
# DCC is disabled here because it is not open source.  See the DCC
# license for more details.
loadplugin Mail::SpamAssassin::Plugin::DCC

You can check your SpamAssassin configuration by executing:

spamassassin --lint

It shouldn't show any errors.

Restart amavisd-new afterwards:

/etc/init.d/amavis restart

Now we update our SpamAssassin rulesets as follows:

sa-update --no-gpg

We create a cron job so that the rulesets will be updated regularly. Run

crontab -e

to open the cron job editor. Create the following cron job:

23 4 */2 * * /usr/bin/sa-update --no-gpg &> /dev/null

This will update the rulesets every second day at 4.23h.


11 Quota Exceedance Notifications

If you want to get notifications about all the email accounts that are over quota, then create the file /usr/local/sbin/quota_notify:

cd /usr/local/sbin/
vi quota_notify

#!/usr/bin/perl -w

# Author <>
# This script assumes that virtual_mailbox_base in defined
# in postfix's file. This directory is assumed to contain
# directories which themselves contain your virtual user's maildirs.
# For example:
# -----------/
#            |
#            |
#    home/vmail/domains/
#        |          |
#        |          |
#                   |
#                   |
#           -----------------
#           |       |       |
#           |       |       |
#         user1/   user2/  user3/
#                           |
#                           |
#                        maildirsize

use strict;

my $POSTFIX_CF = "/etc/postfix/";
my $MAILPROG = "/usr/sbin/sendmail -t";
my @POSTMASTERS = ('postmaster@domain.tld');
my $CONAME = 'My Company';
my $COADDR = 'postmaster@domain.tld';
my $SUADDR = 'postmaster@domain.tld';
my $MAIL_REPORT = 1;

#get virtual mailbox base from postfix config
open(PCF, "< $POSTFIX_CF") or die $!;
my $mboxBase;
while (<PCF>) {
   next unless /virtual_mailbox_base\s*=\s*(.*)\s*/;
   $mboxBase = $1;

#assume one level of subdirectories for domain names
my @domains;
opendir(DIR, $mboxBase) or die $!;
while (defined(my $name = readdir(DIR))) {
   next if $name =~ /^\.\.?$/;        #skip '.' and '..'
   next unless (-d "$mboxBase/$name");
   push(@domains, $name);
#iterate through domains for username/maildirsize files
my @users;
foreach my $domain (@domains) {
        opendir(DIR, $domain) or die $!;
        while (defined(my $name = readdir(DIR))) {
           next if $name =~ /^\.\.?$/;        #skip '.' and '..'
           next unless (-d "$domain/$name");
      push(@users, {"$name\@$domain" => "$mboxBase/$domain/$name"});

#get user quotas and percent used
my (%lusers, $report);
foreach my $href (@users) {
   foreach my $user (keys %$href) {
      my $quotafile = "$href->{$user}/maildirsize";
      next unless (-f $quotafile);
      open(QF, "< $quotafile") or die $!;
      my ($firstln, $quota, $used);
      while (<QF>) {
         my $line = $_;
              if (! $firstln) {
                 $firstln = 1;
                 die "Error: corrupt quotafile $quotafile"
                    unless ($line =~ /^(\d+)S/);
                 $quota = $1;
            last if (! $quota);
         die "Error: corrupt quotafile $quotafile"
            unless ($line =~ /\s*(-?\d+)/);
         $used += $1;
      next if (! $used);
      my $percent = int($used / $quota * 100);
      $lusers{$user} = $percent unless not $percent;

#send a report to the postmasters
   open(MAIL, "| $MAILPROG");
   map {print "To: $_\n"} @POSTMASTERS;
   print "From: $COADDR\n";
   print "Subject: Daily Quota Report.\n";
   print "DAILY QUOTA REPORT:\n\n";
   print "----------------------------------------------\n";
   print "| % USAGE |            ACCOUNT NAME          |\n";
   print "----------------------------------------------\n";
   foreach my $luser ( sort { $lusers{$b} <=> $lusers{$a} } keys %lusers ) {
      printf("|   %3d   | %32s |\n", $lusers{$luser}, $luser);
      print "---------------------------------------------\n";
        print "\n--\n";
        print "$CONAME\n";

#email a warning to people over quota
        foreach my $luser (keys (%lusers)) {
           next unless $lusers{$luser} >= $WARNPERCENT;       # skip those under quota
           open(MAIL, "| $MAILPROG");
           print "To: $luser\n";
      map {print "BCC: $_\n"} @POSTMASTERS;
           print "From: $SUADDR\n";
           print "Subject: WARNING: Your mailbox is $lusers{$luser}% full.\n";
           print "Reply-to: $SUADDR\n";
           print "Your mailbox: $luser is $lusers{$luser}% full.\n\n";
           print "Once your e-mail box has exceeded your monthly storage quota\n";
      print "your monthly billing will be automatically adjusted.\n";
      print "Please consider deleting e-mail and emptying your trash folder to clear some space.\n\n";
           print "Contact <$SUADDR> for further assistance.\n\n";
           print "Thank You.\n\n";
           print "--\n";
           print "$CONAME\n";

Make sure that you adjust the variables at the top (especially the postmaster@domain.tld email address).

We must make the file executable:

chmod 755 quota_notify


crontab -e

to create a cron job for that script:

0 0 * * * /usr/local/sbin/quota_notify &> /dev/null
Share this page:

33 Comment(s)

Add comment


From: Rick Stanley at: 2010-06-10 23:59:47

I wish people would stop tagging every posting with Ubuntu! Most of the postings involved with the installation and configuration of software I have seen tagged with "Ubuntu" can also be done with MANY different Distros, including this one! You would think that there is only ONE Distro available! NOT!!!

Take a look at the top ten Distributions: DistroWatch

From: Anonymous at: 2010-08-11 16:37:17

Did you not notice that distro-specific how-to's are what's created here for some topics? Calm down. This article, and in fact no post on this site claims Ubuntu is the end-all of linux.

From: Mohamed Elsayed at: 2010-11-02 12:36:10

Dear Falko:

 many thanks for this great effort; actually I have installed my mail server before based on Christoph Haas tutorial at it was very helpful, and works 100%.

but for my need, there was something missing which is the mailing lists; I wanted to integrate mailman or any of mailing list management SW to be able to create mailing lists (for example and add the sales users to this list.

it will be perfect if you could complete this part in your great  tutorial which is (as I think) is very important for a many people.

I sent a comment like this to Christoph Haas on and I noticed that another people also were interested to add this feature to their implementation. 


thanks again for you and I hope you can find a time to complete it soon.


From: at: 2011-01-24 02:48:07

you could use the forward table, create a user and add all the emails to it

example: create user

and add  the users


and etc, this would be all done in the sql table forwards

I would use phpadmin much easier

From: at: 2011-09-20 07:20:56

I follow this,and the tables like this:

mysql> select * from forwardings;
| source           | destination                      |
|     |                 |
| |, |
 then i sent a email to, only test usr can receive this email. but when i sent a email to a invalid user,eric user can receive a email.

Anyone can help me?


From: Trapper at: 2010-10-04 17:24:49

I note that when creating the 6 text files in postfix for mysql parsing that there's a line:

password = mail_admin_password

Is it to be left as is or is the actual password to be used?

I also note the same circumstances with other files later in the howto.

From: Anonymous at: 2010-10-16 03:49:48

It should be replaced with your actual password, in those 6 files and everywhere else.

From: Jaac at: 2011-01-26 10:48:35

And be sure it does not contains any invalid characters like # which will comment out the rest of the line. Because that will get you into troubles with the configuration and give you a hard time locating the source of the problem.

Having the password in between single quotes will probably work, like 'your#Pa$$w0rd'. But i just avoided the problem by not using certain characters.

From: Anonymous at: 2011-02-12 04:30:01

Please make sure that /etc/mysql/my.cnf contains the following line:

vi /etc/mysql/my.cnf

# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address =
#bind-address           =   Is this line shoud be unable comment? 

From: blueday at: 2011-12-06 10:46:17


 I folowed your guide, all works ok. However, there is a nasty bug somewhere.

 If you create let;s say and set a password domain99 it's possible to get autentificated with passwords like, domain, domain12 etc. Basically, if you put anything in the password field starting wirh domain, you get autentificated.

 Can anyone reproduce this issue?

 Thank you,

From: at: 2012-02-02 06:47:47

Note: If you want to use your domain also as a virtual Domain, than 'mydestination' should be only 'localhost, localhost.localdomain'

postconf -e 'mydestination=, localhost, localhost.localdomain'

From: undifined at: 2010-08-30 12:42:58

 for amavis-d:

it is important to order  the /etc/hosts file, the important parts are: ipv6 before ipv4, fqdn before shortname

 # The following lines are desirable for IPv6 capable hosts

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

ff02::3 ip6-allhosts

::1 localhost6.localdomain6 localhost6 localhost.localdomain localhost ip6-localhost ip6-loopback localhost.localdomain localhost

From: Markofealing at: 2010-06-19 17:05:15

Great tutorial however I've seem to have fallen at the last fence!

When I try to login to my e-mail account using SquirrelMail I'm getting the error message "ERROR: Connection dropped by IMAP server." When I type in sales@training.lan.

If I type in an invalid e-mail address I see waiting for before I get the "unknown user or password incorrect" message, which is what I would expect because the account does not exist. The connection dropped message suggests that the account is validated but then SquirrelMail falls-over!

From: at: 2010-06-24 07:51:42

Usually it happens because the Maildir for that email does not exist.

Have you send greeting email for that account?

From: Anonymous at: 2010-06-26 12:58:53

Sure..! Very useful document for Linux Newbie administrator like me, however, i am getting the similar error,

ERROR: Connection dropped by IMAP server.

I followed the steps as explained. Instead of using the user sales i used a new one, following similar steps as for the user sales.

However, i can not log in.

Will you please assist? 

From: Anonymous at: 2010-06-27 22:44:41

Hello, I received the same error.

Anyway, great HOWTO, gotta thank You a lot.

Please, if someone figured it out, let us know.

Thank You once again

From: cejohnsonsr at: 2010-10-04 01:06:46

I saw this error 1 time. I sent a welcome message to the account & the next attempt to login produced a blank page. Does anyone have any idea why this might happen? No matter what account I try to login to, I always get a blank page.



From: johnny at: 2011-03-10 17:20:42

Well after going through this walk through a few times and still getting errors on the particular server I'm using, particularly the Connection Dropped by IMAP when logging into squirrel mail and trouble creating mailboxes under /home/vmail and msc other errors.

 I decided to try a Dovecot setup instead of Courier and have this setup working now. After installing Squirrel mail by itself after the mail setup I still had the Error connection dropped from Squirrel mail and after numerous file checks disabled the sql_pass from Squirrel mail as 1 user suggested and got Squirrel mail up then to fix the final errors displaying in the left side nav column I edited the following:

 /etc/squirrelmail/config_local.php and added the following to the end of the file which I believe had the opening <?php tag but was missing the closing one.

 nano or vim  /etc/squirrelmail/config_local.php


The tutorial I located on the Dovecot setup is located at the link below and I noticed the author even took the time to set up an automated install script which was much appreciated and worked great aside from the fact the password regex patterns were older and did not account for symbols in the password. The links are below, First is to the tutorial, second to the automated install script, Enjoy ;-)

 Full Tutorial ::

Automated Install ::

From: kunci at: 2010-10-08 08:02:11


You must insert the

mailbox_transport = virtual

row in the  /etc/postfix/ and delete or insert # the mailbox_command = procmail -a …. line:

vi /etc/postfox/
# mailbox_command = procmail -a...
mailbox_transport = virtual

From: Anonymous at: 2010-07-20 22:36:18

Al work i can send mail but i can not receive mail. any suggestions?


Oh, about the above two. you must make a dir it's in de tutorial you must first send one mail so the dirs wil be created.

From: toopaq at: 2010-08-04 11:01:31

Why do you need the samba package? I suppose for encrypting passwords but not sure.

From: Anonymous at: 2010-07-27 06:06:22

Hi, i have followed the tutorial, and succesfull to login to squirrel and also can send email to another mail server

but when i try to send email from another server to this ubuntu mail server, still the inbox in squirrel is empty, i've tried to use outlook as well but no luck.

i see the mail.log of postfix/local status is sent and delivered to mailboxes..

any idea? thanx a lot


From: at: 2010-08-07 21:25:42


Ive used your tutorials before (couple of years back) and they rock! Luckily i have more experience these days. In any case, i followed it exactly and used patience and common sense. Everything works splendid, i've just sent out my first mail to a gmail address and vice versa, and both emails arrived fast.

To reply on some comments below, even if you buy/rent a domain and forward it correctly, e.g.

domain.tld MX 10

If your using a home server on your home ISP, they might be blocking the incoming or outgoing ports. Some ISP's even block both. In that case you can have problems with the mails arriving. Do some research about your specific ISP and their mail server policy.

 Also you should definitely check out the logs on your server (e.g. using: tail -f):

  • /var/log/system.log

  • /var/log/mail.log

  • /var/log/mysql.log

  • /var/log/apache2/access.log

Using a server (dedicated/private) at a hosting company usually saves a lot of headaches but your going to have to pay. In some cases you could also choose to pay for a mail forwarding/redirection service which is cheaper.

Hope that helps!

From: Anonymous at: 2010-11-15 16:30:28

thanks, mailbox_transport = virtual really helped ;)

From: Mike at: 2010-11-07 02:17:36

This is a very good and straightforward tutorial. I have spent hours trying to solve this one though. From the mail.log:

 Nov  7 11:43:02 tbpl postfix/proxymap[1626]: warning: connect to mysql server Access denied for user 'mail_admin'@'localhost' to database 'maildb'
Nov  7 11:43:02 tbpl postfix/proxymap[1626]: warning: connect to mysql server Access denied for user 'mail_admin'@'localhost' to database 'maildb'
Nov  7 11:43:02 tbpl postfix/trivial-rewrite[1665]: fatal: proxy:mysql:/etc/postfix/,lock|fold_fix): table lookup problem
Nov  7 11:43:03 tbpl postfix/smtpd[1628]: warning: problem talking to service rewrite: Success
Nov  7 11:43:03 tbpl postfix/smtpd[1624]: warning: problem talking to service rewrite: Connection reset by peer
Nov  7 11:43:03 tbpl postfix/master[1418]: warning: process /usr/lib/postfix/trivial-rewrite pid 1665 exit status 1
Nov  7 11:43:03 tbpl postfix/master[1418]: warning: /usr/lib/postfix/trivial-rewrite: bad command startup -- throttling


maildb is the correct name, I changed it from mail in the installation.


I can't work out what I doing wrong. Any help appreciated.



From: at: 2010-11-14 05:50:58

My fault for not reading properly!!! I went back to scratch and built the basic server according to Falko BEFORE doing this install and all worked fine. Excellent Tutorial.

 Mike, Australia

From: bob at: 2011-03-04 07:34:47

i have a problem with squirrelmail.. when i try to login, i got this error

ERROR: Connection dropped by IMAP server.

how to solve this problem.


From: Talgat at: 2011-03-28 04:34:14

Thanks for helpful tutorial, but I have 1 problem. When I trying to get mail by POP3 i have authentication error. In mail.log I can see that:

 Mar 28 04:20:15 mail pop3d: LOGIN FAILED,, ip=[::ffff:]
Mar 28 04:20:20 mail pop3d: Disconnected, ip=[::ffff:]

Please, Help me!

From: at: 2011-09-17 15:50:04

An script (based on this tutorial) to automate the entire installation for postfix-courier SquirrelMail. 3 minutes for install process. You find this script at (post #10)

From: Anonymous at: 2011-10-19 13:07:02

I have a problem with adding users and domains. I added sales@domain.tld. ( form the tutorial ) and it works just fine, but if I add another domain or another email address, I cannot login.

 I restarted the postfix and the mysql and the courier-imap... but still the same problem.

I am getting this error:


ERROR: Connection dropped by IMAP server.


Can somebody help me?

From: at: 2012-03-09 23:47:06

This is because domain name is in two places at time, as real and virtual, and it will not work like that.

Edit /etc/postfix/ and remove Your domain name from "mydestination" .

Then restart postfix.

From: Anonymous at: 2012-04-13 10:24:39

Thanks a lot for your tutorial, clear and simple to follow.

From: Alex at: 2012-12-04 10:23:37

Just tried your setup and it's really good. Also in last installation step I changed Squirrelmail to RoundCube which is less difficult in configuration and looks much better.
There were no changes to the entire setup except when you started installing Squirrel - I started installing RoundCube. It also has password change plugin and mysql authorization that are enabled in config file.