I'm trying to setup Postfix and Dovecot, the latter with virtual users stored in a MySQL database, following this guide (but here I recap everything as there are some "bugs" in the guide I fixed following the comments). Preamble: I have Postfix, Dovecot, postfix-mysql and dovecot-mysql installed from Ubuntu repositories.

Let's start with Postfix config:

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no   
readme_directory = no

myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost
relayhost = 
mynetworks = [::ffff:]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

relay_domains = *
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_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/private/server.crt
smtpd_tls_key_file = /etc/ssl/private/server.key
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1

Then I created user vmail to store emails:

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

And MySQL database and user to store info about domains and virtual users:

USE postfix_db;
CREATE USER postfix_user@localhost IDENTIFIED BY 'password';
GRANT ALL ON postfix_db.* TO postfix_user@localhost;

Then I created the tables related to domains, forwardings and users:

CREATE TABLE `domains` (
  `domain` varchar(50) NOT NULL default "",
  PRIMARY KEY  (`domain`),
  UNIQUE KEY `domain` (`domain`)

CREATE TABLE `forwardings` (
  `source` varchar(80) NOT NULL default "",
  `destination` text NOT NULL,
  PRIMARY KEY  (`source`)

CREATE TABLE `users` (
  `email` varchar(80) NOT NULL default "",
  `password` varchar(20) NOT NULL default "",
  `quota` varchar(20) NOT NULL default '20971520',
  `domain` varchar(255) NOT NULL default "",
  UNIQUE KEY `email` (`email`)

I added my domain (which has A and MX records properly set) in the table:

INSERT INTO `domains` VALUES ('virtualdomain.tld');

And an account related to that domain:

INSERT INTO `users` VALUES ('info@virtualdomain.tld', ENCRYPT('password'), '20971520', 'virtualdomain.tld');

Then I created a self-signed cert:

cd /etc/ssl/private/
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key
chmod 400 server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
chmod 444 server.crt

And then the files I was referring to in Postfix config:


user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = domains
select_field = domain
where_field = domain


user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = forwardings
select_field = destination
where_field = source


user = postfix_user
password = hunter2
hosts = localhost
dbname = postfix_db
table = users
select_field = concat(domain,'/',email,'/')
where_field = email

And then

touch /etc/postfix/transport
postmap /etc/postfix/transport

Now I deleted the default Dovecot config file, replacing it with:

protocols = imap
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/%u
mail_location = maildir:~

ssl_cert = </etc/ssl/private/server.crt
ssl_key = </etc/ssl/private/server.key

I created the /etc/dovecot/dovecot-sql.conf file:

driver = mysql
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
# 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 users WHERE email = '%u'
# Get the password
password_query = SELECT email 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 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

... and finally restarted dovecot and postfix:

service postfix dovecot restart

The problem is that when I try to send an email to info@virtualdomain.tld, I see this in logs:

NOQUEUE: reject: RCPT from blablabla.com[xxx.xxx.xxx.xxx]: 451 4.3.0 <info@virtualdomain.tld>: Temporary lookup failure; from=<my@email.tld> to=<info@virtualdomain.tld> proto=ESMTP helo=<blablabla.com>

And the mail bounces back with the error

550 5.1.1 "Recipient address rejected: User unknown in virtual alias table"
  • What's the result of command postmap -q virtualdomain.tld mysql:/etc/postfix/virtual_alias_maps.cf and postmap -q virtualdomain.tld mysql:/etc/postfix/virtual_mailbox_domains.cf? Please also check maillog after you run those commands. – masegaloeh Oct 31 '14 at 23:41
  • Thanks for the reply. Here are the results: root:~# postmap -q virtualdomain.tld mysql:/etc/postfix/virtual_alias_ maps.cf virtualdomain.tld root:~# postmap -q virtualdomain.tld mysql:/etc/postfix/virtual_mailbox_domains.cf (empty) Better in pastebin: pastebin.com/raw.php?i=66UGqx9L Nothing in server logs – MultiformeIngegno Nov 1 '14 at 1:00
  • 1
    As you said, the tutorial is broken (duh!). Remember, you should consult official documentation whenever you using any tutorial to getting started. – masegaloeh Nov 1 '14 at 1:12

Looks like, your virtual_alias_maps and virtual_mailbox_domains was swapped. Try to rename them

mv /etc/postfix/virtual_alias_maps.cf /tmp/virtual_mailbox_domains.tmp
mv /etc/postfix/virtual_mailbox_domains.cf /etc/postfix/virtual_alias_maps.cf 
mv /tmp/virtual_mailbox_domains.tmp /etc/postfix/virtual_mailbox_domains.cf

Don't forget to run postfix reload.

  • Ooook!!! Something seems to start working now!! I can see the mail in /home/vmail/virtualdomain.tld/info@virtualdomain.tld/new. And here's the syslog: pastebin.com/raw.php?i=pAf3VL2V. But if I try to connect from an email client specifying my FQDN as host and username&password specified in "users" table I get these errors in syslog "Auth failed. TLS: Disconnected" "warning: SASL: Connect to /var/run/dovecot/auth-client failed: No such file or directory" and "fatal: no SASL authentication mechanisms" – MultiformeIngegno Nov 1 '14 at 2:30
  • If I set PLAIN instead of MD5-CRYPT everything works I can even access from my external client. Seems MySQL ENCRYPT function used when adding the password to the users table isn't encrypting as MD5 (it doesn't even start with $1)... mmm – MultiformeIngegno Nov 1 '14 at 2:52

I'm sure Dovecot is the one that creates the auth file, as postfix talks to dovecot and dovecot does the authentication so in your 'dovecot.conf' add:

path = /var/run/dovecot/auth-client

into the client block like so:

service auth {
    unix_listener auth-client {
        path = /var/run/dovecot/auth-client
        group = postfix
        mode = 0660
        user = postfix


service auth {
    unix_listener /var/run/dovecot/auth-client {
        group = postfix
        mode = 0660
        user = postfix

Restart dovecot

Check if /var/run/dovecot/auth-client is created

type in ls -l /var/run/dovecot/auth-client to confirm.

Then retry.

  • I found the correct dirs. Apparently since ubuntu 12.04 the path is /var/spool/postfix/private/auth. Now the only problem seems to be the MD5 encrypt function by MySQL. When I insert the data in "users" table ENCRYPT('password') doesn't actually store the password as MD5-CRYPT scheme.. Which function should I use instead? – MultiformeIngegno Nov 1 '14 at 3:35
  • Your Password row varchar(20) doesn't seem enough for the md5-crypt hash: password varchar(20) NOT NULL default "" Change the varchar length value to varchar(64) – devatnull Nov 1 '14 at 4:00
  • Thanks. I'll try as soon as the screenshot of the VPS is complete. :D – MultiformeIngegno Nov 1 '14 at 4:03
  • BTW MD5 is considered a weak encryption method, once you get the set up working look into another more secure encryption method like sha512/256 etc – devatnull Nov 1 '14 at 4:04
  • Check this post for a reference to a similiar situation: stackoverflow.com/questions/24186158/… – devatnull Nov 1 '14 at 4:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.