This article describes how to set up a virtual user mail system, i.e. where the senders and recipients do not correspond to the Linux system users.

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.

Configuration

User

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.

Alternatively, create a free trusted certificate using Let's Encrypt. The private key will be in /etc/letsencrypt/live/yourdomain/privkey.pem, the certificate in /etc/letsencrypt/live/yourdomain/fullchain.pem. Either change the configuration accordingly, or symlink the keys to /etc/ssl/private:

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:

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

Roundcube

Make sure that both extension=pdo_mysql and extension=iconv 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 ...

For the address of the IMAP host, use ssl://localhost/ or tls://localhost/ and not just localhost.

Use port 993. Likewise with SMTP.

For the address of the SMTP host, use tls://localhost/ and port 587 if you used STARTTLS. Use ssl://localhost/ with port 465 if you used SMTPS.

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 defaults.inc.php.

Apache configuration

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

In the above example, user admin@example.com has access to, and can do anything to, all the public folders. Edit to fit your specific needs.

Note:

lrwstipekxa are the permissions being granted. Visit the Dovecot wiki for further details.

Make sure the user subscribes to the folders in the client they are using.

Fighting Spam

As an alternative to SpamAssassin, consider rspamd. Out of the box, it delivers an amazing amount of spam reduction, greylisting, etc and includes a nifty webui. See also [1].

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:

LMTP / Sieve

Is LMTP not connecting to sieve? Ensure that your server is not routing the messages locally. This can be set in /etc/postfix/main.cf:

mydestination =

Are your emails sent to gmail users ending up in their junk/spam folders?

Google gmail (and most other large email providers) will send your emails straight into your recipients junk / spam folder if you have not implemented SPF / DKIM / DMARC policies. (Hint: Rspamd, via the link above, shows you how to set this up, and will DKIM sign your emails.)