Table of Contents

Replace Courier with Dovecot

This HowTo describes how to replace the courier-pop/imap/authdaemon/maildrop with the according services.

IMPORTANT: There is another (newer) version of this document for the people who can use dovecot 1.2 and adds improvements specially in quota management. http://isp-control.net/documentation/howto:mail:replace_courier_with_dovecot_plus_database_quota

Please report any bugs/hints/whatever in the following board thread: http://www.isp-control.net/forum/thread-6088-post-49018.html

NOTE: ispCP is already assigning 10MB quota to each mail account created, but currently it is not editable by default (ticket #2219). To be able to edit the quota from the control panel you will have to follow this thread: http://www.isp-control.net/forum/thread-8483.html

NOTE: If you want to edit the quota directly; it is stored in bytes in the table “mail_users” in a field named “quota”.

Prerequisites

Your system's hostname has to be resolvable

You can check this by executing

hostname

This should print your system's hostname.

Script for password verification

Somewhere in between rc6 and 1.0.0 password encryption was added and so passwords in clear text are no longer working. Grab the perl script written by sci2tech that handles the verification of passwords for Dovecot: http://www.isp-control.net/forum/attachment.php?aid=1185

Copy it to /var/www/ispcp/engine/ispcp-dovecot-mngr and do a

 chmod 0755 /var/www/ispcp/engine/ispcp-dovecot-mngr

Replace Courier with Dovecot

Please replace every appearance of “PASS_MAILRW” with your password!

1. Add sql user

mysql -u root -p mysql
mysql> GRANT SELECT ON ispcp.* to 'ispcp_dovecot'@'localhost' identified by 'PASS_MAILRW';
mysql> FLUSH PRIVILEGES;
mysql> quit;

2. Stop Courier services

/etc/init.d/courier-pop stop
/etc/init.d/courier-imap stop
/etc/init.d/courier-authdaemon stop
/etc/init.d/saslauthd stop

3. Install Dovecot

apt-get update
apt-get install dovecot-common dovecot-imapd dovecot-pop3d

4. Configure Dovecot

Replace /etc/dovecot/dovecot.conf with the following one (you should backup the original because there are a lot of comments in it explaining all the configuration parameters).

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.org

Then save this content as your /etc/dovecot/dovecot.conf

base_dir = /var/run/dovecot/
protocols = imap pop3
disable_plaintext_auth = no
listen=*

syslog_facility = mail

login_greeting = Dovecot ready.

mail_location = maildir:%h
mail_privileged_group = mail

protocol imap {
  mail_plugins = quota imap_quota
}

namespace private {
 prefix = INBOX.
 inbox = yes
}

protocol pop3 {
 pop3_uidl_format = %u-%v
 mail_plugins = quota
}

protocol lda {
 postmaster_address = postmaster@yourdomain.tld
 auth_socket_path = /var/run/dovecot/auth-master
 mail_plugins = quota

 #Sieve filtering support uncomment to enable (dovecot <= 1.1)
 #mail_plugins = quota cmusieve
 #global_script_path = /etc/dovecot/sieve/dovecot.sieve
}

auth default {
 mechanisms = plain login
 passdb checkpassword {
  args = /var/www/ispcp/engine/ispcp-dovecot-mngr
 }
 userdb sql {
  args = /etc/dovecot/dovecot-sql-domain.conf
 }
 userdb sql {
   args = /etc/dovecot/dovecot-sql-aliasdomain.conf
 }

 userdb sql {
  args = /etc/dovecot/dovecot-sql-subdomain.conf
 }

 socket listen {
  client {
   path = /var/spool/postfix/private/auth
   mode = 0660
   user = postfix
   group = postfix
  }

  master {
   path = /var/run/dovecot/auth-master
   mode = 0660
   user = vmail
   group = mail
  }
 }

 user = root
}

#If you want to save quota occupation in a database, you should uncomment this:
#dict {
#  quotadict = mysql:/etc/dovecot/dovecot-dict-sql.conf
#}

plugin {
  #Enable sieve for everybody (in dovecot >= 1.2 it is configured here)
  #global_script_path = /etc/dovecot/sieve/dovecot.sieve
  #Enable per-user quota
  #OPTION A: Using per user maildir files (no database)
  #quota = maildir:User quota
  #OPTION B: Using per user database quota (can be read from ispCP)
  #quota = dict:user::proxy::quotadict
  #quota_rule = *:bytes=1G
}

Create a new file /etc/dovecot/dovecot-sql-domain.conf with the following content:
NOTE: In the SQL query for user_query there are uids and gids 'hardcoded'. The uid must be the uid of your vmail user and gid the gid of the mail group. Maybe you have to change the defaults (1001/8))

driver = mysql
connect = host=localhost dbname=ispcp user=ispcp_dovecot password=PASS_MAILRW
user_query = SELECT CONCAT('/var/mail/virtual/', domain.domain_name, '/',mail_acc) AS home, '1001' AS uid, '8' AS gid, CONCAT('maildir:storage=', FLOOR(quota/1024)) AS quota FROM mail_users INNER JOIN domain ON mail_users.domain_id = domain.domain_id WHERE mail_acc='%n' and domain.domain_name='%d' AND (mail_type='normal_mail' OR mail_type='normal_mail,normal_forward');

