Difference between revisions of "Virtual user mail system"

From ArchWiki
Jump to: navigation, search
(propose merge with Postfix)
m (add ja link)
 
(103 intermediate revisions by 24 users not shown)
Line 1: Line 1:
[[Category:Mail Server]]
+
[[Category:Mail server]]
{{merge|Postfix|both articles cover the exact same setup}}
+
[[ja:仮想ユーザーメールシステム]]
This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary. Roughly, the components used in this article are Postfix, Dovecot, PostfixAdmin and Roundcube.
+
{{Related articles start}}
 +
{{Related|Courier MTA}}
 +
{{Related|OpenDKIM}}
 +
{{Related|Postfix}}
 +
{{Related|SOGo}}
 +
{{Related articles end}}
 +
This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary.  
 +
 
 +
Roughly, the components used in this article are Postfix as the mail server, Dovecot as the IMAP server, Roundcube as the webmail interface and PostfixAdmin as the administration interface to manage it all.
  
 
In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!
 
In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!
 
This article assumes that you have a working [[LAMP]] setup as we will need a working Apache2 as well as MYSQL database. Of course, with a few changes to these instructions you could easily use another httpd and database. For the purposes of this tutorial, however, the choice made above will be used. Additionally, the article assumes all-default settings for every package installed below. No changes except for those mentioned will be required.
 
 
Should any unforeseen problems occur, feel free to use the discussion page to voice your problems and I will try to answer.
 
  
 
== Installation ==
 
== Installation ==
# pacman -S dovecot postfix
+
Before you start, you must have both a working MySQL server as described in [[MySQL]] and a working Postfix server as described in [[Postfix]].
 +
 
 +
[[Install]] the {{Pkg|dovecot}} and {{Pkg|roundcubemail}} packages.
  
 
== Configuration ==
 
== Configuration ==
 
=== User ===
 
=== User ===
 
For security reasons, a new user should be created to store the mails:
 
For security reasons, a new user should be created to store the mails:
  groupadd -g 5000 vmail
+
  # groupadd -g 5000 vmail
  useradd -u 5000 -g vmail -s /sbin/nologin -d /home/vmail -m vmail
+
  # useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail
A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in '''/home/vmail'''. You could change the home dir to something like '''/var/mail/vmail''' but careful to change this in any configuration below as well.
+
A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in {{ic|/home/vmail}}. You could change the home directory to something like {{ic|/var/mail/vmail}} but be careful to change this in any configuration below as well.
  
 
=== Database ===
 
=== Database ===
You will need to create an empty database and corresponding user. We will be using PostfixAdmin's tables to fill the database later on. In this article, ''postfix_user'' will have read/write access to ''postfix_db'' using ''hunter2'' for a password. You are expected to create your database and user yourself as shown in the following code. Make sure to assign proper permissions.
+
You will need to create an empty database and corresponding user. In this article, the user ''postfix_user'' will have read/write access to the database ''postfix_db'' using ''hunter2'' as password. You are expected to create the database and user yourself, and give the user permission to use the database, as shown in the following code.
  
