How-To: Virtual emails accounts with Postfix and Dovecot

2 minute read

This tutorial will explain how to run a mail server with virtual domains and users using a MySQL backend to store email informations.

Postfix will be our SMTP server, Dovecot will be handling IMAP (optionally one could configure POP3 also) so that users can retrieve their email.

Another tutorial will cover SPAM fighting using DSPAM based on this implementation (yet to be done).

This tutorial was done on Debian Etch using postfix 2.3.8-2etch4 and 1.0.rc15-2etch4.

By using Virtual domains and users, we are able to set up unlimited email accounts without creating a system user. This does not make sense if you have only one user on your mail server, but can become pretty handy if you start hosting quite a fair amount of email accounts/domains.

In order to set this implementation up, we are first going to proceed as follow:

  • Set the emails accounts repository (where emails will be stored)
  • Set the users/domains databases (where user informations will be kept)
  • Set our SMTP server (postfix)
  • Set our IMAP server (dovecot)

1. Installing the required packages

Run this command to install all the required packages for this tutorial:

# apt-get install postfix postfix-mysql openssl ssl-cert dovecot-imapd mysql-server

Optionally, you might want to install dovecot-pop3d if you wish to activate POP3 service.

2. Creating the Virtual Email user

All our emails will be handled by a unique system user on the system: vmail, postfix and dovecot will take care of handling authentication.

To create the vmail user proceed as follow:

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/vmail
mkdir /var/vmail
chown vmail:vmail /var/vmail

3. Creating the database

Now, let’s create the database that will hold our user emails and passwords. Log into MySQL as root and type:

CREATE DATABASE virtual_email;
GRANT USAGE ON *.* TO vemailuser@'localhost' IDENTIFIED BY 'vemailpass';
GRANT ALL PRIVILEGES ON virtual_email.* TO vemailuser@'localhost';

Then use the following script, name it create_emaildb.sql:

DROP TABLE IF EXISTS `virtual_domains`;
CREATE TABLE `virtual_domains` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `UNIQUE_NAME` (`name`)
) ENGINE=InnoDB ;

DROP TABLE IF EXISTS `virtual_aliases`;
CREATE TABLE `virtual_aliases` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `source` varchar(40) NOT NULL,
  `destination` varchar(80) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `domain_id` (`domain_id`),
  CONSTRAINT `virtual_aliases_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `virtual_domains` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;

DROP TABLE IF EXISTS `virtual_users`;
CREATE TABLE `virtual_users` (
  `id` int(11) NOT NULL auto_increment,
  `domain_id` int(11) NOT NULL,
  `user` varchar(40) NOT NULL,
  `password` varchar(32) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `UNIQUE_EMAIL` (`domain_id`,`user`),
  CONSTRAINT `virtual_users_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `virtual_domains` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;

and inject it into the database:

mysql -u root -p virtual_email < create_emaildb.sql

Finally, create some sample users:

# mysql -u vemailuser -p virtual_email
INSERT INTO virtual_domains (id, name) VALUES (1, 'example.com');
INSERT INTO virtual_users (id, domain_id, user, password) VALUES (1, 1, 'chantra', MD5('chantra'));
INSERT INTO virtual_users (id, domain_id, user, password) VALUES (2, 1, 'chantra2', MD5('chantra'));
INSERT INTO virtual_aliases (id, domain_id, source, destination) VALUES (1, 1, 'foo', '[email protected]'), (2, 1, '', '[email protected]');

Well, this is is for the database, you now have some sample users to play with.

Let’s now configure Postfix.