# Use this for Dovecot 1.1+
# user_query = SELECT CONCAT('/var/mail/virtual/', domain.domain_name, '/',mail_acc) AS home, '1001' AS uid, '8' AS gid, CONCAT('*:bytes=',quota,'B') AS quota_rule FROM mail_users INNER JOIN domain ON mail_users.domain_id = domain.domain_id WHERE mail_acc='%n' AND domain.domain_name='%d' AND (mail_type='normal_mail' OR mail_type='normal_mail,normal_forward');

#Use this if you don't want quota
# user_query = SELECT CONCAT('/var/mail/virtual/', domain.domain_name, '/',mail_acc) AS home, '1001' AS uid, '8' AS gid FROM mail_users INNER JOIN domain ON mail_users.domain_id = domain.domain_id WHERE mail_acc='%n' AND domain.domain_name='%d' AND (mail_type='normal_mail' OR mail_type='normal_mail,normal_forward');

Create a new file /etc/dovecot/dovecot-sql-subdomain.conf with the following content:
(In the sql for user_query there are uids and gids 'hardcoded'. The uid must be the uid of vmail user and gid the gid of the mail group. Maybe you have to change the defaults (1001/8))

driver = mysql
connect = host=localhost dbname=ispcp user=ispcp_dovecot password=PASS_MAILRW
user_query = SELECT CONCAT('/var/mail/virtual/', subdomain.subdomain_name, ".", domain.domain_name, '/',mail_acc) AS home, '1001' AS uid, '8' AS gid FROM (mail_users INNER JOIN subdomain ON mail_users.sub_id = subdomain.subdomain_id) INNER JOIN domain ON mail_users.domain_id = domain.domain_id WHERE mail_acc='%n' and concat(subdomain.subdomain_name,".",domain.domain_name)='%d';

Create a new file /etc/dovecot/dovecot-sql-aliasdomain.conf with the following content:
(In the sql for user_query there are uids and gids 'hardcoded'. The uid must be the uid of vmail user and gid the gid of the mail group. Maybe you have to change the defaults (1001/8))

driver = mysql
connect = host=localhost dbname=ispcp user=ispcp_dovecot password=PASS_MAILRW
user_query = SELECT concat('/var/mail/virtual/', domain_aliasses.alias_name, '/',mail_acc) as home, '1001' as uid, '8' as gid FROM (mail_users INNER JOIN domain_aliasses ON mail_users.sub_id = domain_aliasses.alias_id) INNER JOIN domain ON mail_users.domain_id = domain.domain_id WHERE mail_acc='%n' and domain_aliasses.alias_name ='%d';

Set correct permissions for dovecot.conf (the deliver command accesses this file too)

chmod 0644 /etc/dovecot/dovecot.conf

5. Configure Postfix

Change parameters in /etc/postfix/main.cf:

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
#smtpd_sasl2_auth_enable = yes
smtpd_sasl_security_options = noanonymous
#smtpd_sasl_local_domain =
broken_sasl_auth_clients = yes

virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

Add the following line to /etc/postfix/master.cf:

for Debian Etch use

dovecot unix - n n - - pipe
  flags=DROhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

for Debian Lenny (dovecot >= 1.0.15)

dovecot unix - n n - - pipe
  flags=DROhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient} -s

for *BSD dovecot from port

dovecot unix - n n - - pipe
  flags=DROhu user=vmail:mail argv=/usr/local/libexec/dovecot/deliver -f ${sender} -d ${recipient} -s

for CentOS it should be something like this:

dovecot unix - n n - - pipe
  flags=DROhu user=vmail:mail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

6. Migrate existing maildirs

If you are using existing maildirs which were accessed by courier you have to migrate the maildirs. This can be easily done with the courier-dovecot-migrate.pl script from http://wiki.dovecot.org/Migration/Courier Be sure to pick the one that corresponds with your Dovecot version.

7. Enable SSL support

If you don't want SSL support you can skip this step. Change/add the following lines to /etc/dovecot/dovecot.conf:

protocols = imap pop3 imaps pop3s
# Enable Dovecot's SSL support
#Dovecot <= 1.1
#ssl_disable = no
#For *BSD from port
#ssl = no
#
#Dovecot 1.2+ (i.e *BSD ports)
#ssl = yes
#
#Certificate location
#ssl_cert_file = /etc/ssl/certs/servername.crt
#ssl_key_file = /etc/ssl/certs/servername.key

Generate your SSL certificates

openssl req -new -x509 -days 365 -nodes -out /etc/ssl/certs/dovecot.pem -keyout /etc/ssl/private/dovecot.pem

The script will ask you a few questions, here an example:

