====== Replace Courier with Dovecot plus Database quota ======
This is a forked version from the original article here (http://isp-control.net/documentation/howto:mail:replace_courier_with_dovecot) because the dovecot versions 1.2 and newer bring important improvements but it's still not in every distribution (it's already on lenny-backports and squeeze tough)
It describes how to replace the courier-pop/imap/authdaemon/maildrop with dovecot.
===== The improvements from the original document =====
* Quotas are stored on database so they will be shown from the control panel
* Required dovecot version is now 1.2 (almost everything could be done in 1.1 but with 1.2 it's easier and cleaner)
* Filtering is enabled by default
* Following the installation is easier now.
===== Introduction =====
What do you win by changing from courier to dovecot:
* You can do server-side filtering with sieve (for example saving spam to junk folder)
* Reading your logs for problems will be easier
* Having custom setups is simpler due to the dovecot config files
* All the data is taken from the database, so everything is immediate and you don't rely on scripts
* You can block users after they are exceeding their quotas.
* Dovecot is really fast and reliable
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, as a bonus you will see the current values.
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. Create a new table in ispcp called quota_dovecot ====
This will create also the database to store quota
mysql -u root -p mysql
mysql> USE ispcp;
mysql> CREATE TABLE quota_dovecot (
username varchar(100) not null,
bytes bigint not null default 0,
messages integer not null default 0,
primary key (username)
);
==== 2. Add sql user ====
mysql -u root -p mysql
mysql> GRANT SELECT ON ispcp.* to 'ispcp_dovecot'@'localhost' identified by 'PASS_MAILRW';
mysql> GRANT SELECT,INSERT,UPDATE ON ispcp.quota_dovecot to 'ispcp_dovecot'@'localhost'
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
#Uncomment if using ssl
#protocols = imap pop3 imaps pop3s
disable_plaintext_auth = no
listen=*
syslog_facility = mail
login_greeting = Dovecot ready.
mail_location = maildir:%h
mail_privileged_group = mail
#Uncomment these lines to enable dovecot ssl support
#Dovecot 1.2+ (i.e *BSD ports, lenny backport or squeeze)
ssl = yes
#
#Certificate location
#ssl_cert_file = /etc/ssl/certs/servername.crt
#ssl_key_file = /etc/ssl/certs/servername.key
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
}
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 don't want to save quota occupation in a database, you should comment 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
#Uncomment this if you are using managesieve or per-user rules
#sieve = ~/sieve/.dovecot.sieve
#sieve_dir = ~/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';
Create the file used to store the quotas on the db
**/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
}
Create the sieve script to redirect spam to junk folder
**/etc/dovecot/sieve/dovecot.sieve**
If you have a spam filter such as amavis, it will add the header "X-Spam-Flag = yes", with this little sieve all this mail will go to Junk folder in webmail. Very practical because all the users can check their own spam without the need of the server admin.
mkdir /etc/dovecot/sieve
chown -R vmail:mail /etc/dovecot/sieve/
touch /etc/dovecot/sieve/dovecot.sieve
require "fileinto";
if exists "X-Spam-Flag" {
if header :contains "X-Spam-Flag" "NO" {
} else {
fileinto "INBOX.Junk";
stop;
}
}
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 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.
Otherwise, you have to uncomment the appropiate lines in dovecot.conf:
protocols = imap pop3 imaps pop3s
#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 ===
You can follow the tutorial here to get a certificate that you can use also for apache, postfix, etc.
http://isp-control.net/documentation/doku.php?id=howto:security:ssl_made_easy
==== 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 =====
==== Use domain alias as mail alias too ====
Making a small change in postfix configuration, we can use the domain alias as a mail ailas.
Being example2.com an alias of example1.com, whenever I create a mailbox in example1.com the same mailbox in example2.com becomes a redirection.
So creating admin@example1.com will also receive the mail from admin@example2.com automatically.
/etc/postfix/mysql_virtual_domains.cf
user = ispcp_dovecot
password = PASS_MAILRW
hosts = 127.0.0.1
dbname = ispcp
query = (SELECT domain_name FROM domain_aliasses
INNER JOIN domain ON domain_aliasses.domain_id=domain.domain_id
WHERE domain.domain_status='ok'
AND domain.domain_mailacc_limit > '-1'
AND domain_aliasses.alias_name='%s')
UNION
(SELECT domain_name FROM domain
WHERE domain.domain_status='ok'
AND domain.domain_mailacc_limit > '-1'
AND domain_name='%s')
/etc/postfix/mysql_virtual_forwards.cf
user = ispcp_dovecot
password = PASS_MAILRW
hosts = 127.0.0.1
dbname = ispcp
query =
SELECT DISTINCT CONCAT(CONCAT(mail_users.mail_acc, "@"), domain.domain_name) from mail_users
INNER JOIN domain ON mail_users.domain_id = domain.domain_id
INNER JOIN domain_aliasses ON domain.domain_id = domain_aliasses.domain_id
WHERE domain_aliasses.alias_name = '%d' AND mail_users.mail_acc = '%u'
==== 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