Using Ubuntu to build a personal e-mail server on the public network (based on postfix, dovecot, MySQL)



This tutorial is based on Ubuntu 18.04 (other Linux can be used in theory, and the software packages installed by knowledge are different). The main software used is: postfix, dovecot, mysql. There’s not much nonsense. Here’s the tutorial:


  • Mysql database. In this tutorial, MySQL is used to store domain names, user information, etc.
  • Domain name. Domain name is required to send / receive mail to the public network. Take for example.
  • SSL certificate. There are many free SSL certificate providers, or use self signed certificate, Baidu can.

Installation software

Switch to root and execute the following command:

apt update
apt install postfix postfix-mysql dovecot-core dovecot-pop3d dovecot-imapd dovecot-lmtpd dovecot-mysql

During installation, postfix will pop up a prompt:

Here we choose the second option: Internet site.

Then there will be the following prompt:

Fill in here:

Configure MX resolution

Add the following resolution to the domain name provider:

  • MX record: points to server IP
  • A record: points to server IP
  • A record: points to server IP

Create MySQL database

Create a new database mailserver with the management account of admin / 123456

Create a virtual domain table as the authentication domain. This table is the domain name used by the mail server to receive mail:

-- Establishing tables
CREATE TABLE `virtual_domains` (
`name` VARCHAR(50) NOT NULL,
--Insert a record
insert into virtual_domains values(1,'')

Create a user table for user authentication.

--Create user table
CREATE TABLE `virtual_users` (
`domain_id` INT NOT NULL,
`password` VARCHAR(106) NOT NULL,
`email` VARCHAR(120) NOT NULL,
UNIQUE KEY `email` (`email`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
--Insert two users to encrypt the password with MD5. In practical application, we should choose the algorithm with higher strength. MD5 is not safe at present
insert into virtual_users values(1,1,md5('123456'),'[email protected]');
insert into virtual_users values(2,1,md5('123456'),'[email protected]');

Create a nickname table. The function of this table is to automatically forward the message to the destination when the source receives the message.

-- create table
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,
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE)
--Insert data, all messages sent to first will be forwarded to second automatically
insert into virtual_aliases values(1,1,'[email protected]','[email protected]')

Generate SSL certificate

For SSL certificate generation, please refer to this, assuming the certificate storage address is:

  • Public key / etc / letsencrypt / Live /;
  • Private key / etc / letsencrypt / Live /;

Configure Postfix

First, back up the default configuration file of postfix, and then edit

cp /etc/postfix/ /etc/postfix/
vim /etc/postfix/

Note the following configuration:

Then add the following configuration:

#Use your own SSL certificate
smtpd_tls_auth_only = yes
#Using dovecot for authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination

Modify myhostname and myorigin to the following values:

myhostname =
myorigin = $myhostname

Modify the value of mydestination to localhost to start the virtual domain in MySQL. :

mydestination = localhost

Add the following lines at the end of the configuration file to ensure that messages are delivered to the virtual domains listed in the MySQL table.

virtual_transport = lmtp:unix:private/dovecot-lmtp

Finally, add the following three parameters to inform postfix to configure virtual domain, user and alias

virtual_mailbox_domains = mysql:/etc/postfix/
virtual_mailbox_maps = mysql:/etc/postfix/
virtual_alias_maps = mysql:/etc/postfix/

Next, create the file corresponding to the last three parameters added above.

Create / etc / postfix / MySQL virtual mailbox as follows:

user = admin
password = 123456
port = 3306
hosts =
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

Then restart postfix and test whether postfix can find the domain. If successful, return 1:

service postfix restart
postmap -q mysql:/etc/postfix/

Create / etc / postfix / MySQL virtual mailbox as follows:

user = admin
password = 123456
port = 3306
hosts =
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

Then restart postfix, test whether it can find the email address, and return 1:

service postfix restart
postmap -q [email protected] mysql:/etc/postfix/

Finally, create / etc / postfix / MySQL virtual alias as follows:

user = admin
password = 123456
port = 3306
hosts =
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

Also restart postfix, verify whether the alias can be found correctly, and return:

service postfix restart
postmap -q [email protected] mysql:/etc/postfix/

If the response uses port 587 for my SMTP communication, you need to modify the file / etc / postfix /

Uncomment the following lines:

Configure dovecot

After the configuration of postfix is completed, you can configure dovecot. First, edit the main configuration file / etc / dovecot / dovecot.conf:

First make sure that the following line is enabled:

!include conf.d/*.conf

Then add the following configuration at the end of the configuration file to enable each protocol:

protocols = imap lmtp pop3

Modify / etc / dovecot / conf.d/10-mail.conf to ensure that there are two configurations:

mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = mail

The above configuration sets the mail storage directory in / var / mail, so change the owner of the folder to Vmail / Vmail. The command is as follows:

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

Modify / etc / dovecot / conf.d/10-auth.conf. First, make sure that the following two configurations exist and the values are correct:

disable_plaintext_auth = yes
auth_mechanisms = plain login

Then modify the configuration to disable system user login and enable MySQL support, as shown in the following figure:

Modify the / etc / dovecot / dovecot-sql.conf.ext file to change the content to the following:

passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n

Modify / etc / dovecot / dovecot-sql.conf.ext:

It is preferred to uncomment the driver parameter and set it to MySQL

driver = mysql

Then uncomment the connect line and set it as follows:

connect = host= port=3306 dbname=mailserver user=admin password=123456

Then uncomment the default pass scheme line and change it to MD5

default_pass_scheme = MD5

Then uncomment the password? Query line and set it to the following information:

password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

Finally, change the owner of / etc / dovecot to Vmail: dovecot

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

Modify / etc / dovecot / conf.d/10-master.conf:

First, set the first port under IMAP login and POP3 login to 0 to disable the IMAP and POP3 protocols for non SSL encryption, as shown in the following figure:

Then find service lmtp and modify it as follows:

service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
# Create inet listener only if you can't use the above UNIX socket
#inet_listener lmtp {
# Avoid making LMTP visible for the entire internet
#address =
#port =

Then find service auth and modify its contents as follows:

service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
user = dovecot

Finally, find the service auth worker and change it to the following:

service auth-worker {
# Auth worker process is run as root by default, so that it can access
# /etc/shadow. If this isn't necessary, the user should be changed to
# $default_internal_user.
user = vmail

The last thing to change is / etc / dovecot / conf.d/10-ssl.conf to enable SSL authentication

First, change the SSL parameter to required:

ssl = required

Then set the SSL certificate path to OK, or use the previous SSL certificate:

ssl_cert = </etc/letsencrypt/live/
ssl_key = </etc/letsencrypt/live/

All the configurations are OK here. Restart postfix and dovecot can connect with the mailbox client (such as Foxmail).

service postfix restart
service dovecot restart


It seems very simple to cooperate with a mail client, but actually there are many pits. Just look at the above configuration items, and be patient.

If you can’t log in, you can check the log errors of postfix and dovecot, and then modify them. Log location in / var / log

Be careful:

Puzzled by this problem for several days, I didn’t find a solution, and finally gave up

At present, many host manufacturers do not support the 25 port communication with other servers, known as (Google cloud, Alibaba cloud), which leads to the postfix mail server built on these machines, unable to send mail to other Internet mailboxes, because it is unable to establish a connection with the 25 port of other SMTP servers. It seems that it is to avoid that someone maliciously set up a mail server to send a large number of spam to other mail servers, so that this server IP is listed in SML by anti spam organizations.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.

Recommended Today

DOS batch date command using method

1. System helpC:\>date /? Displays or sets the date. DATE [/T | date] Type date without parameters to display the current date setting and promptYou enter a new date. Press enter to keep the original date. If the command extension is enabled, the date command supports the / t command option, which tellsThe command outputs […]