Country Name (2 letter code) [AU]: ''CH''\\
State or Province Name (full name) [Some-State]: ''Zurich''\\
Locality Name (eg, city) []: ''Esslingen''\\
Organization Name (eg, company) [Internet Widgits Pty Ltd]: ''My Hosting Company''\\
Organizational Unit Name (eg, section) []: ''Dovecot Secure Mailservice''\\
Common Name (eg, YOUR name) []: ''mail.domain.tld'' -> this should be equal to the servername you use for connect to the server...\\
Email Address []: ''hostmaster@domain.tld''\\

8. Start services

/etc/init.d/dovecot start
/etc/init.d/postfix restart

9. Test the whole thing and remove Courier

If everything works as expected you can remove Courier. Remove all startup links.

update-rc.d -f courier-imap remove
update-rc.d -f courier-pop remove
update-rc.d -f courier-authdaemon remove
update-rc.d -f saslauthd remove

Remove all courier packages.

apt-get remove courier-base courier-authdaemon courier-maildrop

Don't forget to disable makeuserdb and Courier services:

In file /etc/ispcp/ispcp.conf:

Old values (Debian):

CMD_MAKEUSERDB = /usr/sbin/makeuserdb
CMD_AUTHD = /etc/init.d/courier-authdaemon
CMD_IMAP = /etc/init.d/courier-imap
CMD_IMAP_SSL = /etc/init.d/courier-imap-ssl
CMD_POP = /etc/init.d/courier-pop
CMD_POP_SSL = /etc/init.d/courier-pop-ssl

New values:

CMD_MAKEUSERDB = /bin/true
CMD_AUTHD = /bin/true
CMD_IMAP = /bin/true
CMD_IMAP_SSL = /bin/true
CMD_POP = /bin/true
CMD_POP_SSL = /bin/true

As Dovecot reads users directly out of the database, there's no need to restart it if something changes, but ispCP needs something to execute which returns an exit code of 0. That's why we use /bin/true which always return 0.

10. That's it

You have successfully replaced Courier with Dovecot. The next steps are optional.

Optional features

Enabling Sieve filtering support

Uncomment the Sieve lines in lda section from dovecot.conf and create a file in /etc/dovecot/sieve/dovecot.sieve with this content:

require "fileinto";
if exists "X-Spam-Flag" {
        fileinto "Junk";
        stop;
}

Chown to the appropiate user

chown -R vmail:mail /etc/dovecot/sieve/

Then all the mails tagged with X-Spam-Flag = yes in the headers will go to Junk folder in webmail. Very practical because all the users can check their own spam.

Saving Dovecot quota on MySQL

By doing this you will have your quota usage stored in the database. This can be used for really useful stuff. For example you can warn your mail users when they are approaching their maximum quota and you can also use this mod (http://isp-control.net/forum/thread-8483.html) to show mail space occupation in realtime.

Create /etc/dovecot/dovecot-dict-sql.conf:

# v1.2+ only:
connect = host=localhost dbname=ispcp user=ispcp_dovecot password=PASS_MAILRW
map {
  pattern = priv/quota/storage
  table = quota_dovecot
  username_field = username
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = quota_dovecot
  username_field = username
  value_field = messages
}

You will need another table in ispcp database:

USE ispcp;
CREATE TABLE quota_dovecot (
  username varchar(100) not null,
  bytes bigint not null default 0,
  messages integer not null default 0,
  primary key (username)
);

Grant permissions to quota_dovecot table for ispcp_dovecot user
GRANT SELECT,INSERT,UPDATE ON ispcp.quota_dovecot to 'ispcp_dovecot'@'localhost';
FLUSH PRIVILEGES;

Automatically alert user if his quota exceeds a critical limit

You can configure Dovecot to execute an external command if an user's quota exceeds a specified limit. In this example the user receives alert emails if his quota exceeds 80% / 95% percent.

Append the following to your plugin section in /etc/dovecot.conf:

quota_warning = storage=95%% /usr/local/bin/dovecot-quota-warning.sh 95
quota_warning2 = storage=80%% /usr/local/bin/dovecot-quota-warning.sh 80

If the user's quota reaches the limit the external script dovecot-quota-warning.sh is run. If you define quota warnings make sure that you start with the highest limit because Dovecot only runs the command for the first limit that is exceeded.

Create /usr/local/bin/dovecot-quota-warning.sh

#!/bin/sh
PERCENT=$1
cat << EOF | /usr/lib/dovecot/deliver -d $USER -c /etc/dovecot/dovecot-no-quota-warning.conf
From: postmaster@yourdomain.tld
To: $USER
Subject: quota warning
Content-Type: text/plain; charset="UTF-8"

Attention! The emails in your mailbox are using more than $PERCENT% of your total mail space.
EOF

Create /etc/dovecot/dovecot-no-quota-warning.conf
This is basically the same file as dovecot.conf but the quota rules are stripped out in order to avoid looping. You can strip the quota lines manually or let it grep do for you:

grep -v "quota" dovecot.conf > dovecot-no-quota-warning.conf

At last set correct permissions to dovecot-no-quota-warning.conf

chmod 0644 /etc/dovecot/dovecot-no-quota-warning.conf

For more information about this have a look at http://wiki.dovecot.org/Quota/1.1