Email with Postfix, Dovecot and MariaDB on CentOS 7
Updated by Linode Written by Linode
In this guide, you’ll learn how to set up a secure virtual user mail server with Postfix, Dovecot, and MariaDB (a drop-in replacement for MySQL) on CentOS 7. We’ll explain how to create new user mailboxes and send or receive email to and from configured domains.
For a different Linux distribution or different mail server, review our email tutorials.
Note About Email at LinodeThis guide may involve or result in sending email. In an effort to fight spam, Linode restricts outbound connections on ports 25, 465, and 587 on all Linodes for new accounts created after November 5th, 2019. For more information, please see Sending Email on Linode.
Before You Begin
Set up the Linode as specified in the Getting Started and Securing Your Server guides.
Verify that the iptables firewall is not blocking any of the standard mail ports (
25
,465
,587
,110
,995
,143
, and993
). If using a different form of firewall, confirm that it is not blocking any of the needed ports.Review the concepts in the Running a Mail Server guide.
Configure DNS
When you’re ready to update the DNS and start sending mail to the server, edit the domain’s MX record so that it points to the Linode’s domain or IP address, similar to the example below:
example.com A 10 12.34.56.78
example.com MX 10 example.com
mail.example.com MX 10 example.com
Make sure that the MX record is changed for all domains and subdomains that might receive email. If setting up a brand new domain, these steps can be performed prior to configuring the mail server. When using Linode’s DNS Manager, create an MX record that points to the desired domain or subdomain, and then create an A record for that domain or subdomain, which points to the correct IP address.
Update Hosts File
Verify that the hosts
file contains a line for the Linode’s public IP address and is associated with the Fully Qualified Domain Name (FQDN). In the example below, 192.0.2.0
is the public IP address, hostname
is the local hostname, and hostname.example.com
is the FQDN.
- /etc/hosts
-
1 2
127.0.0.1 localhost.localdomain localhost 192.0.2.0 hostname.example.com hostname
Install SSL Certificate
You will need to install a SSL certificate on your mail server prior to completing the Dovecot configuration steps. The SSL certificate will authenticate the identity of the mail server to users and encrypt the transmitted data between the user’s mail client and the mail server.
Enable the EPEL repository:
sudo yum install epel-release sudo yum update
Install the Certbot and web server-specific packages, then run Certbot:
sudo yum install python2-certbot-nginx nginx sudo certbot --nginx
Certbot will ask for information about the site. The responses will be saved as part of the certificate:
# sudo certbot --nginx Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator apache, Installer apache Which names would you like to activate HTTPS for? ------------------------------------------------------------------------------- 1: example.com 2: www.example.com ------------------------------------------------------------------------------- Select the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shown (Enter 'c' to cancel):
Certbot will also ask if you would like to automatically redirect HTTP traffic to HTTPS traffic. It is recommended that you select this option.
When the tool completes, Certbot will store all generated keys and issued certificates in the
/etc/letsencrypt/live/$domain
directory, where$domain
is the name of the domain entered during the Certbot certificate generation step.Note
Certbot recommends pointing your web server configuration to the default certificates directory or creating symlinks. Keys and certificates should not be moved to a different directory.Finally, Certbot will update your web server configuration so that it uses the new certificate, and also redirects HTTP traffic to HTTPS if you chose that option.
If you have a firewall configured on your Linode, you can add a firewall rule to allow incoming and outgoing connections to the HTTPS service. On CentOS, firewalld is the default tool for managing firewall rules. Configure firewalld for HTTP and HTTPS traffic:
sudo firewall-cmd --zone=public --permanent --add-service=http sudo firewall-cmd --zone=public --permanent --add-service=https sudo firewall-cmd --reload
Make a note of the certificate and key locations on the Linode. You will need the path to each during the Dovecot configuration steps.
Install Required Packages
Install any outstanding package updates:
yum update
Install the required packages:
yum install postfix dovecot mariadb-server dovecot-mysql
This installs the Postfix mail server, the MariaDB database server, the Dovecot IMAP and POP daemons, and several supporting packages that provide services related to authentication.
Versions
This guide uses the following package versions:
- Postfix 2.10.1
- Dovecot 2.2.10
- MariaDB 5.5.60
MariaDB
In this section you will set up a MariaDB database to store virtual domains, users and passwords. Dovecot and Postfix require this data.
Creating the Database and Tables
Follow the steps below to create the database tables for virtual users, domains and aliases:
Ensure the MariaDb server is running and enabled to start automatically on reboot:
sudo systemctl start mariadb sudo systemctl enable mariadb
Use the mysql_secure_installation tool to configure additional security options. This tool will ask if you want to set a new password for the MySQL root user, but you can skip that step:
sudo mysql_secure_installation
Answer Y at the following prompts:
- Remove anonymous users?
- Disallow root login remotely?
- Remove test database and access to it?
- Reload privilege tables now?
Create a new database:
sudo mysqladmin -u root -p create mailserver
Log in to MySQL:
sudo mysql -u root -p
Create the MySQL user and grant the new user permissions over the database. Replace
mailuserpass
with a secure password:GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1' IDENTIFIED BY 'mailuserpass';
Flush the MySQL privileges to apply the change:
FLUSH PRIVILEGES;
Switch to the new
mailsever
database:USE mailserver;
Create a table for the domains that will receive mail on the Linode:
CREATE TABLE `virtual_domains` ( `id` int(11) NOT NULL auto_increment, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Create a table for all of the email addresses and passwords:
CREATE TABLE `virtual_users` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `password` varchar(106) NOT NULL, `email` varchar(100) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Create a table for the email aliases:
CREATE TABLE `virtual_aliases` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `source` varchar(100) NOT NULL, `destination` varchar(100) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Adding Data
You can now add data to the database and tables that were created in the previous section.
Add the domains to the
virtual_domains
table. Replace the values forexample.com
andhostname
with your own settings:INSERT INTO `mailserver`.`virtual_domains` (`id` ,`name`) VALUES ('1', 'example.com'), ('2', 'hostname.example.com'), ('3', 'hostname'), ('4', 'localhost.example.com');
Note
Note whichid
corresponds to which domain, theid
value is necessary for the next two steps.Add email addresses to the
virtual_users
table. Thedomain_id
value references thevirtual_domain
table’sid
value. Replace the email address values with the addresses that you wish to configure on the mailserver. Replace thepassword
values with strong passwords.INSERT INTO `mailserver`.`virtual_users` (`id`, `domain_id`, `password` , `email`) VALUES ('1', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email1@example.com'), ('2', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email2@example.com');
An email alias will forward all email from one email address to another. To set up an email alias, add it to the
virtual_aliases
table:INSERT INTO `mailserver`.`virtual_aliases` (`id`, `domain_id`, `source`, `destination`) VALUES ('1', '1', 'alias@example.com', 'email1@example.com');
Testing
In the previous section, data was added to the MySQL mailserver
database. The steps below will test that the data has been stored and can be retrieved.
Log in to MySQL:
sudo mysql -u root -p
Check the contents of the
virtual_domains
table:SELECT * FROM mailserver.virtual_domains;
Verify that the output displays the domains you add to the
virtual_domains
table:+----+-----------------------+ | id | name | +----+-----------------------+ | 1 | example.com | | 2 | hostname.example.com | | 3 | hostname | | 4 | localhost.example.com | +----+-----------------------+ 4 rows in set (0.00 sec)
Check the
virtual_users
table:SELECT * FROM mailserver.virtual_users;
Verify that the output displays the email addresses you added to the
virutal_users
table. Your hashed passwords will appear longer than they are displayed below:+----+-----------+-------------------------------------+--------------------+ | id | domain_id | password | email | +----+-----------+-------------------------------------+--------------------+ | 1 | 1 | $6$574ef443973a5529c20616ab7c6828f7 | email1@example.com | | 2 | 1 | $6$030fa94bcfc6554023a9aad90a8c9ca1 | email2@example.com | +----+-----------+-------------------------------------+--------------------+ 2 rows in set (0.01 sec)
Check the
virtual_aliases
table:SELECT * FROM mailserver.virtual_aliases;
Verify that the output displays the aliases you added to the
virtual_aliases
table:+----+-----------+-------------------+--------------------+ | id | domain_id | source | destination | +----+-----------+-------------------+--------------------+ | 1 | 1 | alias@example.com | email1@example.com | +----+-----------+-------------------+--------------------+ 1 row in set (0.00 sec)
If all the desired data displays as expected, exit MySQL:
exit
Postfix
Postfix is a Mail Transfer Agent (MTA) that relays mail between the Linode and the internet. It is highly configurable, allowing for great flexibility. This guide maintains many of Posfix’s default configuration values.
Configuration File Settings
The main.cf
file is the primary configuration file used by Postfix.
Make a copy of the default Postfix configuration file in case you need to revert to the default configuration:
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
Edit the
/etc/postfix/main.cf
file to match the example configurations. Replace occurrences ofexample.com
with your domain name:- /etc/postfix/main.cf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# See /usr/share/postfix/main.cf.dist for a commented, more complete version # Debian specific: Specifying a file name will cause the first # line of that file to be used as the name. The Debian default # is /etc/mailname. #myorigin = /etc/mailname smtpd_banner = $myhostname ESMTP $mail_name (CentOS) biff = no # appending .domain is the MUA's job. append_dot_mydomain = no # Uncomment the next line to generate "delayed mail" warnings #delay_warning_time = 4h readme_directory = no # TLS parameters smtpd_tls_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/example.com/privkey.pem smtpd_use_tls=yes smtpd_tls_auth_only = yes smtp_tls_security_level = may smtpd_tls_security_level = may smtpd_sasl_security_options = noanonymous, noplaintext smtpd_sasl_tls_security_options = noanonymous # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for # information on enabling SSL in the smtp client. smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination myhostname = example.com alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases mydomain = example.com myorigin = $mydomain mydestination = localhost, localhost.$mydomain relayhost = mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all inet_protocols = all # Handing off local delivery to Dovecot's LMTP, and telling it where to store mail virtual_transport = lmtp:unix:private/dovecot-lmtp # Virtual domains, users, and aliases virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf, mysql:/etc/postfix/mysql-virtual-email2email.cf
The
main.cf
file declares the location ofvirtual_mailbox_domains
,virtual_mailbox_maps
,virtual_alias_maps
, andmysql-virtual-email2email
files. These files contain the connection information for the MySQL lookup tables created in the MariaDB section of this guide. Postfix will use this data to identify all domains, corresponding mailboxes, and valid users.Create the file for
virtual_mailbox_domains
. Replace the value forpassword
with your database user’s password. This password was created in the Creating the Database and Tables section. If you used a different name for your databaseuser
anddbname
replace those with your own values:- /etc/postfix/mysql-virtual-mailbox-domains.cf
-
1 2 3 4 5
user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_domains WHERE name='%s'
Create the
/etc/postfix/mysql-virtual-mailbox-maps.cf
file, and enter the following values. Use the database user’s password and make any other changes as needed:- /etc/postfix/mysql-virtual-mailbox-maps.cf
-
1 2 3 4 5
user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_users WHERE email='%s'
Create the
/etc/postfix/mysql-virtual-alias-maps.cf
file and enter the following values. Use the database user’s password and make any other changes as needed:- /etc/postfix/mysql-virtual-alias-maps.cf
-
1 2 3 4 5
user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT destination FROM virtual_aliases WHERE source='%s'
Create the
/etc/postfix/mysql-virtual-email2email.cf
file and enter the following values. Use the database user’s password and make any other changes as needed:- /etc/postfix/mysql-virtual-email2email.cf
-
1 2 3 4 5
user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT email FROM virtual_users WHERE email='%s'
Restart Postfix:
sudo systemctl restart postfix
The
postmap
command creates or queries Postfix’s lookup tables, or updates an existing one. Enter the following command to ensure that Postfix can query thevirtual_domains
table. Replaceexample.com
with the firstname
value. The command should return1
if it is successful:sudo postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
Test Postfix to verify that it can retrieve the first email address from the MySQL table
virtual_users
. Replaceemail1@example.com
with the first email address added to the table. You should receive1
as the output:sudo postmap -q email1@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
Verify that Postfix can retrieve the first email address from the MySQL table
virtual_users
using the database values entered in themysql-virtual-mailbox-maps.cf
file. Replaceemail1@example.com
with the first email address added to the table. You should receive1
as the output:sudo postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-email2email.cf
Test Postfix to verify that it can query the
virtual_aliases
table. Replacealias@example.com
with the firstsource
value created in the table. The command should return thedestination
value for the row:sudo postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cf
Master Program Settings
Postfix’s master program starts and monitors all of Postfix’s processes. The configuration file master.cf
lists all programs and information on how they should be started.
Make a copy of the
/etc/postfix/master.cf
file:sudo cp /etc/postfix/master.cf /etc/postfix/master.cf.orig
Edit
/etc/postfix/master.cf
to contain the values in the excerpt example. The rest of the file can remain unchanged:- /etc/postfix/master.cf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
# # Postfix master process configuration file. For details on the format # of the file, see the master(5) manual page (command: "man 5 master" or # on-line: http://www.postfix.org/master.5.html). # # Do not forget to execute "postfix reload" after editing this file. # # ========================================================================== # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ========================================================================== smtp inet n - n - - smtpd #smtp inet n - - - 1 postscreen #smtpd pass - - - - - smtpd #dnsblog unix - - - - 0 dnsblog #tlsproxy unix - - - - 0 tlsproxy submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_reject_unlisted_recipient=no -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING smtps inet n - - - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING ...
Change the permissions of the
/etc/postfix
directory to restrict permissions to allow only its owner and the corresponding group:sudo chmod -R o-rwx /etc/postfix
Restart Postfix:
sudo systemctl restart postfix
Dovecot
Dovecot is the Mail Delivery Agent (MDA) which is passed messages from Postfix and delivers them to a virtual mailbox. In this section, configure Dovecot to force users to use SSL when they connect so that their passwords are never sent to the server in plain text.
Copy all of the configuration files so you can easily revert back to them if needed:
sudo cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig sudo cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig sudo cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig sudo cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-sql.conf.ext.orig sudo cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig sudo cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig
Edit the
/etc/dovecot/dovecot.conf
file. Uncommentprotocols = imap pop3 lmtp
in the# Protocols we want to be serving.
section of the file:- /etc/dovecot/dovecot.conf
-
1 2 3 4
## Dovecot configuration file ... # Protocols we want to be serving. protocols = imap pop3 lmtp
Edit the
/etc/dovecot/conf.d/10-mail.conf
file. This file controls how Dovecot interacts with the server’s file system to store and retrieve messages.Modify the following variables within the configuration file:
- /etc/dovecot/conf.d/10-mail.conf
-
1 2 3 4 5
... mail_location = maildir:/var/mail/vhosts/%d/%n ... mail_privileged_group = mail ...
Create the
/var/mail/vhosts/
directory and a subdirectory for your domain. Replaceexample.com
with your domain name:sudo mkdir -p /var/mail/vhosts/example.com
This directory will serve as storage for mail sent to your domain.
Create the
vmail
group with ID5000
. Add a new uservmail
to thevmail
group. This system user will read mail from the server.sudo groupadd -g 5000 vmail sudo useradd -g vmail -u 5000 vmail -d /var/mail/
Change the owner of the
/var/mail/
folder and its contents to belong tovmail
:sudo chown -R vmail:vmail /var/mail/
Edit the user authentication file, located in
/etc/dovecot/conf.d/10-auth.conf
. Uncomment the following variables and replace with the file excerpt’s example values:- /etc/dovecot/conf.d/10-auth.conf
-
1 2 3 4 5 6 7 8 9
... disable_plaintext_auth = yes ... auth_mechanisms = plain login ... !include auth-system.conf.ext ... !include auth-sql.conf.ext ...
Edit the
/etc/dovecot/conf.d/auth-sql.conf.ext
file with authentication and storage information. Ensure your file contains the following lines and that they are uncommented:- /etc/dovecot/conf.d/auth-sql.conf.ext
-
1 2 3 4 5 6 7 8 9 10 11
... passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } ... userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n } ...
Create the
/etc/dovecot/dovecot-sql.conf.ext
file and update it with your MySQL connection information. Add the following variables and replace the values with the excerpt example. Replacedbname
,user
andpassword
with your own MySQL database values:- /etc/dovecot/dovecot-sql.conf.ext
-
1 2 3 4
driver = mysql connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass default_pass_scheme = SHA512-CRYPT password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
The
password_query
variable uses email addresses listed in thevirtual_users
table as the username credential for an email account.To use an alias as the username:
- Add the alias as the
source
anddestination
email address to thevirtual_aliases
table. - Change the
/etc/dovecot/dovecot-sql.conf.ext
file’spassword_query
value topassword_query = SELECT email as user, password FROM virtual_users WHERE email=(SELECT destination FROM virtual_aliases WHERE source = '%u');
Change the owner and group of the
/etc/dovecot/
directory tovmail
anddovecot
:sudo chown -R vmail:dovecot /etc/dovecot
Change the permissions on the
/etc/dovecot/
directory to be recursively read, write, and execute for the owner of the directory:sudo chmod -R o-rwx /etc/dovecot
Edit the service settings file
/etc/dovecot/conf.d/10-master.conf
:Note
When editing the file, be careful not to remove any opening or closing curly braces. If there’s a syntax error, Dovecot will crash silently. You can check/var/log/upstart/dovecot.log
to debug the error.Disable unencrypted IMAP and POP3 by setting the protocols’ ports to
0
. Uncomment theport
andssl
variables:- /etc/dovecot/conf.d/10-master.conf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
... service imap-login { inet_listener imap { port = 0 } inet_listener imaps { port = 993 ssl = yes } ... } ... service pop3-login { inet_listener pop3 { port = 0 } inet_listener pop3s { port = 995 ssl = yes } } ...
Find the
service lmtp
section of the file and use the configuration shown below:- /etc/dovecot/conf.d/10-master.conf
-
1 2 3 4 5 6 7 8 9 10
... service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { #mode = 0666i mode = 0600 user = postfix group = postfix } ... }
Locate
service auth
and configure it as shown below:- /etc/dovecot/conf.d/10-master.conf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
... service auth { ... unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } unix_listener auth-userdb { mode = 0600 user = vmail } ... user = dovecot } ...
In the
service auth-worker
section, uncomment theuser
line and set it tovmail
:- /etc/dovecot/conf.d/10-master.conf
-
1 2 3 4 5
... service auth-worker { ... user = vmail }
Save the changes to the
/etc/dovecot/conf.d/10-master.conf
file.Edit
/etc/dovecot/conf.d/10-ssl.conf
file to require SSL and to add the location of your domain’s SSL certificate and key. Replaceexample.com
with your domain:- /etc/dovecot/conf.d/10-ssl.conf
-
1 2 3 4 5 6
... # SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt> ssl = required ... ssl_cert = </etc/letsencrypt/live/example.com/fullchain.pem ssl_key = </etc/letsencrypt/live/example.com/privkey.pem
Restart Dovecot to enable all configurations:
sudo systemctl restart dovecot
Test Your Configuration
NoteGiven the possibility of hosting a large number of virtual domains on a single mail system, the username portion of an email address (i.e. before the@
sign) is not sufficient to authenticate to the mail server. When email users authenticate to the server, they must supply their email clients with the entire email address created above as their username.
Prior to accessing any newly-created email account, a test message needs to be sent to create that user’s mailbox (replace
email1@example.com
with an address that you have configured in your database):yum install mailx mail email1@example.com
Enter a subject and message (optional), then press
Ctrl+D
to complete and send the message.After the test mail is sent, check
/var/log/maillog
to make sure the mail was delivered.tail /var/log/maillog
At the end of the file, you should see something similar to the following:
- /var/log/maillog
-
1 2 3 4
Mar 18 17:18:47 localhost postfix/cleanup[3427]: B624062FA: message-id=<20150318171847.B624062FA@example.com> Mar 18 17:18:47 localhost postfix/qmgr[3410]: B624062FA: from=<root@example.com>, size=515, nrcpt=1 (queue active) Mar 18 17:18:47 localhost postfix/pipe[3435]: B624062FA: to=<email1@example.com>, relay=dovecot, delay=0.14, delays=0.04/0.01/0/0.09, dsn=2.0.0, $ Mar 18 17:18:47 localhost postfix/qmgr[3410]: B624062FA: removed
Now you can test to see what the users of your email server would see with their email clients. To test the
email1@example.com
mailbox, navigate to the mailbox directory/var/mail/vhosts/example.com/email1
and issue the following command:find
You should see output similar to the following:
. ./dovecot-uidvalidity ./new ./maildirfolder ./dovecot.index.cache ./cur ./cur/1539202420.M440788P27259.mail,S=450,W=465:2,S ./dovecot.index.log ./dovecot-uidlist ./dovecot-uidvalidity.5bbe5d50 ./tmp
Test the mailbox by using a simple mail client. For this test, using mutt is recommended. If it is not installed by default, install it with
yum install mutt
, then run:sudo mutt -f .
You may be prompted to create the root mailbox. This is not required.
If there is an email in the inbox, Postfix, Dovecot, and MySQL have been successfully configured! To quit mutt press
q
.
Email Client
You can set up an email client to connect to your mail server. Many clients detect server settings automatically. Manual configuration requires the following parameters:
- Username: The full email address, including the
@example.com
part. - Password: The password that was entered for the email address in the
virtual_users
table of themailuser
database. - Server name: The incoming and outgoing server names must be a domain that resolves to the Linode.
- SSL: Incoming and outgoing servers require authentication and SSL encryption.
- Ports: Use Port
993
for secure IMAP, Port995
for secure POP3, and Port587
with SSL for SMTP.
See Install SquirrelMail on Ubuntu 16.04 for details on installing an email client.
Adding New Domains, Email Addresses, and Aliases
To add new domains, email addresses, and aliases to the mailserver you will need to update the corresponding MySQL tables created in the MySQL section of this guide.
Domains
To add a new domain, connect to your Linode via SSH.
Log in to the MySQL server:
sudo mysql -u root
Enter the root MySQL password when prompted.
View the contents of the table before adding new entries. If you did not use
virtual_domains
as the name of your domain table, replace the value:SELECT * FROM mailserver.virtual_domains;
The output should resemble the following:
+----+-----------------------+ | id | name | +----+-----------------------+ | 1 | example.com | | 2 | hostname.example.com | | 3 | hostname | | 4 | localhost.example.com | +----+-----------------------+
Add a new domain to the table. Replace
newdomain.com
with the desired domain name:INSERT INTO `mailserver`.`virtual_domains` (`name`) VALUES ('newdomain.com');
Verify that the new domain has been added. The output should display the new domain name.
SELECT * FROM mailserver.virtual_domains;
Exit MySQL:
quit
Email Addresses
Log in to the MySQL server:
sudo mysql -u root
When prompted enter the MySQL password.
Verify the contents of the user table. Replace
virtual_users
with your table name:SELECT * FROM mailserver.virtual_users;
The output should resemble the following:
+----+-----------+-------------------------------------+--------------------+ | id | domain_id | password | email | +----+-----------+-------------------------------------+--------------------+ | 1 | 1 | $6$574ef443973a5529c20616ab7c6828f7 | email1@example.com | | 2 | 1 | $6$030fa94bcfc6554023a9aad90a8c9ca1 | email2@example.com | +----+-----------+-------------------------------------+--------------------+ 2 rows in set (0.01 sec)
Add a new email address to the existing table. Replace
newpassword
with the user’s password, andemail3@newdomain.com
with the user’s email address:INSERT INTO `mailserver`.`virtual_users` (`domain_id`, `password` , `email`) VALUES ('5', ENCRYPT('newpassword', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))) , 'email3@newdomain.com');
Note
Thedomain_id
should correspond to theid
value of the domain in thevirtual_domains
table. In the example, we are creating an email address fornewdomain.com
added in the previous section.Verify that the new email address has been added. The new email address should be displayed in the output:
SELECT * FROM mailserver.virtual_users;
Exit MySQL:
quit
Aliases
Log in to the MySQL server:
sudo mysql -u root
When prompted enter the MySQL password.
Verify the contents of the user table. Replace
virtual_users
with your table name:SELECT * FROM mailserver.virtual_aliases;
The output should resemble the following:
+----+-----------+-------------------+--------------------+ | id | domain_id | source | destination | +----+-----------+-------------------+--------------------+ | 1 | 1 | alias@example.com | email1@example.com | +----+-----------+-------------------+--------------------+ 1 row in set (0.00 sec)
Add a new alias. Replace
alias@newdomain.com
with the address to forward email from, andemail1@gmail.com
with the address that you want to forward the mail to. Thealias@newdomain.com
needs to be an email address that already exists on the mail server:INSERT INTO `mailserver`.`virtual_aliases` (`domain_id`, `source`, `destination`) VALUES ('5', 'alias@newdomain.com', 'myemail@gmail.com');
Note
Thedomain_id
should correspond to theid
value of the domain in thevirtual_domains
table. In the example, we are creating an email address fornewdomain.com
added in the previous section.You can create a “catch-all” alias which will forward all emails sent to the matching domain that does not have matching aliases or users. Replace
@newdomain.com
with your domain. This value is the source of the alias.INSERT INTO `mailserver`.`virtual_aliases` (`domain_id`, `source`, `destination`) VALUES ('5', '@newdomain.com', 'myemail@gmail.com');
Verify that the new alias has been added. The new alias will be displayed in the output:
SELECT * FROM mailserver.virtual_aliases;
Exit MySQL:
quit
More Information
You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.
- Troubleshooting Problems with Postfix, Dovecot, and MySQL
- Postfix Basic Configuration
- Postfix SASL Howto
- Dovecot Wiki
Join our Community
Find answers, ask questions, and help others.
This guide is published under a CC BY-ND 4.0 license.