Personal wiki of Goran Jurić



This article is outdated. Updated version on building a mail server on Debian 6 is published as a free eBook here.

To achieve automatic moving of messages to the Junk folder we will have to use Maildrop instead of the Postix local delivery agent. This, on the other hand, has some drawbacks. When we tell Postix to use Maildrop as a local delivery agent, we will have to create Maildirs for new mailboxes by hand every time we create a new email account. But do not worry, this step can be automated.

To install maildrop, run

apt-get install maildrop

Maildrop config file is located at /etc/maildroprc, open it and replace the content with:

# Global maildrop filter file (used on Debian)
# For use with Postfix/Courier IMAP/Amavisd-new virtual mailbox domains.
# This maildroprc automagically creates a Spam folder for the recipient
# and places spam there. It also subscibes the recipient to the folder.
# Example maildir: /home/vmail/
# Also in
# virtual_transport = maildrop
# maildrop_destination_concurrency_limit = 2
# maildrop_destination_recipient_limit = 1
# and in
# maildrop  unix  -       n       n       -       -       pipe
#  flags=DRhu user=vmail:vmail argv=/usr/bin/maildrop -w 90 -d ${user}@${nexthop}
#  ${extension} ${recipient} ${user} ${nexthop}
# /var/log/maildroprc.log needs to exist and owned by vmail:vmail and
# a logrotate script needs to be created.
logfile "/var/log/maildroprc.log"
# Check if host and user directory exist
`test -e $HOME_DIR/$HOST/$USER`
#log "Testing for $HOME_DIR/$HOST subdirectory: result=$RETURNCODE"
# Only continue if directory does NOT exist
if ($RETURNCODE != 0)
        log "MailDir $HOME_DIR/$HOST/$USER does NOT exist"
        `test -e $HOME_DIR/$HOST`
        if ( $RETURNCODE != 0 )
                log "Creating $HOME_DIR/$HOST"
                `mkdir $HOME_DIR/$HOST`
                `chmod -R 0700 $HOME_DIR/$HOST`
        # Create users MailDir
        `maildirmake $HOME_DIR/$HOST/$USER`
