BenV's notes

Qmail + vpopmail + Dovecot and Sieve

by on Dec.07, 2009, under Software

Let’s start with a problem description. We start out with a -working- mailer:
A pretty simple qmail/vpopmail installation with Courier IMAP and the pop3d that comes with qmail. This is administered by users with the qmailadmin frontend and allows for creation of mailboxes and forwards by postmasters. Together with spamdyke and spamassassin it works pretty well. So why change it?

The problem: First of all, Courier is a piece of shit. The various parts of it have broken in various ways over the years (authd hanging for no apparent reason or suddenly eating a ton of memory, stuff like that). Not only that, but they decided that vpopmail wasn’t worth supporting anymore, so their latest release of courier-authlib simply doesn’t handle vpopmail anymore. (don’t ask me why, can’t find any details on it).
Second of all, it would be cool to give our users the ability to create their own custom mail filters on our server. Stuff that you can do in thunderbird or through webmail, so they can setup their mailbox filters and vacation messages and whatever without me having to help them. (well…. we’ll see about that). Needless to say we could do that by giving them access to the .qmail files, but those are way out of their league. Not only that, it would be a security nightmare. So to solve that, we’re trying the Sieve disaster. I mean language… or something.

Getting rid of Courier is really simple. Simply pull the harddisk out of your server and shake it a few times, then step on it and throw it out of the window (while still standing on top of it of course). If you did it properly you should now be wondering why the hell you follow instructions without thinking. However, if you do have a brain, you might want to shutdown the courier-imap* and pop* services and remove them from your disk. Tada.
Personally I replaced the pop, imap and auth services with Dovecot. If you’re running qmail like you’re supposed to this is pretty easy. Check out this page by John Simpson for details on that. Instructions for vpopmail included. (thanks again John!)

Now for the interesting part. Getting Sieve to work. I decided to get the latest shiny version from their hg repository, but feel free to take the latest stable version instead.

root@black:/usr/src/dovecot-sieve$ hg clone dovecot-1.2-sieve-hg
*clone meets clone*
root@black:/usr/src/dovecot-sieve$ cd dovecot-1.2-sieve-hg
root@black:/usr/src/dovecot-sieve/dovecot-1.2-sieve-hg$ ./
*skip that if you are using the stable version*
root@black:/usr/src/dovecot-sieve/dovecot-1.2-sieve-hg$ ./configure --prefix=/usr --with-dovecot=/usr/src/dovecot-1.2.8
root@black:/usr/src/dovecot-sieve/dovecot-1.2-sieve-hg$ make ; mkdir pkg ; make DESTDIR=`pwd`/pkg install ; cd pkg ; makepkg /usr/src/packages/dovecot-sieve-i386-1.tgz

Now we still need to enable it. Make sure your /etc/dovecot.conf has a section like this:

