(I have written this article in english since I wasn’t able to find any updated guide about this subject in any language).
DISCLAIMER. this is a very basic configuration. Not intended for production environment. Use at your own risk.
I have a small mailserver handling very few domains with mailboxes for may friends and relatives an it have been working fine for the last 8 years.
But it is based on the old CentOS 5 + sendmail and I think it is time to upgrade!
So, in order to test the new future configuration, I have performed a CentOS 7 minimum install on a virtual machine and tried to configure the minimum amount of packages to have it working.
Now let’s start!
First of all, good news: on CentOS 7 both the stock postfix and dovecot packages have full mysql support without the need for enabling external repos or recompiling them from the source.
DATABASE CONFIGURATION
Mysql have been replaced by MariaDB that is mainly compatible.
Ask yum to install mariadb and mariadb-server packages.
[root@server03 ~]# yum install mariadb mariadbserver
Start and enable the service
[root@server03 ~]# systemctl start mariadb [root@server03 ~]# systemctl enable mariadb
(please note the new SystemD commands. You can still use the service command for compatibility, but it will be redirected to systemctl)
Then launch
[root@server03 ~]# mysql_secure_installation
and answer all the questions (change root password….)
Now it is time to create database and tables for our simple installation.
Enter the mysql console:
[root@server03 ~]# mysql -uroot -p Enter password:
(enter the root mariaDB password you have set during secure installation process)
Create the database:
MariaDB [(none)]> create database mailserver; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]>
Select database:
MariaDB [(none)]> use mailserver;
Create user table (paste the following SQL):
CREATE TABLE `users` ( `email` varchar(200) NOT NULL, `password` varchar(128) NOT NULL, `enabled` int(11) NOT NULL DEFAULT '1', `username` varchar(45) DEFAULT NULL, PRIMARY KEY (`email`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;
This table will be used by postfix and dovecot to select valid mailboxes and to authenticate matching users.
The fields are self-explanatory.
Just one note: even if Dovecot will use email as username, the field username will be used for SMTP auth (in the next article) since I prefer my ordinary mail users (IMAP, POP) not to be able to send email using the resident SMTP service. Only users with ‘username’ set will be able to do it.
Now you need to create the domains table.
CREATE TABLE `domains` ( `domain` varchar(200) NOT NULL, `enabled` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`domain`)) ENGINE=MyISAM DEFAULT CHARSET=utf8
In this table you will put all the domains you decide to recive mail for.
Now the alias TABLE:
CREATE TABLE `aliases` ( `email` varchar(128) NOT NULL, `alias` varchar(255) NOT NULL, `enabled` int(11) DEFAULT '1', PRIMARY KEY (`email`)) ENGINE=MyISAM DEFAULT CHARSET=utf8;
This table will contain all your aliases. For example a global address sales@example.com can be routed to both john@example.com, mike@example.com.
Grant privileges to a new user postfix on the whole database.
grant select on mailserver.* to postfix@localhost identified by 'yoursecretpassword'
Add some relevant data in the above tables:
insert into users set email='paperino@vettore.org', password='segretissima', username='paperino'; insert into users set email='pluto@vettore.org', password='segretissima', username='pluto'; insert into domains set domain='vettore.org'; insert into aliases set email='global@vettore.org', alias='pluto@vettore.org, paperino@vettore.org'
This way you have created two mailboxes and a global alias routing to both of them.
Moreover you have just told your server to accept incoming emails for vettore.org domain.
thats’all for the database!
POSTFIX configuration
Postfix already installed and enabled, otherwise:
[root@server03 ~]# yum install postfix ......... [root@server03 ~]# systemctl enable postfix [root@server03 ~]# systemctl start postfix
save your configuration
[root@server03 ~]# cd /etc/postfix [root@server03 ~]# cp main.cf main.cf.orig
Now you can edit your main.cf.
This is a very basic configuration example:
queue_directory = /var/spool/postfix data_directory = /var/lib/postfix mail_owner = postfix #replace with your FQDN myhostname = server03.vettore.org #listen on all interfaces (not only localhost) inet_interfaces = all #enable IPV6 too inet_protocols = all smtpd_helo_required = yes mydestination=localhost unknown_local_recipient_reject_code = 550 mynetworks = 127.0.0.0/8 in_flow_delay = 3s alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases mail_spool_directory = /var/spool/mail #replace with your personal banner smtpd_banner = $myhostname benvenuto sul server di posta della Famiglia Vettore debug_peer_level = 2 debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5 sendmail_path = /usr/sbin/sendmail.postfix newaliases_path = /usr/bin/newaliases.postfix mailq_path = /usr/bin/mailq.postfix html_directory = no #place where virtual databases are located virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-users.cf virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-aliases.cf #delivery transport: dovecot virtual_transport=dovecozz dovecozz_destination_recipient_limit = 1 #user virtual_minimum_uid = 150 virtual_uid_maps = static:150 virtual_gid_maps = static:150
Create system user vmail:vmail with an high uid and gid (150 in the above example) so it won’t interfere with ordinary system users. Create a directory to store incoming emails.
[root@server03 ~]# useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual mailbox" vmail [root@server03 ~]# groupadd -g 150 vmail [root@server03 ~]# mkdir /var/vmail [root@server03 ~]# chown vmail:vmail /var/vmail
For a simple configuration a single user can be enough.
Now you have to create database connectors as stated in the above configuration file.
For example /etc/postfix/mysql-virtual-domains.cf:
user = postfix password = yuorsecretpassword hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM domains WHERE domain='%s' AND enabled=1
This is self-explanatory: when postfix look for a domain name it can find here instructions to connect to the database and query it.
You can test your configuration as follows:
[root@server03 ~]# postmap -q yourdomain.com mysql:/etc/postfix/mysqlvirtualdomains.cf
If youdomain.com is in your domains table it willl return 1.
Similarly you can setup the other two connectors.
/etc/postfix/mysql-virtual-users.cf :
user = postfix password = yoursecretpassword hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM users where email='%s' and enabled=1
/etc/postfix/mysql-virtual-aliases.cf
user = postfix password = yoursecretpassword hosts = 127.0.0.1 dbname = mailserver query = SELECT alias FROM aliases WHERE email='%s' AND enabled=1
Finally, you should tell postfix to use dovecot to deliver local mail.
Add this to your /etc/postfix/master.cf
dovecozz unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
Service name (‘dovecozz’ in this case) must match the configuration in your main.cf (virtual_transport=dovecozz).
DOVECOT installation and configuration
First of all install the packages, activate and start dovecot the service:
[root@server03 ~]# yum install dovecot dovecot-mysql .... [root@server03 ~]# systemctl enable dovecot [root@server03 ~]# systemctl start dovecot
Very few configurations are needed.
In your /etc/dovecot/dovecot.conf add the following lines:
mail_location=maildir:/var/vmail/%d/%n/Maildir mail_uid=vmail mail_gid=vmail first_valid_uid = 150 last_valid_uid = 150
The first line is the most important: it tells dovecot how to store incoming emails.
I have choosen this simple schema: for example email to pippo@vettore.org will be stored in:
/var/vmail/vettore.org/pippo/Maildir/
The other configuration lines simply tell dovecot to use the user vmail we have created above.
Similarly to other services the new dovecot configurations follow the new scheme of the single file in the ./conf.d folder.
So you will find the auth conf in
/etc/dovecot/conf.d/10-auth.conf
You have to tell dovecot to use mysql backend. Edit the above file, comment (adding #) all the !include line at the end of the file.
Than add
!include authmysql.conf.ext
This tells dovecot to look in /etc/dovecot/conf.d/auth-mysql.conf.ext for the auth configuration.
This file doesn’t exist so we have to create it.
After that insert the following lines:
passdb { driver=sql args = /etc/dovecot/dovecot-sql.conf } userdb { driver=static args = uid=150 gid=150 home=/var/vmail/%d/%n allow_all_users=yes }
Please note in the passdb section there is a reference to /etc/dovecot/dovecot-sql.conf .
This is the real connector.
We can create the connector as follows:
/etc/dovecot/dovecot-sql.conf:
driver=mysql default_pass_scheme = PLAIN connect= host=127.0.0.1 port=3306 dbname=mailserver user=postfix password=yoursecretpassword password_query = SELECT password, email as user FROM users where email='%u' AND enabled=1
Please note in the above connector I have stated to use a PLAIN password scheme.
This means your password will be stored in plain text. If U think this can be a security issue you can choose CRAM-MD5, CRYPT or more complex schemes.
Time for test now!
TESTING the configuration
Restart the dovecot and postfix services.
Telnet your server from localhost:
[root@server03 ~]# telnet localhost 25 Trying ::1... Connected to localhost. Escape character is '^]'. 220 server03.vettore.org benvenuto sul server di posta della Famiglia Vettore helo pippolo 250 server03.vettore.org mail from:info@microsoft.com 250 2.1.0 Ok rcpt to:pluto@vettore.org 250 2.1.5 Ok data 354 End data with. subject: test mail from localhost This is the body of the mail . 250 2.0.0 Ok: queued as 7630680FF9A7 quit 221 2.0.0 Bye Connection closed by foreign host. [root@server03 ~]#
If everything went fine, you should find something like this at the end of your /var/log/maillog
Sep 10 15:04:03 server03 postfix/smtpd[23520]: connect from localhost[::1] Sep 10 15:04:34 server03 postfix/smtpd[23520]: 7630680FF9A7: client=localhost[::1] Sep 10 15:05:06 server03 postfix/cleanup[23530]: 7630680FF9A7: messageid=<20140910130434.7630680FF9A7@server03.vettore.org> Sep 10 15:05:06 server03 postfix/qmgr[23074]: 7630680FF9A7: from=, size=378, nrcpt=1 (queue active) Sep 10 15:05:09 server03 postfix/smtpd[23520]: disconnect from localhost[::1] Sep 10 15:05:23 server03 dovecot: lda(pluto@vettore.org): msgid=<20140910130434.7630680FF9A7@server03.vettore.org>: saved mail to INBOX Sep 10 15:05:23 server03 postfix/pipe[23533]: 7630680FF9A7: to= , relay=dovecozz, delay=59, delays=42/0.02/0/16, dsn=2.0.0, status=sent (delivered via dovecozz service) Sep 10 15:05:23 server03 postfix/qmgr[23074]: 7630680FF9A7: removed
You shold find a newly created folders in /var/vmail/vettore.org/pluto/Maildir/ and your incoming mail in /var/vmail/vettore.org/pluto/Maildir/new.
Try the above example replacing the destination with global@vettore.org and check the mail routed to both your alias addresses.
You can try to telnet from a remote host but pay attention to kick or (better) configure your firewallD service. Pay attention: iptables and ip6tables are no longer installed by default!.
The NEXT STEP
In the next articles I will explain how to enable authenticated SMTP with SSL and how to fight SPAM and VIRUSES.
Have fun!
When i go in step:
chown vmail:vmail /var/vmail
there is an error: utilizador inválido
any solution?
I think your error it is the translation for “invalid user”. Check user “vmail” exists in your system!
Sorry my fault! pasting the code from my server the minus (“-“) sign disappeared 🙁
So the useradd and groupadd command were wrong.
Fixed commands:
thank you for your feedback!
Thanks for the help…
In line: useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c
I got the error: useradd: option requires an argument — ‘c’
any solution for this?
The solution is to run useradd and groupadd again with the correct (fixed) syntax.
This way you create user “vmail” and you can chown your dir
In your fix solution you have…
useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c
I think you dont paste all of the code because you miss the name of user (vmail) and the option ‘-c’ i dont understand what do.
I type this (withou option -c and with user ‘vmail’):
useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin vmail
The user was created…
My question is… Is this correct?
and You type “-g mail” is this correct or we need to change to “-g vmail”
Thanks for your help.
You are absolutely right for the truncated line.
The full command is:
The group “mail” is correct. It is the same group of postfix user.
So your command (without -c) is OK.
Thank you for your help in debugging my article.
Hope to do better next time 🙂
At File:/etc/postfix/master.cf
In Line Add this to your /etc/postfix/master.cf
dovecozz unix n n pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver f ${sender} d ${recipient}
When i restart my postfix Service I get the error
bad value “Pipe”
any solution?
Sorry bad code pasted in my article.
The right one is:
dovecozz unix – n n – – pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
Fixed now! Thank you
thanks!
When i restart my service DOVECOT i got the error:
Dovecot: Fatal: Error in configuration file: /etc/dovecot/conf.d/auth-mysql.conf.ext
Line 1: expecting ‘=’
check your syntax.
This is pasted from my working server:
When you are testing and Telnet your server from localhost:… you write:
helo pippolo
what is the meaning of this?
The meaning is “Hello server on localhost! my name is pippolo, how are you?”.
Great work!
Thanks!
Waiting for… The NEXT STEP! 🙂
Hi, thanks for your tutorial.
I have a question, all of my setting is complete but I still can’t sent mail :
when I test to send email via telnet, then I have error status in var/log/maillog
Error dovecot:
“Initialization failed :Namespace ” mkdir(var/vmail/domain.net/user1/Maildir) failed; Permission denied (euid=150(vmail) egid=150(vmail) missing +w perm: /var/vmail, UNIX perms appear ok (ACL/MAC wrong?)) ”
what makes the error ?
Thanks
Your “vmail” user hasn’t write permission on the /var/vmail dir.
try chowning it:
[root@server03 ~]# chown vmail:vmail /var/vmail
It should be ok.
Forse sarà pignoleria ma il comando yum per l’installazione di mariadb va corretto perché manca un trattino:
yum install mariadb mariadbserver non fuzniona
yum install mariadb mariadb-server FUNZIONA
Saluti
Hello i have finished up the tutorial and have setted it up what i have done is i have setted it up with sasl cyrus but the issue here is i cannot receive the mail in inbox for the user from thunderbird
i have done it by setting up a ssl connection but i dont know why its not receiving mail after i send a mail i get a response from the server saying this user is not found by returning the user name… not with domain
Sorry, I dropped Cyrus (and sendmail…) a long time ago.
Moreover this tutorial Is very old