{{hc|$> mysql -u root -p|password:}}
+
{{hc|$ mysql -u root -p|
{{bc|
+
CREATE DATABASE postfix_db;
CREATE SCHEMA `postfix_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
+
GRANT ALL ON postfix_db.* TO 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
CREATE USER 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
+
FLUSH PRIVILEGES;
GRANT ALL ON `postfix_db`.* TO `postfix_user`@`localhost`;
+
 
}}
 
}}
 +
 +
{{Expansion|Further manual database installation is missing. So far, the only way to follow this article is by installing PostfixAdmin with Apache, MySQL and PHP.}}
 +
 +
Now you can go to the PostfixAdmin's setup page, let PostfixAdmin create the needed tables and create the users in there.
 +
 +
==== PostfixAdmin ====
 +
See [[Postfix#PostfixAdmin]].
 +
 +
=== SSL certificate ===
 +
You will need a SSL certificate for all encrypted mail communications (SMTPS/IMAPS/POP3S). If you do not have one, create one:
 +
# cd /etc/ssl/private/
 +
# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout vmail.key -out vmail.crt -days 1460 #days are optional
 +
# chmod 400 vmail.key
 +
# chmod 444 vmail.crt
  
 
=== Postfix ===
 
=== Postfix ===
There are basically 2 ways for of doing SMTPS.
 
  
One is using the wrapper mode which enables even old/odd clients like Outlook to use TLS. The wrapper mode uses the system service "smtps" which is a non-standard service and runs on port 465.
+
==== SMTPS ====
  
The other, more proper method is to use a port that simply enforces TLS without any wrapping. The system service for this is "submission" which is standard and uses port 587.
+
Enable secure SMTP as described in [[Postfix#Secure SMTP]].  
  
For the improper variant uncomment this in {{ic|/etc/postfix/master.cf}}:
+
==== Prerequisites ====
smtps    inet  n      -      n      -      -      smtpd
+
  -o smtpd_tls_wrappermode=yes
+
  -o smtpd_sasl_auth_enable=yes
+
  
And verify that these lines are in {{ic|/etc/services}}:
+
Before you copy&paste the configuration below, check if {{ic|relay_domains}} has already been already set. If you leave more than one active, you will receive warnings during runtime.
smtps 465/tcp # Secure SMTP
+
smtps 465/udp # Secure SMTP
+
  
otherwise posfix won't start :
+
{{Warning|{{ic|<nowiki>relay_domains</nowiki>}} can be dangerous. You usually do not want Postfix to forward mail of strangers. {{ic|<nowiki>$mydestination</nowiki>}} is a sane default value. Double check it's value before running postfix! See http://www.postfix.org/BASIC_CONFIGURATION_README.html#relay_to}}
  
''postfix/master[5309]: fatal: 0.0.0.0:smtps: Servname not supported for ai_socktype''
+
Also check if your SSL certificate paths are set right in all upcoming config examples.
  
For the proper variant uncomment this in {{ic|/etc/postfix/master.cf}}:
+
==== Setting up Postfix ====
smtp    inet  n      -      n      -      -      smtpd
+
submission    inet  n      -      n      -      -      smtpd
+
  -o smtpd_tls_security_level=encrypt
+
  -o smtpd_sasl_auth_enable=yes
+
  
 
To {{ic|/etc/postfix/main.cf}} append:
 
To {{ic|/etc/postfix/main.cf}} append:
  relay_domains = *
+
  relay_domains = $mydestination
 
  virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
 
  virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
  virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_domains_maps.cf
+
  virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_mailbox_domains.cf
 
  virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf
 
  virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf
 
  virtual_mailbox_base = /home/vmail
 
  virtual_mailbox_base = /home/vmail
Line 77: Line 86:
 
  smtpd_sasl_security_options = noanonymous
 
  smtpd_sasl_security_options = noanonymous
 
  smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
 
  smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
 +
smtpd_tls_security_level = may
 
  smtpd_tls_auth_only = yes
 
  smtpd_tls_auth_only = yes
  smtpd_tls_cert_file = /etc/ssl/private/server.crt
+
smtpd_tls_received_header = yes
  smtpd_tls_key_file = /etc/ssl/private/server.key
+
  smtpd_tls_cert_file = /etc/ssl/private/vmail.crt
 +
  smtpd_tls_key_file = /etc/ssl/private/vmail.key
 
  smtpd_sasl_local_domain = $mydomain
 
  smtpd_sasl_local_domain = $mydomain
 
  broken_sasl_auth_clients = yes
 
  broken_sasl_auth_clients = yes
 
  smtpd_tls_loglevel = 1
 
  smtpd_tls_loglevel = 1
  
{{Warning|{{ic|<nowiki>relay_domains = *</nowiki>}} might me a bad idear (see http://www.postfix.org/BASIC_CONFIGURATION_README.html#relay_to). You usually do not want postfix to forward mail from strangers.}}  
+
* In the configuration above {{ic|virtual_mailbox_domains}} is a list of the domains that you want to receive mail for. This CANNOT contain the domain that is set in {{ic|mydestination}}. That is why we left {{ic|mydestination}} to be localhost only.
  
This references a lot of files that do not even exist yet. Let's create them.
+
* {{ic|virtual_mailbox_maps}} will contain the information of virtual users and their mailbox locations. We are using a hash file to store the more permanent maps, and these will then override the forwards in the MySQL database.
  
Edit {{ic|/etc/postfix/virtual_alias_maps.cf}} as new and add:
+
* {{ic|virtual_mailbox_base}} is the base directory where the virtual mailboxes will be stored.
user = postfix_user
+
password = hunter2
+
hosts = localhost
+
dbname = postfix_db
+
query = SELECT goto FROM alias WHERE address='%s' AND active = true
+
  
Edit {{ic|/etc/postfix/virtual_domains_maps.cf}} as new and add:
+
The {{ic|virtual_uid_maps}} and {{ic|virtual_gid_maps}} are the real system user IDs that the virtual mails will be owned by. This is for storage purposes.
user = postfix_user
+
password = hunter2
+
hosts = localhost
+
dbname = postfix_db
+
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = false AND active = true
+
  
Edit {{ic|/etc/postfix/virtual_mailbox_limits.cf}} as new and add:
+
{{note|Since we will be using a web interface (Roundcube), and do not want people accessing this by any other means, we will be creating this account later without providing any login access.}}
user = postfix_user
+
password = hunter2
+
hosts = localhost
+
dbname = postfix_db
+
query = SELECT quota FROM mailbox WHERE username='%s'
+
  
Edit {{ic|/etc/postfix/virtual_mailbox_maps.cf}} as new and add:
+
==== Create the file structure ====
user = postfix_user
+
password = hunter2
+
hosts = localhost
+
dbname = postfix_db
+
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true
+
  
Run ''postmap'' on ''transport'' to generate its db:
+
Those new additional settings reference a lot of files that do not even exist yet. We will create them with the following steps.
postmap /etc/postfix/transport
+
  
We still need the SSL cert and private key:
+
If you were setting up your database with PostfixAdmin and created the database schema through PostfixAdmin, you can create the following files. Do not forget to change the password:
cd /etc/ssl/certs
+
 
openssl req -new -x509 -newkey rsa:1024 -days 365 -keyout server.key -out server.crt
+
{{hc|/etc/postfix/virtual_alias_maps.cf|<nowiki>
openssl rsa -in server.key -out server.key
+
user = postfix_user
chown nobody:nobody server.key server.crt
+
password = hunter2
chmod 400 server.key
+
hosts = localhost
chmod 444 server.crt
+
dbname = postfix_db
mv server.key /etc/ssl/private/
+
table = alias
  mv server.crt /etc/ssl/private/
+
select_field = goto
 +
where_field = address
 +
</nowiki>}}
 +
 
 +
{{hc|/etc/postfix/virtual_mailbox_domains.cf|<nowiki>
 +
user = postfix_user
 +
password = hunter2
 +
hosts = localhost
 +
dbname = postfix_db
 +
table = domain
 +
select_field = domain
 +
where_field = domain
 +
</nowiki>}}
 +
 
 +
{{hc|/etc/postfix/virtual_mailbox_maps.cf|<nowiki>
 +
user = postfix_user
 +
password = hunter2
 +
hosts = localhost
 +
dbname = postfix_db
 +
table = mailbox
 +
select_field = maildir
 +
where_field = username
 +
</nowiki>}}
 +
 
 +
{{Note | For setups without using PostfixAdmin, create the following files.}}
 +
 
 +
{{hc|/etc/postfix/virtual_alias_maps.cf|<nowiki>
 +
user = postfix_user
 +
password = hunter2
 +
hosts = localhost
 +
dbname = postfix_db
 +
table = domains
 +
select_field = virtual
 +
where_field = domain
 +
</nowiki>}}
 +
 
 +
{{hc|/etc/postfix/virtual_mailbox_domains.cf|<nowiki>
 +
user = postfix_user
 +
password = hunter2
 +
hosts = localhost
 +
dbname = postfix_db
 +
table = forwardings
 +
select_field = destination
 +
where_field = source
 +
</nowiki>}}
 +
 
 +
{{hc|/etc/postfix/virtual_mailbox_maps.cf|<nowiki>
 +
user = postfix_user
 +
password = hunter2
 +
hosts = localhost
 +
dbname = postfix_db
 +
table = users
 +
select_field = concat(domain,'/',email,'/')
 +
where_field = email
 +
</nowiki>}}
 +
 
 +
Run ''postmap'' on ''transport'' to generate its db:
 +
  # postmap /etc/postfix/transport
  
 
=== Dovecot ===
 
=== Dovecot ===
Start by getting a fresh config file from the pre-existing sample config:
 
cp /etc/dovecot/dovecot.conf.sample /etc/dovecot/dovecot.conf
 
  
In {{ic|/etc/dovecot/dovecot.conf}} we'll need to do quite some configuration:
+
Instead of using the provided Dovecot example config file, we'll create our own {{ic|/etc/dovecot/dovecot.conf}}. Please note that the user and group here might be vmail '''instead of postfix'''!
protocols = imap pop3
+
 
auth_mechanisms = plain
+
{{hc|/etc/dovecot/dovecot.conf|<nowiki>
passdb {
+
protocols = imap pop3
    driver = sql
+
auth_mechanisms = plain
    args = /etc/dovecot/dovecot-sql.conf
+
passdb {
}
+
    driver = sql
userdb sql {
+
    args = /etc/dovecot/dovecot-sql.conf
    driver = sql
+
}
    args = /etc/dovecot/dovecot-sql.conf
+
userdb {
}
+
    driver = sql
 +
    args = /etc/dovecot/dovecot-sql.conf
 +
}
 
   
 
   
service auth {
+
service auth {
    unix_listener auth-client {
+
    unix_listener auth-client {
        group = postfix
+
        group = postfix
        mode = 0660
+
        mode = 0660
        user = postfix
+
        user = postfix
    }
+
    }
    user = root
+
    user = root
}
+
}
+
mail_home = /home/vmail/%d/%u
+
mail_location = maildir:~
+
+
ssl_cert = </etc/ssl/private/server.crt
+
ssl_key = </etc/ssl/private/server.key
+
  
See http://wiki2.dovecot.org/Variables for the docevot variables %d and %u.
+
mail_home = /home/vmail/%d/%n
 +
mail_location = maildir:~
  
Now obviously we also need the {{ic|/etc/dovecot/dovecot-sql.conf}} we just referenced in the config above. Go ahead and create a {{ic|/etc/dovecot/dovecot-sql.conf}} with these contents:
+
ssl_cert = </etc/ssl/private/vmail.crt
driver = mysql
+
ssl_key = </etc/ssl/private/vmail.key
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
+
</nowiki>}}
# The new name for MD5 is MD5-CRYPT so you might need to change this depending on version
+
default_pass_scheme = MD5-CRYPT
+
# Get the mailbox
+
user_query = SELECT '/home/vmail/%d/%u' as home, 'maildir:/home/vmail/%d/%u' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
+
# Get the password
+
password_query = SELECT username as user, password, '/home/vmail/%d/%u' as userdb_home, 'maildir:/home/vmail/%d/%u' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
+
# If using client certificates for authentication, comment the above and uncomment the following
+
#password_query = SELECT null AS password, ‘%u’ AS user
+
  
=== PostfixAdmin ===
+
{{note|If you instead want to modify {{ic|dovecot.conf.sample}}, beware that the default configuration file imports the content of {{ic|conf.d/*.conf}}. Those files call other files that aren't present in our configuration.}}
To install PostfixAdmin, we can use the {{Pkg|postfixadmin}} package from the [[official repositories]].
+
  
Next, PostfixAdmin needs to be configured. First edit the /etc/webapps/postfixadmin/config.inc.php file:
+
Now we create {{ic|/etc/dovecot/dovecot-sql.conf}}, which we just referenced in the config above. Use the following contents and check if everything is set accordingly to your system's configuration.
$CONF['configured'] = true;
+
// correspond to dovecot maildir path /home/vmail/%d/%u
+
$CONF['domain_path'] = 'YES';
+
$CONF['domain_in_mailbox'] = 'YES';
+
$CONF['database_type'] = 'mysql';
+
$CONF['database_host'] = 'localhost';
+
$CONF['database_user'] = 'postfix_user';
+
$CONF['database_password'] = 'hunter2';
+
$CONF['database_name'] = 'postfix_db';
+
  
Then assuming localhost is the hostname of the machine you are installing this on, navigate to ''http://localhost/postfixAdmin/setup.php''. The setup will guide you through the remaining steps to set up PostfixAdmin.
+
If you used PostfixAdmin, then you add the following:
  
{{Note|For a detailed section on setting up domains and mailboxes in PostfixAdmin see the related [[http://en.gentoo-wiki.com/wiki/Mail_server_using_Postfix_and_Dovecot#Setting_up_Mailboxes| Gentoo wiki article]] }}
+
{{hc|/etc/dovecot/dovecot-sql.conf|<nowiki>
 +
driver = mysql
 +
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
 +
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
 +
default_pass_scheme = SHA512-CRYPT
 +
# Get the mailbox
 +
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
 +
# Get the password
 +
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
 +
# If using client certificates for authentication, comment the above and uncomment the following
 +
#password_query = SELECT null AS password, ‘%u’ AS user
 +
</nowiki>}}
 +
 
 +
Without having used PostfixAdmin you can use:
 +
 
 +
{{hc|/etc/dovecot/dovecot-sql.conf|<nowiki>
 +
driver = mysql
 +
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
 +
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
 +
default_pass_scheme = SHA512-CRYPT
 +
# Get the mailbox
 +
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM users WHERE email = '%u'
 +
# Get the password
 +
password_query = SELECT email as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM users WHERE email = '%u'
 +
# If using client certificates for authentication, comment the above and uncomment the following
 +
#password_query = SELECT null AS password, ‘%u’ AS user
 +
</nowiki>}}
 +
 
 +
{{tip | Visit http://wiki2.dovecot.org/Variables to learn more about Dovecot variables.}}
 +
 
 +
=== PostfixAdmin ===
 +
See [[Postfix#PostfixAdmin]].
  
 
=== Roundcube ===
 
=== Roundcube ===
Roundcube is available in the community repo.
 
pacman -S roundcubemail
 
  
The post install process is similar to any other webapps like [[PhpMyAdmin]] or PostFixAdmin. Copy the example configuration file to your webserver configuration directory. If you are using Apache do:
+
Make sure that both the {{ic|pdo_mysql.so}} extension and {{ic|iconv.so}} extension are uncommented in your {{ic|php.ini}} file. Also check the {{ic|.htaccess}} for access restrictions. Assuming that localhost is your current host, navigate a browser to {{ic|http://localhost/roundcube/installer/}} and follow the instructions.  
cp /etc/webapps/roundcubemail/apache.conf /etc/httpd/conf/extra/httpd-roundcubemail.conf
+
Add the include line in /etc/httpd/conf/httpd.conf
+
Include conf/extra/httpd-roundcubemail.conf
+
Make some directories writable by the webserver in /usr/share/webapps/roundcubemail/:
+
chown -R http:http temp logs
+
Roundcube now requires the pdo_mysql.so extension, make sure this extension is un-commented in your php.ini file. Also check .htaccess for access restrictions. Assuming that localhost is your current host, navigate a browser to ''http://localhost/roundcubemail/installer/'' and follow the instructions. You could use the same database for Roundcube that you already used for PostfixAdmin though you shouldn't. For a proper setup, create a second database "roundcube_db" and a "roundcube_user" for use with Roundcube. Update this info in db.inc.php.
+
  
While running the installer, make sure to address the IMAP host with '''ssl://localhost/''' or '''tls://localhost/''' instead of just '''localhost'''. Use port 993. Likewise with SMTP, make sure to provide '''ssl://localhost/''' on port 465 if you used the wrapper mode and '''tls://localhost/''' on port 587 if you used the proper TLS mode. See [[#Postfix|here]] for an explanation on that.
+
Roundcube needs a separate database to work. You should not use the same database for Roundcube and PostfixAdmin. Create a second database {{ic|roundcube_db}} and a new user named {{ic|roundcube_user}}.
  
=== systemd ===
+
While running the installer ...
Make sure your daemons start on boot:
+
 
  systemctl enable dovecot postfix
+
* Make sure to address of the IMAP host is {{ic|ssl://localhost/}} or {{ic|tls://localhost/}} and not just {{ic|localhost}}.
 +
* Use port {{ic|993}}. Likewise with SMTP.
 +
* Make sure to provide {{ic|ssl://localhost/}} with port {{ic|465}} if you used the wrapper mode
 +
* and use {{ic|tls://localhost/}} port {{ic|587}} if you used the proper TLS mode.
 +
* See [[#Postfix|here]] for an explanation on that.
 +
 +
The post install process is similar to any other webapp like [[PhpMyAdmin]] or PostFixAdmin. The configuration file is in {{ic|/etc/webapps/roundcubemail/config/config.inc.php}} which works as an override over {{ic|default.inc.php}}.
 +
 
 +
==== Apache configuration ====
 +
 
 +
If you are using Apache, copy the example configuration file to your webserver configuration directory.
 +
 
 +
  # cp /etc/webapps/roundcubemail/apache.conf /etc/httpd/conf/extra/httpd-roundcubemail.conf
 +
 
 +
Add the following line in
 +
 
 +
{{hc|/etc/httpd/conf/httpd.conf|<nowiki>
 +
Include conf/extra/httpd-roundcubemail.conf
 +
</nowiki>}}
 +
 
 +
==== Roundcube: Change Password Plugin ====
 +
 
 +
To let users change their passwords from within Roundcube, do the following:
 +
 
 +
Enable the password plugin by adding this line to
 +
 
 +
{{hc|/etc/webapps/roundcubemail/config/config.inc.php|<nowiki>
 +
$rcmail_config['plugins'] = array('password');
 +
</nowiki>}}
 +
 
 +
Configure the password plugin and make sure you alter the settings accordingly:
 +
 
 +
{{hc|/usr/share/webapps/roundcubemail/plugins/password/config.inc.php|<nowiki>
 +
$config['password_driver'] = 'sql';
 +
$config['password_db_dsn'] = 'mysql://<postfix_database_user>:<password>@localhost/<postfix_database_name>';
 +
$config['password_query'] = 'UPDATE mailbox SET password=%c WHERE username=%u';
 +
</nowiki>}}
  
 
== Fire it up ==
 
== Fire it up ==
Since now hopefully everything is set up correctly, all necessary daemons should be started for a test run:
+
All necessary daemons should be started in order to test the configuration. [[Start]] both {{ic|postfix}} and {{ic|dovecot}}.
systemctl start postfix dovecot
+
  
 
Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.
 
Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.
Line 219: Line 301:
 
Although these items are not required, they definitely add more completeness to your setup
 
Although these items are not required, they definitely add more completeness to your setup
  
=== SpamAssassin ===
+
=== Quota ===
Is available in the extra repo. Following steps borrowed from [[SOHO_Postfix#Spamassassin]]
+
To enable mailbox quota support by dovecot, do the following:
  pacman -S spamassassin
+
*First add the following lines to /etc/dovecot/dovecot.conf
Go over /etc/mail/spamassassin/local.cf and configure it to your needs. Create Spamassassin user/group and folder.
+
  dict {
groupadd -g 5001 spamd
+
quotadict = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
  useradd -u 5001 -g spamd -s /sbin/nologin -d /var/lib/spamassassin -m spamd
+
}
  chown spamd:spamd /var/lib/spamassassin
+
service dict {
 +
unix_listener dict {
 +
group = vmail
 +
mode = 0660
 +
user = vmail
 +
}
 +
user = root
 +
}
 +
service quota-warning {
 +
executable = script /usr/local/bin/quota-warning.sh
 +
user = vmail
 +
unix_listener quota-warning {
 +
group = vmail
 +
mode = 0660
 +
user = vmail
 +
}
 +
  }
 +
mail_plugins=quota
 +
protocol pop3 {
 +
mail_plugins = quota
 +
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
 +
pop3_uidl_format = %08Xu%08Xv
 +
}
 +
protocol lda {
 +
mail_plugins = quota
 +
postmaster_address = postmaster@yourdomain.com
 +
}
 +
protocol imap {
 +
mail_plugins = $mail_plugins imap_quota
 +
mail_plugin_dir = /usr/lib/dovecot/modules
 +
  }
 +
plugin {
 +
        quota = dict:User quota::proxy::quotadict
 +
        quota_rule2 = Trash:storage=+10%%
 +
        quota_warning = storage=100%% quota-warning +100 %u
 +
        quota_warning2 = storage=95%% quota-warning +95 %u
 +
        quota_warning3 = storage=80%% quota-warning +80 %u
 +
        quota_warning4 = -storage=100%% quota-warning -100 %u # user is no longer over quota
 +
}
  
Make sure /etc/conf.d/spamd look like following.
+
*Create a new file /etc/dovecot/dovecot-dict-sql.conf.ext with the following code:
  SAHOME="/var/lib/spamassassin/"
+
  connect = host=localhost dbname=yourdb user=youruser password=yourpassword
  SPAMD_OPTS="--create-prefs --max-children 5 --username spamd --helper-home-dir ${SAHOME} -s ${SAHOME}spamd.log --pidfile /var/run/spamd.pid"
+
map {
 +
pattern = priv/quota/storage
 +
table = quota2
 +
username_field = username
 +
value_field = bytes
 +
}
 +
map {
 +
pattern = priv/quota/messages
 +
table = quota2
 +
username_field = username
 +
value_field = messages
 +
}
 +
*Create a warning script /usr/local/bin/quota-warning.sh and make sure it is executable. This warning script works with postfix lmtp configuration as well.
 +
<pre> #!/bin/sh
 +
BOUNDARY="$1"
 +
  USER="$2"
 +
MSG=""
 +
if [[ "$BOUNDARY" = "+100" ]]; then
 +
    MSG="Your mailbox is now overfull (>100%). In order for your account to continue functioning properly, you need to remove some emails NOW."
 +
elif [[ "$BOUNDARY" = "+95" ]]; then
 +
    MSG="Your mailbox is now over 95% full. Please remove some emails ASAP."
 +
elif [[ "$BOUNDARY" = "+80" ]]; then
 +
    MSG="Your mailbox is now over 80% full. Please consider removing some emails to save space."
 +
elif [[ "$BOUNDARY" = "-100" ]]; then
 +
    MSG="Your mailbox is now back to normal (<100%)."
 +
fi
 +
 +
cat << EOF | /usr/lib/dovecot/dovecot-lda -d $USER -o "plugin/quota=maildir:User quota:noenforcing"
 +
From: postmaster@yourdomain.com
 +
Subject: Email Account Quota Warning
 +
 +
Dear User,
 +
 +
$MSG
 +
 +
Best regards,
 +
Your Mail System
 +
EOF
 +
</pre>
  
To leave the service ready to run, let's update the spamassassin matching patterns.
+
*Edit the user_query line and add iterat_query in dovecot-sql.conf as following:
  /usr/bin/vendor_perl/sa-update
+
  user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
 +
  iterate_query = SELECT username AS user FROM mailbox
 +
*Set up LDA as described above under SpamAssassin. If you're not using SpamAssassin, the pipe should look like this in /etc/postfix/master.cf :
 +
  dovecot    unix -      n      n      -      -      pipe
 +
  flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
 +
As above activate it in Postfix main.cf
 +
  virtual_transport = dovecot
 +
*You can set up quota per each mailbox in postfixadmin. Make sure the relevant lines in config.inc.php look like this:
 +
$CONF['quota'] = 'YES';
 +
$CONF['quota_multiplier'] = '1024000';
  
{{Note| If you want to combine Spamassassin and Dovecot Mail Filtering you have to ignore the next two lines and continue further down instead.}}
+
Restart postfix and dovecot services. If things go well, you should be able to list all users' quota and usage by the this command:
 +
doveadm quota get -A
 +
You should be able to see the quota in roundcube too.
  
Edit /etc/postfix/master.cf and add the content filter under smtp.
+
== Sidenotes ==
smtp      inet  n      -      n      -      -      smtpd
+
        -o content_filter=spamassassin
+
  
Also add the following service entry for spamassassin
+
=== Alternative vmail folder structure ===
spamassassin  unix  -    n      n      -      -      pipe
+
        user=spamd argv=/usr/bin/vendor_perl/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
+
  
===== SpamAssassin combined with Dovecot LDA / Sieve (Mailfiltering) =====
+
Instead of having a directory structure like {{ic|/home/vmail/example.com/user@example.com}} you can have cleaner subdirectories (without the additional domain name) by replacing {{ic|select_field}} and {{ic|where_field}} with:
* Set up LDA and the Sieve-Plugin which is descriped in [[Dovecot#Sieve]]. But ignore the last line {{ic|mailbox_command... }}
+
{{bc|1=query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'}}
* Instead add a pipe in /etc/postfix/master.cf
+
  dovecot  unix  -      n      n      -      -      pipe
+
        flags=DRhu user=vmail:vmail argv=/usr/bin/vendor_perl/spamc -f -u spamd -e /usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}
+
* And activate it in Postfix main.cf
+
  virtual_transport = dovecot
+
  
Enable and start the service with systemctl
 
systemctl enable spamassassin
 
systemctl start spamassassin
 
  
 
== Troubleshooting ==
 
== Troubleshooting ==
If you get errors like your imap/pop3 client failing to receive mails, take a look into your /var/log/mail.log file.
 
It turned out that the maildir /home/vmail/mail@domain.tld is just being created if there is at least one email waiting. Otherwise there wouldn't be any need for the directory.
 
  
== Tips and Tricks ==
+
=== IMAP/POP3 client failing to receive mails ===
===When sending email with Postfix, how can I hide the sender’s IP and username in the Received header===
+
This is a privacy concern mostly, if you use Thunderbird and send an email. The received header will contain your LAN and WAN IP and info about the email client you used.
+
(Original source: [http://askubuntu.com/questions/78163/when-sending-email-with-postfix-how-can-i-hide-the-senders-ip-and-username-in AskUbuntu])
+
What we want to do is remove the Received header from outgoing emails. This can be done by applying header_checks exclusively to the submission port. What we need to do is pass the cleanup_service_name option to the submission service so that we can set up a new cleanup service, “subcleanup.” The relevant section of /etc/postfix/master.cf might look like this:
+
  
submission inet n      -       -       -       -      smtpd
+
If you get similar errors, take a look into {{ic|/var/log/mail.log}} or use {{ic|journalctl -xn --unit postfix.service}} to find out more.
  -o smtpd_tls_security_level=encrypt
+
  -o smtpd_sasl_auth_enable=yes
+
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+
  -o milter_macro_daemon_name=ORIGINATING
+
  -o cleanup_service_name=subcleanup
+
Now we can pass the header_checks option to the new cleanup service. That part of /etc/postfix/master.cf might look like this:
+
  
cleanup  unix  n      -      -      -      0      cleanup
+
It may turn out that the Maildir {{ic|/home/vmail/mail@domain.tld}} is just being created if there is at least one email waiting. Otherwise there wouldn't be any need for the directory creation before.
subcleanup unix n      -      -      -      0      cleanup
+
  -o header_checks=regexp:/etc/postfix/submission_header_checks
+
Finally, we need to create the file /etc/postfix/submission_header_checks, which will contain the regex that filters offending Received header lines:
+
  
/^Received:/ IGNORE
+
 
/^User-Agent:/ IGNORE
+
=== Roundcube not able to delete emails or view any 'standard' folders ===
==See also==
+
 
*[[Courier MTA]]
+
Ensure that the Roundcube config.inc.php file contains the following:
*[[Postfix]]
+
 
*[[SOHO Postfix]]
+
{{bc|1=
*[[OpenDKIM]]
+
$rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
 +
$rcmail_config['create_default_folders'] = true;
 +
$rcmail_config['protect_default_folders'] = true;
 +
}}

Latest revision as of 10:39, 4 June 2016

Related articles

This article describes how to set up a complete virtual user mail system on an Arch Linux system in the simplest manner possible. However, since a mail system consists of many complex components, quite a bit of configuration will still be necessary.

Roughly, the components used in this article are Postfix as the mail server, Dovecot as the IMAP server, Roundcube as the webmail interface and PostfixAdmin as the administration interface to manage it all.

In the end, the provided solution will allow you to use the best currently available security mechanisms, you will be able to send mails using SMTP and SMTPS and receive mails using POP3, POP3S, IMAP and IMAPS. Additionally, configuration will be easy thanks to PostfixAdmin and users will be able to login using Roundcube. What a deal!

Installation

Before you start, you must have both a working MySQL server as described in MySQL and a working Postfix server as described in Postfix.

Install the dovecot and roundcubemail packages.

Configuration

User

For security reasons, a new user should be created to store the mails:

# groupadd -g 5000 vmail
# useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail

A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in /home/vmail. You could change the home directory to something like /var/mail/vmail but be careful to change this in any configuration below as well.

Database

You will need to create an empty database and corresponding user. In this article, the user postfix_user will have read/write access to the database postfix_db using hunter2 as password. You are expected to create the database and user yourself, and give the user permission to use the database, as shown in the following code.

$ mysql -u root -p
CREATE DATABASE postfix_db;
GRANT ALL ON postfix_db.* TO 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
FLUSH PRIVILEGES;

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: Further manual database installation is missing. So far, the only way to follow this article is by installing PostfixAdmin with Apache, MySQL and PHP. (Discuss in Talk:Virtual user mail system#)

Now you can go to the PostfixAdmin's setup page, let PostfixAdmin create the needed tables and create the users in there.

PostfixAdmin

See Postfix#PostfixAdmin.

SSL certificate

You will need a SSL certificate for all encrypted mail communications (SMTPS/IMAPS/POP3S). If you do not have one, create one:

# cd /etc/ssl/private/
# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout vmail.key -out vmail.crt -days 1460 #days are optional
# chmod 400 vmail.key
# chmod 444 vmail.crt

Postfix

SMTPS

Enable secure SMTP as described in Postfix#Secure SMTP.

Prerequisites

Before you copy&paste the configuration below, check if relay_domains has already been already set. If you leave more than one active, you will receive warnings during runtime.

Warning: relay_domains can be dangerous. You usually do not want Postfix to forward mail of strangers. $mydestination is a sane default value. Double check it's value before running postfix! See http://www.postfix.org/BASIC_CONFIGURATION_README.html#relay_to

Also check if your SSL certificate paths are set right in all upcoming config examples.

Setting up Postfix

To /etc/postfix/main.cf append:

relay_domains = $mydestination
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_mailbox_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf
virtual_mailbox_base = /home/vmail
virtual_mailbox_limit = 512000000
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
transport_maps = hash:/etc/postfix/transport

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/run/dovecot/auth-client
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_received_header = yes
smtpd_tls_cert_file = /etc/ssl/private/vmail.crt
smtpd_tls_key_file = /etc/ssl/private/vmail.key
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1
  • In the configuration above virtual_mailbox_domains is a list of the domains that you want to receive mail for. This CANNOT contain the domain that is set in mydestination. That is why we left mydestination to be localhost only.
  • virtual_mailbox_maps will contain the information of virtual users and their mailbox locations. We are using a hash file to store the more permanent maps, and these will then override the forwards in the MySQL database.
  • virtual_mailbox_base is the base directory where the virtual mailboxes will be stored.

The virtual_uid_maps and virtual_gid_maps are the real system user IDs that the virtual mails will be owned by. This is for storage purposes.

Note: Since we will be using a web interface (Roundcube), and do not want people accessing this by any other means, we will be creating this account later without providing any login access.

Create the file structure

Those new additional settings reference a lot of files that do not even exist yet. We will create them with the following steps.

If you were setting up your database with PostfixAdmin and created the database schema through PostfixAdmin, you can create the following files. Do not forget to change the password:

/etc/postfix/virtual_alias_maps.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = alias
select_field = goto
where_field = address
/etc/postfix/virtual_mailbox_domains.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = domain
select_field = domain
where_field = domain
/etc/postfix/virtual_mailbox_maps.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = mailbox
select_field = maildir
where_field = username
Note: For setups without using PostfixAdmin, create the following files.
/etc/postfix/virtual_alias_maps.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = domains
select_field = virtual
where_field = domain
/etc/postfix/virtual_mailbox_domains.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = forwardings
select_field = destination
where_field = source
/etc/postfix/virtual_mailbox_maps.cf
user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = users
select_field = concat(domain,'/',email,'/')
where_field = email

Run postmap on transport to generate its db:

# postmap /etc/postfix/transport

Dovecot

Instead of using the provided Dovecot example config file, we'll create our own /etc/dovecot/dovecot.conf. Please note that the user and group here might be vmail instead of postfix!

/etc/dovecot/dovecot.conf
protocols = imap pop3
auth_mechanisms = plain
passdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}
userdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}
 
service auth {
    unix_listener auth-client {
        group = postfix
        mode = 0660
        user = postfix
    }
    user = root
}

mail_home = /home/vmail/%d/%n
mail_location = maildir:~

ssl_cert = </etc/ssl/private/vmail.crt
ssl_key = </etc/ssl/private/vmail.key
Note: If you instead want to modify dovecot.conf.sample, beware that the default configuration file imports the content of conf.d/*.conf. Those files call other files that aren't present in our configuration.

Now we create /etc/dovecot/dovecot-sql.conf, which we just referenced in the config above. Use the following contents and check if everything is set accordingly to your system's configuration.

If you used PostfixAdmin, then you add the following:

/etc/dovecot/dovecot-sql.conf
driver = mysql
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
default_pass_scheme = SHA512-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user

Without having used PostfixAdmin you can use:

/etc/dovecot/dovecot-sql.conf
driver = mysql
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes
default_pass_scheme = SHA512-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM users WHERE email = '%u'
# Get the password
password_query = SELECT email as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM users WHERE email = '%u'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user
Tip: Visit http://wiki2.dovecot.org/Variables to learn more about Dovecot variables.

PostfixAdmin

See Postfix#PostfixAdmin.

Roundcube

Make sure that both the pdo_mysql.so extension and iconv.so extension are uncommented in your php.ini file. Also check the .htaccess for access restrictions. Assuming that localhost is your current host, navigate a browser to http://localhost/roundcube/installer/ and follow the instructions.

Roundcube needs a separate database to work. You should not use the same database for Roundcube and PostfixAdmin. Create a second database roundcube_db and a new user named roundcube_user.

While running the installer ...

  • Make sure to address of the IMAP host is ssl://localhost/ or tls://localhost/ and not just localhost.
  • Use port 993. Likewise with SMTP.
  • Make sure to provide ssl://localhost/ with port 465 if you used the wrapper mode
  • and use tls://localhost/ port 587 if you used the proper TLS mode.
  • See here for an explanation on that.

The post install process is similar to any other webapp like PhpMyAdmin or PostFixAdmin. The configuration file is in /etc/webapps/roundcubemail/config/config.inc.php which works as an override over default.inc.php.

Apache configuration

If you are using Apache, copy the example configuration file to your webserver configuration directory.

# cp /etc/webapps/roundcubemail/apache.conf /etc/httpd/conf/extra/httpd-roundcubemail.conf

Add the following line in

/etc/httpd/conf/httpd.conf
Include conf/extra/httpd-roundcubemail.conf

Roundcube: Change Password Plugin

To let users change their passwords from within Roundcube, do the following:

Enable the password plugin by adding this line to

/etc/webapps/roundcubemail/config/config.inc.php
$rcmail_config['plugins'] = array('password');

Configure the password plugin and make sure you alter the settings accordingly:

/usr/share/webapps/roundcubemail/plugins/password/config.inc.php
$config['password_driver'] = 'sql';
$config['password_db_dsn'] = 'mysql://<postfix_database_user>:<password>@localhost/<postfix_database_name>';
$config['password_query'] = 'UPDATE mailbox SET password=%c WHERE username=%u';

Fire it up

All necessary daemons should be started in order to test the configuration. Start both postfix and dovecot.

Now for testing purposes, create a domain and mail account in PostfixAdmin. Try to login to this account using Roundcube. Now send yourself a mail.

Optional Items

Although these items are not required, they definitely add more completeness to your setup

Quota

To enable mailbox quota support by dovecot, do the following:

  • First add the following lines to /etc/dovecot/dovecot.conf
dict {
	quotadict = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
service dict {
	unix_listener dict {
		group = vmail
		mode = 0660
		user = vmail
	}
	user = root
}
service quota-warning {
	executable = script /usr/local/bin/quota-warning.sh
	user = vmail
	unix_listener quota-warning {
		group = vmail
		mode = 0660
		user = vmail
	}
}	
mail_plugins=quota
protocol pop3 {
	 mail_plugins = quota
	 pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
	 pop3_uidl_format = %08Xu%08Xv
}
protocol lda {
	mail_plugins = quota
	postmaster_address = postmaster@yourdomain.com
}
protocol imap {
	mail_plugins = $mail_plugins imap_quota
	mail_plugin_dir = /usr/lib/dovecot/modules
}
plugin {
       quota = dict:User quota::proxy::quotadict
       quota_rule2 = Trash:storage=+10%%
       quota_warning = storage=100%% quota-warning +100 %u
       quota_warning2 = storage=95%% quota-warning +95 %u
       quota_warning3 = storage=80%% quota-warning +80 %u
       quota_warning4 = -storage=100%% quota-warning -100 %u # user is no longer over quota
}
  • Create a new file /etc/dovecot/dovecot-dict-sql.conf.ext with the following code:
connect = host=localhost dbname=yourdb user=youruser password=yourpassword
map {
	pattern = priv/quota/storage
	table = quota2
	username_field = username
	value_field = bytes
}
map {
	pattern = priv/quota/messages
	table = quota2
	username_field = username
	value_field = messages
}
  • Create a warning script /usr/local/bin/quota-warning.sh and make sure it is executable. This warning script works with postfix lmtp configuration as well.
 #!/bin/sh
 BOUNDARY="$1"
 USER="$2"
 MSG=""
 if [[ "$BOUNDARY" = "+100" ]]; then
    MSG="Your mailbox is now overfull (>100%). In order for your account to continue functioning properly, you need to remove some emails NOW."
 elif [[ "$BOUNDARY" = "+95" ]]; then
    MSG="Your mailbox is now over 95% full. Please remove some emails ASAP."
 elif [[ "$BOUNDARY" = "+80" ]]; then
    MSG="Your mailbox is now over 80% full. Please consider removing some emails to save space."
 elif [[ "$BOUNDARY" = "-100" ]]; then
    MSG="Your mailbox is now back to normal (<100%)."
 fi
 
 cat << EOF | /usr/lib/dovecot/dovecot-lda -d $USER -o "plugin/quota=maildir:User quota:noenforcing"
 From: postmaster@yourdomain.com
 Subject: Email Account Quota Warning
 
 Dear User,
 
 $MSG
 
 Best regards,
 Your Mail System
 EOF
  • Edit the user_query line and add iterat_query in dovecot-sql.conf as following:
 user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
 iterate_query = SELECT username AS user FROM mailbox
  • Set up LDA as described above under SpamAssassin. If you're not using SpamAssassin, the pipe should look like this in /etc/postfix/master.cf :
 dovecot    unix  -       n       n       -       -       pipe
 flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

As above activate it in Postfix main.cf

 virtual_transport = dovecot
  • You can set up quota per each mailbox in postfixadmin. Make sure the relevant lines in config.inc.php look like this:
$CONF['quota'] = 'YES';
$CONF['quota_multiplier'] = '1024000';

Restart postfix and dovecot services. If things go well, you should be able to list all users' quota and usage by the this command:

doveadm quota get -A

You should be able to see the quota in roundcube too.

Sidenotes

Alternative vmail folder structure

Instead of having a directory structure like /home/vmail/example.com/user@example.com you can have cleaner subdirectories (without the additional domain name) by replacing select_field and where_field with:

query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'


Troubleshooting

IMAP/POP3 client failing to receive mails

If you get similar errors, take a look into /var/log/mail.log or use journalctl -xn --unit postfix.service to find out more.

It may turn out that the Maildir /home/vmail/mail@domain.tld is just being created if there is at least one email waiting. Otherwise there wouldn't be any need for the directory creation before.


Roundcube not able to delete emails or view any 'standard' folders

Ensure that the Roundcube config.inc.php file contains the following:

$rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
$rcmail_config['create_default_folders'] = true;
$rcmail_config['protect_default_folders'] = true;