## Local Delivery Agent stuff
protocol lda {
postmaster_address =
hostname =
sendmail_path = /var/qmail/bin/sendmail
mail_plugins = sieve

log_path = /var/log/dovecot-deliver-errors.log
info_log_path = /var/log/dovecot-deliver.log
auth default {
# Your other garbage options here ....
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0660
user = vpopmail
group = vchkpw
plugin {
sieve = ~/.sieve/dovecot.sieve
sieve_dir = ~/.sieve
sieve_global_dir = /etc/dovecot/sieve/
sieve_subaddress_sep = -+

Easy. This should make the /usr/libexec/dovecot/deliver program able to verify the account information of a requested user against the vpopmail database and it instructs the local delivery part to use the sieve plugin. (which I’ve configured some paths for).
However, next part literally took me hours to figure out. I wanted to use the Dovecot LDA only for my test email account. So I created a .qmail file for my user – according to their wiki :

root@black$ echo '|/var/qmail/bin/preline -f /usr/local/libexec/dovecot/deliver -d $EXT@$USER' > ~vpopmail/domains/
root@black$ chown vpopmail:vchkpw ~vpopmail/domains/

According to their wiki, this should be the correct way to invoke the deliver program. So I send a test mail to …. nothing happens. Nothing in logs, nothing.
Oh that’s a lie, the error log says:

deliver( Info: Loading modules from directory: /usr/lib/dovecot/lda
deliver( Info: Module loaded: /usr/lib/dovecot/lda/

Of course it doesn’t work yet, I haven’t put a sieve filter in place yet. So I put a simple reject filter there so I know it works when it does 😉
This is the contents of a file ~vpopmail/domains/ Corresponding with the dovecot.conf plugin settings.

require ["reject"];

reject "If you're getting this reject... it works. Also, your mom wears combat boots!";

I send another mail. Same stuff in the logs. Mhm… more debugging would be great guys. I have no idea if it loads a sieve filter, from what directory or if it does anything at all! GRRRr.
After a lot of cursing and throwing with plants and cats and hammers, I went through the mailing archives from the John’s qmail-patch list and found a snippet from someone else that set up something similar. Apparently the way to invoke the deliver program is different. Because I use the qmail extension addresses, was given as user. However, vpopmail only knows about, so it failed. Blegh.
So for now I decided to use the solution offered by the mailinglist:

| DTLINE=${DTLINE/$USER-} /var/qmail/bin/preline -f /usr/libexec/dovecot/deliver -d ${EXT/-*}@$USER -a $EXT@$USER

A little explanation on the environment variables. Normally when I send a message to they look like this:


The DTLINE rewrite isn’t strictly necessary but looks a bit nicer in the logs. However, the EXT@USER part should not contain all the extensions since they won’t resolve to a vpopmail user.
With the rewritten .qmail file I send another test email. Here’s the log:

deliver( Info: Loading modules from directory: /usr/lib/dovecot/lda
deliver( Info: Module loaded: /usr/lib/dovecot/lda/
deliver( Info: auth input: uid=89
deliver( Info: auth input: gid=89
deliver( Info: auth input: home=/home/vpopmail/domains/
deliver( Info: Namespace: type=private, prefix=INBOX., sep=., inbox=yes, hidden=no, list=1, subscriptions=yes
deliver( Info: maildir: data=/home/vpopmail/domains/
deliver( Info: maildir++: root=/home/vpopmail/domains/, index=, control=, inbox=/home/vpopmail/domains/
deliver( Info: sieve: using sieve path for user's script: /home/vpopmail/domains/
deliver( Info: sieve: opening script /home/vpopmail/domains/
deliver( Info: sieve: executing compiled script /home/vpopmail/domains/
deliver( Info: sieve: msgid=<>: rejected message from (reject)

Woohoo, it rejected! 😉
So Sieve works. Next thing to do is to get ManageSieve up and running and test it with thunderbird and some sieve addons
But that’s a rant for later, my eyes are collapsing.

:, ,

3 Comments for this entry

  • roberto67

    Thanks for the guide, benv. At the end I suppose you wanted to let all users and virtualdomains use sieve rules. In that case, as you know, you had to edit qmail/control/defauldelivery but unfortunately the .qmail-default in the vpopmail/domain directory overwrites this file so that is necessary to clean .qmail-default in each domain, which is nuisance.
    Any idea on how to overcome this?

  • BenV

    Hej roberto67, thanks for your comment. Did you manage to find a solution yet? Getting rid of the .qmail-default files can be done with a single find command, but I’m not sure if that’s a smart thing to do.

    I haven’t changed my own server to use sieve by default yet, but when I do I’ll come back on this.

  • roberto67

    not yet, BenV. I also suggest not to store the aliases on mysql (–disable-valias when compiling vpopmail), otherwise it’s not possible to create aliases with qmailadmin.
    Enabling sieve rules is convenient also because users can completely manage their accounts from within a webmail (roundcube for instance).

1 Trackback or Pingback for this entry

Leave a Reply

You must be logged in to post a comment.


  • 2018 (1)
  • 2016 (1)
  • 2015 (7)
  • 2014 (4)
  • 2013 (11)
  • 2012 (27)
  • 2011 (26)
  • 2010 (25)
  • 2009 (68)