if (/^X-Spam-Flag: YES/)
        EXTENSION = "Junk"
        # See if the spam directory already exists
        `test -e $HOME_DIR/$HOST/$USER/.$EXTENSION`
        #log "Testing for $EXTENSION subdirectory: result=$RETURNCODE"
        if ( $RETURNCODE != 0 ) # spam directory does not exist - so we create it
                # Create the subdirectory
                `maildirmake -f $EXTENSION $HOME_DIR/$HOST/$USER`
                log "Ran \"maildirmake -f $EXTENSION $HOME_DIR/$HOST/$USER\""
                # Auto-subscribe the subdirectory
                `if ! grep -q INBOX.$EXTENSION $HOME_DIR/$HOST/$USER/courierimapsubscribed; then echo INBOX.$EXTENSION >> $HOME_DIR/$HOST/$USER/courierimapsubscribed; fi`
        # Deliver the message to the mailbox
        exception {
                # for those who unsubscribed themselves - subscribe them
                `if ! grep -q INBOX.$EXTENSION $HOME_DIR/$HOST/$USER/courierimapsubscribed; then echo INBOX.$EXTENSION >> $HOME_DIR/$HOST/$USER/courierimapsubscribed; fi`
                to "$HOME_DIR/$HOST/$USER/.$EXTENSION"

This script is a modified version of the script I took from and it does two things:

  1. Creates the folders for the users mail on the server if they do not exist (this is the part that Postfix virtual delivery agent does automatically)
  2. Checks if the messages has the X-Spam-Flag: YES header and delivers the message to the Junk folder (it creates one if it doesn't exist)

Create the log file, and change ownership:

touch /var/log/maildroprc.log
chown vmail:vmail /var/log/maildroprc.log

To automatically rotate logs for the maildroprc.log file create /etc/logrotate.d/maildroprc and paste this:

/var/log/maildroprc.log {
    rotate 7

Edit /etc/postfix/ and add

virtual_transport = maildrop
maildrop_destination_concurrency_limit = 2
maildrop_destination_recipient_limit = 1

Note: you already have virtual_transport = virtual, you have to replace this line and change virtual to maildrop.

Edit /etc/postfix/ and look for

maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}

and replace it with

maildrop  unix  -       n       n       -       -       pipe
  flags=ODRhu user=vmail:vmail argv=/usr/bin/maildrop -w 90 -d ${user}@${nexthop}
  ${extension} ${recipient} ${user} ${nexthop}

As you can see we are invoking maildrop as user:group “vmail:vmail”. Maildrop on Debian is compiled against the courier-authlib library which need access to the /var/run/courier/authdaemon folder. Debian package sets user/group permission to daemon:daemon on this folder. To force maildrop to work when invoked as vmail:vmail we need to change the group ownership of this folder to vmail.

chgrp vmail /var/run/courier/authdaemon

A quote from the courier-users mailing list by Gordon Messmer:

See the NOTE in the first section of the INSTALL document:


When using the standalone maildrop build with courier-authlib, one of the following configurations must be used:

* Your mail server must invoke maildrop as the root user (the -d flag reads the mail account's uid and gid, then drops root) .
* Manually change the permissions on the maildrop binary to be setuid root.
* Manually change the permissions on the courier-authlib's socket directory (/usr/local/var/spool/authdaemon by default) to be globally readable or executable.

The default permissions on courier-authlib's socket directory blocks world-access to the filesystem socket connected to courier-authlib's authentication daemon process. In order for maildrop to connect to the authentication   library, maildrop must either have root privileges (which will be temporary, as soon as maildrop determines the account's userid and groupid, it will drop root, before reading the maildroprc file), or courier-authlib's socket directory must have world read and execute permission.

Note that if the permissions on the socket directory are changed, anyone on the system can connect and obtain any account's password!

It is the system administrator's responsibility to choose the appropriate security policy when using the Courier Authentication Library.

This line invokes maildrop with some parameters. -w 90 tells maildrop to copy the quota warning message if the user is over 90% of his mailbox quota.

The quota warning message must be located in /etc/quotawarnmsg and it should look something like this:

X-Comment: Rename/Copy this file to quotawarnmsg, and make appropriate changes
X-Comment: See deliverquota man page for more information
From: Mail Delivery System <>
To: Valued Customer:;
Subject: Mail quota warning
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

Your mailbox on the server is now more than 90% full. So that you can continue to receive mail you need to remove some messages from your mailbox.

Todo: I don't get the body off the message, everything is in the headers, need to check this one out.

Unfortunately Postfix Admin does not allow entering quota values, but id does create the needed columns in the database table mbox. To enter quota values log into mysql and add the quota value for the mailbox you wish to have quota applied. Your mailbox should have something like this:

mysql> select * from mailbox;
| username        | password | name        | maildir            | quota     | local_part | domain       | created             | modified            | active |
| | ommited  | Goran Juric |  | 100000000 | mail       |  | 2009-04-14 00:53:38 | 2009-04-14 00:53:38 |      1 |

Maildrop will get quota information using Couriers /etc/courier/authmysqlrc settings. Rhat is the reason why we have added

MYSQL_QUOTA_FIELD concat(quota,'S')

in that config file.

Change the permissions on /var/lib/amavis/tmp

chmod -R 775 /var/lib/amavis/tmp

After configuration Amavis needs to be restarted:

/etc/init.d/amavis restart

Restart Postfix:

/etc/init.d/postfix restart

Send a test email to check that everything is working.

Per user filtering

If you would like to have the ability to provide per user filtering you will have to modify /etc/maildroprc to

  1. check if there is a “mailfilter” file in the users directory
  2. include the file

Note: you can use some other file name if you like

You can change it to look like this:

        # Create users MailDir
        `maildirmake $HOME_DIR/$HOST/$USER`
`test -e $DEFAULT/mailfilter`
if ( $RETURNCODE == 0 )
     exception {
         log "Including $HOME_DIR/$HOST/$USER/mailfilter..."
         include "$HOME_DIR/$HOST/$USER/mailfilter"
if (/^X-Spam-Flag: YES/)

All you have to do now is to put your rules in the mailfilter file.

debian/maildrop.txt · Last modified: 2015/03/13 23:29 (external edit)