在 CentOS 7 上搭建屬於自己的 “完美” 郵件系統


一、前言

為什么要自己搭建郵件系統?
• 自從小學上信息技術課接觸到電子郵件開始,我就對 @ 后面那幾個字母充滿了疑惑,為什么 @ 后面的幾個字母一定要是 qq 、gmail 呢?難道不能自定義嗎?直到初三我弄懂了域名這個概念之后,這個謎團才被解開:我們用的是別人的服務器來使用電子郵件服務。自己有域名當然也可以搭建一個啊!由於當時還基本上沒有雲主機這種東西,而且家里也不讓我整天開着電腦(電信有公網 IP ),所以該計划暫時擱置。直到 2015 年,用 163 郵箱的 Apple ID 大規模被盜(很慶幸我逃過了一劫),我這才明白了自己有個郵箱服務器那是多么重要!恰好高考完了,可以折騰一番了。當時用的是傻瓜式的  macOS Server ,啥原理都不懂,點幾下就搭建成功了,就這樣湊合着用了一年,系統非常穩定,除了停電以及升級系統之外沒有重啟過(這里贊一下  macOS Server )。 macOS Server 最大的缺點就是可以自己定制的功能太少了!現在熟悉了 Linux 的基本操作和服務器的基礎知識,是時候該在 Linux 平台上搭建一個了!
• 其實,Linux 上也有傻瓜式郵件系統, iRedMail 就是其中之一。不過我玩 Linux 的目的就是為了學習服務器以及網絡知識,還是自己搭建一個才能學到東西。

郵件系統所涉及的模塊較多,而且軟件又是不斷更新的,不同 Linux 發行版的系統環境和默認配置文件也可能不相同,想只看一篇教程然后一次完美的幾率太低了。我自己折騰了一個星期,中途也遇到過各種各樣的錯誤,不過好在最后都解決了。所以說,想要自己親手搭建一個完美的郵件系統,耐心是必不可少的。

我把我搭建的整個過程整理一下,步驟盡量精簡,然后寫下了這一篇文章,主要目的是想給大家分享下我的學習經驗,讓新手少走一點彎路,也能給自己增加點印象。所有的步驟(除了域名參數)我在寫完之后都有重裝系統然后全部重新走一遍驗證一次。如果想提高一次成功的幾率,建議使用全新安裝的系統,然后嚴格按照我的步驟要求來做。如有錯誤,請及時留言提出,謝謝!

二、所需軟件 & 環境

  • 操作系統:CentOS 7.3.1611 最小安裝 (已關閉 SELinux 和防火牆)
  • 應用軟件: Postfix 2.10.1 、Dovecot 2.2.10 、MariaDB 5.5.52 、OpenDKIM 2.11.0 、Nginx 1.10.2 、PHP 5.4.16 、Roundcube WebMail 1.3.0
  • 域名(主機名):example.com
  • 公網 IP:1.1.1.1
  • 二級域名mail(這里就是 mail.example.com)的數字證書(推薦免費的 Let’s Encrypt)
說明
1、下文的 MySQL 均代表 MariaDB;
2、Nginx 和 PHP 不做詳細配置,只確保 Webmail 可以正常使用。

三、原理 & 關系圖

下面兩張圖足以說明一切:

說明
• SMTP 是 Postfix 發件的模塊,SMTPD 是 Postfix 收件的模塊,請注意區分。

四、安裝軟件

執行以下命令:

yum -y update && \
yum -y install epel-release && \
yum -y update && \
yum -y install dovecot dovecot-mysql mariadb-server nginx opendkim php-fpm php-mbstring php-mysql php-xml postfix pypolicyd-spf tar wget

若出現密鑰警告,按 y 回車即可。

五、配置 MySQL

5.1 初始化 MySQL

5.1.1 啟動服務

執行以下命令:

systemctl start mariadb

5.1.2 進行安全設置

執行以下命令:

mysql_secure_installation 

然后根據提示操作:

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): # 回車即可
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Set root password? [Y/n] y # 使用密碼驗證
New password: # 設置 root 密碼
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!

# 后面的問題全部按 y 回車,這里省略。

5.2 郵件系統數據庫的創建

注意
• SQL 語句后面要加上分號才能執行。

5.2.1 進入 MySQL 命令行界面

執行以下命令:

mysql -u root -p

然后輸入剛才設置的數據庫 Root 密碼然后按回車。

出現 MariaDB [(none)]> 指示符就說明進入了。

5.2.2 創建一個用戶用於讀取郵件系統數據庫

執行以下 SQL 語句:

CREATE USER 'mail_sys'@'localhost' IDENTIFIED BY 'mail_sys';

5.2.3 創建郵件系統數據庫

執行以下 SQL 語句:

CREATE DATABASE mail_sys;
說明
• 這里的“郵件系統數據庫”並不存儲郵件,只用作域名、用戶、別名的驗證。郵件默認是存儲在  /var/spool/mail 里面的。

5.2.4 為用戶授予讀取權限

執行以下 SQL 語句:

GRANT SELECT ON mail_sys.* TO 'mail_sys'@'localhost' IDENTIFIED BY 'mail_sys';

5.2.5 刷新權限

執行以下 SQL 語句:

FLUSH PRIVILEGES;

5.2.6 進入郵件系統數據庫

執行以下 SQL 語句:

USE mail_sys;

5.2.7 創建域名表

執行以下 SQL 語句:

CREATE TABLE `domains` ( `id` int(20) NOT NULL auto_increment, `name` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.2.8 創建用戶表

執行以下 SQL 語句:

CREATE TABLE `users` ( `id` int(20) NOT NULL auto_increment, `domain_id` int(20) NOT NULL, `password` varchar(200) NOT NULL, `email` varchar(200) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.2.9 創建別名表

執行以下 SQL 語句:

CREATE TABLE `aliases` ( `id` int(20) NOT NULL auto_increment, `domain_id` int(20) NOT NULL, `source` varchar(200) NOT NULL, `destination` varchar(200) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.3 往郵件系統數據庫里添加或刪除域名、用戶、別名

說明
1、為了方便以后添加或刪除,下面我把 SQL 語句(命令)的格式寫出來;
2、索引號從 1 開始依次遞增,需手動指定;
3、由於密碼需要使用 SQL 語句進行 SHA512 運算來存儲散列值,因此圖形化數據庫管理工具可能無法實現;
4、當添加多行數據時,非末行的行分隔符為逗號,直到末行才使用分號。

5.3.1 添加或刪除域名

添加域名

INSERT INTO `mail_sys`.`domains` (`id` ,`name`) 
VALUES ('<域名索引號>', '<域名>');

例如:

MariaDB [mail_sys]> INSERT INTO `mail_sys`.`domains` (`id` ,`name`) 
    -> VALUES ('1', 'example.com');

刪除域名

DELETE FROM `mail_sys`.`domains` WHERE `id`='<域名索引號>';

5.3.2 添加或刪除用戶

添加用戶

INSERT INTO `mail_sys`.`users`
(`id`, `domain_id`, `password` , `email`) VALUES
('<用戶索引號>', '<域名索引號>', ENCRYPT('<密碼>', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), '<郵箱地址>'),
('<用戶索引號>', '<域名索引號>', ENCRYPT('<密碼>', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), '<郵箱地址>'),
('<用戶索引號>', '<域名索引號>', ENCRYPT('<密碼>', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), '<郵箱地址>');

例如:

MariaDB [mail_sys]> INSERT INTO `mail_sys`.`users`
    -> (`id`, `domain_id`, `password` , `email`) VALUES
    -> ('1', '1', ENCRYPT('12345678', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user1@example.com'),
    -> ('2', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user2@example.com'),
    -> ('3', '1', ENCRYPT('11111111', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user3@example.com');
#以后再繼續添加用戶名的時候,用戶索引就應該從4開始,下同。

刪除用戶

DELETE FROM `mail_sys`.`users` WHERE `id`='<用戶索引號>';

5.3.3 添加或刪除別名(可選)

說明
• 別名的意思就比如說:設置  user1@example.com 的別名是  user11@example.com ,那么其他人往  user11@example.com 里發送郵件時,郵件就會到  user1@example.com 的郵箱里去。

添加別名

INSERT INTO `mail_sys`.`aliases`
(`id`, `domain_id`, `source`, `destination`) VALUES
('<別名索引號>', '<域名索引號>', '<別名地址>', '<目的地址>'),
('<別名索引號>', '<域名索引號>', '<別名地址>', '<目的地址>'),
('<別名索引號>', '<域名索引號>', '<別名地址>', '<目的地址>');

例如:

MariaDB [mail_sys]> INSERT INTO `mail_sys`.`aliases`
    -> (`id`, `domain_id`, `source`, `destination`) VALUES
    -> ('1', '1', 'user11@example.com', 'user1@example.com'),
    -> ('2', '1', 'user22@example.com', 'user2@example.com'),
    -> ('3', '1', 'user33@example.com', 'user3@example.com');

刪除別名

DELETE FROM `mail_sys`.`aliases` WHERE `id`='<別名索引號>';

5.4 檢查數據庫

5.4.1 檢查域名表

執行以下 SQL 語句:

SELECT * FROM mail_sys.domains;

若出現以下格式的輸出結果,說明設置正確。

+----+-------------+
| id | name        |
+----+-------------+
|  1 | example.com |
+----+-------------+
1 row in set (0.00 sec)

5.4.2 檢查用戶表

執行以下 SQL 語句:

SELECT * FROM mail_sys.users;

若出現以下格式的輸出結果,說明設置正確。

+----+-----------+------------------------------------------------------------------------------------------------------------+-------------------+
| id | domain_id | password                                                                                                   | email             |
+----+-----------+------------------------------------------------------------------------------------------------------------+-------------------+
|  1 |         1 | $6$afbdd821f68a3f27$QH9yDKslGZMNZjzvBBvMtYXzzclbnNgb1AhmB7lqu6fj6PU04QTgCTvcvPwqsAaW6mJt9kcKPicN0VCQGalg5/ | user1@example.com |
|  2 |         1 | $6$a4f819161bd19901$oeDntXEyiY6RiM369ugKZrMfsK6yeV3CG/fhFF4ruPJImLCyzi2hR/PX8f2nBDBRWiMvWv7zWiNv5yEruRsW// | user2@example.com |
|  3 |         1 | $6$2a85aaab0ec76f64$KRQ2H8Zgn0YjTzDDnfwqim3mZynZ05iPMZ1GQPw7GNuJApcXuLi5LOmR9yDC6Jh2eAKbhuG4lgHG.I5FdIrf4. | user3@example.com |
+----+-----------+------------------------------------------------------------------------------------------------------------+-------------------+
3 rows in set (0.00 sec)

5.4.3 檢查別名表(可選)

執行以下 SQL 語句:

SELECT * FROM mail_sys.aliases;

若出現以下格式的輸出結果,說明設置正確。

+----+-----------+--------------------+-------------------+
| id | domain_id | source             | destination       |
+----+-----------+--------------------+-------------------+
|  1 |         1 | user11@example.com | user1@example.com |
|  2 |         1 | user22@example.com | user2@example.com |
|  3 |         1 | user33@example.com | user3@example.com |
+----+-----------+--------------------+-------------------+
3 rows in set (0.00 sec)

數據庫設置完成。按 Ctrl + D 退出 MySQL 命令行界面。

六、設置郵件系統專用用戶

說明
1、所有的郵件用戶都映射到系統的同一個真實的用戶上;
2、不建議直接使用系統自帶的  mail 賬戶。

6.1 創建郵件系統專用組

執行以下命令:

groupadd -g 2000 mail_sys

6.2 創建郵件系統專用用戶

執行以下命令:

useradd -g mail_sys -u 2000 mail_sys -d /var/spool/mail -s /sbin/nologin

6.3 修改郵件目錄所有者

執行以下命令:

chown -R mail_sys:mail_sys /var/spool/mail

七、配置 Postfix

7.1 備份原版配置文件

執行以下命令:

cp -r /etc/postfix /etc/postfix.bak

7.2 修改 main.cf

說明
• 該文件配置 Postfix 的全局參數。

執行以下命令:

cat > /etc/postfix/main.cf << EOF

請按實際情況以及注釋提示修改以下內容,完成后去除 # 號和后面的注釋,然后粘貼到命令行窗口中按回車即可。

mydomain = example.com # 您的域名,需要修改
myhostname = mail.example.com # 您的域名前面加上 mail. 需要修改
mydestination = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mynetworks = 127.0.0.0/8
mailbox_size_limit = 0
recipient_delimiter = +
inet_protocols = all
inet_interfaces = all
smtp_address_preference = ipv4
smtpd_banner = ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no
virtual_transport = lmtp:unix:private/dovecot-lmtp
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
virtual_mailbox_domains = mysql:/etc/postfix/mysql_mailbox_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_mailbox_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_alias_maps.cf
smtpd_sender_login_maps = mysql:/etc/postfix/mysql_mailbox_maps.cf, mysql:/etc/postfix/mysql_alias_maps.cf
disable_vrfy_command = yes
strict_rfc821_envelopes = yes
smtpd_sender_restrictions = reject_non_fqdn_sender, reject_unknown_sender_domain, reject_sender_login_mismatch
smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/policyd-spf
virtual_uid_maps = static:2000
virtual_gid_maps = static:2000
message_size_limit = 102400000
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtpd_tls_cert_file=/etc/pki/tls/certs/cert.pem # mail.example.com 證書文件位置,需要修改
smtpd_tls_key_file=/etc/pki/tls/private/key.pem # mail.example.com 證書私鑰文件位置,需要修改
smtpd_tls_session_cache_database = btree:\${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:\${data_directory}/smtp_scache
smtpd_tls_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_mandatory_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_ciphers = high
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtpd_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtp_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtp_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
tls_preempt_cipherlist = yes
smtpd_tls_received_header = yes
policyd-spf_time_limit = 3600
EOF

7.3 修改 master.cf

說明
• 該文件配置 Postfix 中各模塊的參數。

執行以下命令:

cat > /etc/postfix/master.cf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

smtp      inet  n       -       n       -       -       smtpd
submission inet n       -       n       -       -       smtpd
       -o smtpd_tls_security_level=encrypt
smtps     inet  n       -       n       -       -       smtpd
       -o smtpd_tls_wrappermode=yes
pickup    unix  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
       -o smtp_helo_timeout=120 -o smtp_connect_timeout=120
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
policyd-spf    unix  -       n       n       -       0       spawn
       user=mail_sys argv=/usr/libexec/postfix/policyd-spf
EOF

7.4 與 MySQL 對接

7.4.1 指定域名數據表

執行以下命令:

cat > /etc/postfix/mysql_mailbox_domains.cf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

user = mail_sys
password = mail_sys
hosts = localhost
dbname = mail_sys
query = SELECT 1 FROM domains WHERE name='%s'
EOF

7.4.2 指定用戶數據表

執行以下命令:

cat > /etc/postfix/mysql_mailbox_maps.cf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

user = mail_sys
password = mail_sys
hosts = localhost
dbname = mail_sys
query = SELECT email FROM users WHERE email='%s'
EOF

7.4.3 指定別名數據表

執行以下命令:

cat > /etc/postfix/mysql_alias_maps.cf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

user = mail_sys
password = mail_sys
hosts = localhost
dbname = mail_sys
query = SELECT destination FROM aliases WHERE source='%s'
EOF

7.5 測試數據庫讀取

7.5.1 啟動 Postfix 服務

執行以下命令:

systemctl start postfix

7.5.2 測試域名數據表的讀取

下面的 example.com 請替換為自己設定的域名。

執行以下命令:

postmap -q example.com mysql:/etc/postfix/mysql_mailbox_domains.cf

若返回 1,則說明設置正確。

7.5.3 測試用戶數據表的讀取

下面的 user2@example.com 請替換為自己設定的用戶名的其中一個。

執行以下命令:

postmap -q user2@example.com mysql:/etc/postfix/mysql_mailbox_maps.cf

若返回用戶名,則說明設置正確。

7.5.4 測試別名數據表的讀取(可選)

下面的 user11@example.com 請替換為自己設定的別名其中一個。

執行以下命令:

postmap -q user11@example.com mysql:/etc/postfix/mysql_alias_maps.cf

若返回別名所對應的真實用戶名,則說明設置正確。

7.5.5 停止 Postfix 服務

等全部配置完成后再啟動。

執行以下命令:

systemctl stop postfix

八、配置 Dovecot

8.1 備份原版配置文件

執行以下命令:

cp -r /etc/dovecot /etc/dovecot.bak

8.2 修改 dovecot.conf

說明
• 該文件配置 Dovecot 的全局參數。

執行以下命令:

cat > /etc/dovecot/dovecot.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

protocols = imap lmtp
dict {
}
!include conf.d/*.conf
!include_try local.conf
EOF

8.3 修改 conf.d/10-mail.conf

說明
• 該文件配置郵箱文件存儲的位置和命名空間。

執行以下命令:

cat > /etc/dovecot/conf.d/10-mail.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

namespace inbox {
  inbox = yes
}
first_valid_uid = 1000
mbox_write_locks = fcntl
mail_location = maildir:/var/spool/mail/%d/%n
mail_privileged_group = mail
EOF

8.4 修改 conf.d/15-mailboxes.conf

說明
• 該文件配置郵箱內部的目錄結構。

執行以下命令:

cat > /etc/dovecot/conf.d/15-mailboxes.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

namespace inbox {
  mailbox Drafts {
    auto = create
    special_use = \Drafts
  }
  mailbox Trash {
    auto = create
    special_use = \Trash
  }
  mailbox Sent {
    auto = create
    special_use = \Sent
  }
}
EOF

8.5 修改 conf.d/10-auth.conf

說明
• 該文件配置用戶身份認證流程。

執行以下命令:

cat > /etc/dovecot/conf.d/10-auth.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

auth_mechanisms = plain login
!include auth-sql.conf.ext
EOF

8.6 修改 conf.d/auth-sql.conf.ext

說明
• 該文件配置數據庫認證的參數。

執行以下命令:

cat > /etc/dovecot/conf.d/auth-sql.conf.ext << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = static
  args = uid=mail_sys gid=mail_sys home=/var/spool/mail/%d/%n
}
EOF

8.7 修改 dovecot-sql.conf.ext

說明
• 該文件配置驗證用戶名密碼所用的數據表以及認證方法。

執行以下命令:

cat > /etc/dovecot/dovecot-sql.conf.ext << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

driver = mysql
connect = host=localhost dbname=mail_sys user=mail_sys password=mail_sys
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';
EOF

8.8 修改 conf.d/10-ssl.conf

說明
• 該文件配置 SSL 加密參數。

執行以下命令:

cat > /etc/dovecot/conf.d/10-ssl.conf << EOF

請按實際情況以及注釋提示修改以下內容,完成后去除 # 號和后面的注釋,然后粘貼到命令行窗口中按回車即可。

ssl = required
ssl_cert = </etc/pki/tls/certs/cert.pem # mail.example.com 證書文件位置,需要修改
ssl_key = </etc/pki/tls/private/key.pem # mail.example.com 證書私鑰文件位置,需要修改
ssl_protocols = TLSv1.2 TLSv1.1 !TLSv1 !SSLv2 !SSLv3
ssl_cipher_list = ALL:!MD5:!DES:!ADH:!RC4:!PSD:!SRP:!3DES:!eNULL:!aNULL
EOF

8.9 修改 conf.d/10-master.conf

說明
• 該文件配置 Dovecot 中各服務的主要參數。

執行以下命令:

cat > /etc/dovecot/conf.d/10-master.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service lmtp {
    unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service imap {

}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

  unix_listener auth-userdb {
    mode = 0600
    user = mail_sys
  }
  user = dovecot
}

service auth-worker {
  user = mail_sys
}
EOF

8.10 修改 conf.d/15-lda.conf

說明
1、該文件配置特定域的 postmaster 郵箱;
2、我自己沒有修改這個配置文件。但是根據部分網友反饋,如果不設定 postmaster 郵箱的話會導致收不到郵件,所以還是加上去吧。

執行以下命令:

cat > /etc/dovecot/conf.d/15-lda.conf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

postmaster_address = postmaster@%d

protocol lda {
}
EOF

九、配置 OpenDKIM

9.1 修改 OpenDKIM 配置文件

執行以下命令:

cat > /etc/opendkim.conf << EOF

請按實際情況以及注釋提示修改以下內容,完成后去除 # 號和后面的注釋,然后粘貼到命令行窗口中按回車即可。

Syslog yes
UMask 002
OversignHeaders From
Socket inet:8891@127.0.0.1
Domain example.com # 您的域名,需要修改
KeyFile /etc/opendkim/keys/mail.private
Selector mail
RequireSafeKeys no
EOF

9.2 生成私鑰

下面的 example.com 請替換成您的域名。

執行以下命令:

opendkim-genkey -D /etc/opendkim/keys/ -d example.com -s mail && \
chown -R opendkim:opendkim /etc/opendkim/keys/

9.3 配置 Postfix 的 main.cf

配置發件增加 DKIM 簽名。

執行以下命令:

cat >> /etc/postfix/main.cf << EOF

以下內容直接粘貼到命令行窗口中按回車即可。

milter_protocol = 2
milter_default_action = accept
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:127.0.0.1:8891
EOF

9.4 啟動所有服務

執行以下命令:

systemctl start postfix dovecot opendkim

如需開機啟動,請執行以下命令:

systemctl enable postfix dovecot opendkim mariadb

十、配置域名記錄

以下項目需要在域名服務商或雲主機服務商的控制面板中設置。下文的域名服務商以 DNSPOD 為例,其他域名服務商或雲主機服務商請自行參閱相關說明文檔。

10.1 A 記錄的設定

在域名控制面板中添加一條記錄,主機記錄填 @ ,記錄類型選 A 記錄值填 1.1.1.1 ,其他保持默認,保存即可。

10.2 MX 記錄的設定

在域名控制面板中添加一條記錄,主機記錄填 @ ,記錄類型選 MX ,記錄值填 mail.example.com,其他保持默認;
再添加一條記錄,主機記錄填 mail ,記錄類型選 A ,記錄值填 1.1.1.1,其他保持默認,保存即可。

10.3 SPF 記錄的設定

在域名控制面板中添加一條記錄,主機記錄填 @ ,記錄類型選 TXT ,記錄值填 v=spf1 mx -all,其他保持默認,保存即可。

10.4 DMARC 記錄的設定

在域名控制面板中添加一條記錄,主機記錄填 _dmarc ,記錄類型選 TXT ,記錄值填 v=DMARC1; p=reject,其他保持默認,保存即可。

10.5 DKIM 記錄的設定

(以我的密鑰文件為例)

執行以下命令:

cat /etc/opendkim/keys/mail.txt 

會出現以下結果:

mail._domainkey IN  TXT ( "v=DKIM1; k=rsa; "
      "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU5nkxbS36hOa2FCJqotvahTbxb83CvLt5XqV4WAPzJQmfaA1eHyvOz9XiZgE8vWRgP2jJFlL+J4yEroB3YV/8EBjAM8lFTi31DVgRsoHMwH6f3GuLAfcuVofymDfRxHxPzIlm7rgzfWwrGcPrIzt64NLuZG4yusTWp8MTfWZxvQIDAQAB" )  ; ----- DKIM key default for example.com

把括號內的值復制出來,去掉所有引號並整理成一行,形如:

v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU5nkxbS36hOa2FCJqotvahTbxb83CvLt5XqV4WAPzJQmfaA1eHyvOz9XiZgE8vWRgP2jJFlL+J4yEroB3YV/8EBjAM8lFTi31DVgRsoHMwH6f3GuLAfcuVofymDfRxHxPzIlm7rgzfWwrGcPrIzt64NLuZG4yusTWp8MTfWZxvQIDAQAB

在域名控制面板中添加一條記錄,主機記錄填 mail._domainkey ,記錄類型選 TXT ,記錄值填 v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU5nkxbS36hOa2FCJqotvahTbxb83CvLt5XqV4WAPzJQmfaA1eHyvOz9XiZgE8vWRgP2jJFlL+J4yEroB3YV/8EBjAM8lFTi31DVgRsoHMwH6f3GuLAfcuVofymDfRxHxPzIlm7rgzfWwrGcPrIzt64NLuZG4yusTWp8MTfWZxvQIDAQAB ,其他保持默認,保存即可。

上述五個步驟完成后域名控制面板的效果如下圖:

10.6 IP 反向解析

這個……普通家庭寬帶用戶就別想了,企業寬帶和國內雲主機用戶需要網站通過備案才能設置。如果用國外雲主機的話,有些可以支持(我使用的 Vultr 支持)。將服務器的 IP 地址反向解析(PTR 記錄)到 MX 域名(這里就是 mail.example.com)可以大幅降低外發郵件被拒收的幾率。

十一、配置 Web 郵箱

11.1 下載並安裝 Roundcube

11.1.1 下載

執行以下命令:

wget https://github.com/roundcube/roundcubemail/releases/download/1.3.0/roundcubemail-1.3.0-complete.tar.gz

11.1.2 解壓 & 安裝

執行以下命令:

tar -xf roundcubemail-1.3.0-complete.tar.gz && \
mv roundcubemail-1.3.0 /usr/share/roundcube && \
chown -R apache:apache /usr/share/roundcube

11.2 配置 Nginx 、PHP

11.2.1 配置 Nginx

執行以下命令:

vi /etc/nginx/conf.d/mail.conf

請按實際情況以及注釋提示修改以下內容,在命令行窗口按下 i ,將內容直接粘貼到命令行窗口中,再按下 ESC ,最后輸入 :wq 按回車。

server {
    listen       80;
    server_name  mail.example.com; # 您的域名前面加上 mail. 需要修改
    return 301 https://$server_name$request_uri;
}

server {
    listen       443 ssl http2;
    server_name  mail.example.com; # 您的域名前面加上 mail. 需要修改
    ssl_certificate "/etc/pki/tls/certs/cert.pem"; # mail.example.com 證書文件位置,需要修改
    ssl_certificate_key "/etc/pki/tls/private/key.pem"; # mail.example.com 證書私鑰文件位置,需要修改
    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains";
    location / {
     root         /usr/share/roundcube;
     index        index.php;     
    }   
    location ~ .php$ {
        root         /usr/share/roundcube;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

11.2.2 配置 PHP

設置時區

執行以下命令:

echo "date.timezone = Asia/Shanghai" >> /etc/php.ini 

創建會話文件夾

執行以下命令:

mkdir /var/lib/php/session && \
chown apache:apache /var/lib/php/session

11.3 配置數據庫

11.3.1 進入 MySQL 命令行界面

執行以下命令:

mysql -u root -p

然后輸入 5.1.2 設置的數據庫 Root 密碼然后按回車。

出現 MariaDB [(none)]> 指示符就說明進入了。

11.3.2 創建一個用戶用於讀寫 Roundcube 數據庫

執行以下 SQL 語句:

CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'roundcube';

11.3.3 創建 Roundcube 數據庫

執行以下 SQL 語句:

CREATE DATABASE roundcube;

11.3.4 為用戶授予讀寫權限

執行以下 SQL 語句:

GRANT ALL ON roundcube.* TO 'roundcube'@'localhost' IDENTIFIED BY 'roundcube';

11.3.5 刷新權限

執行以下 SQL 語句:

FLUSH PRIVILEGES;

數據庫設置完成。按 Ctrl + D 退出 MySQL 命令行界面。

11.4 啟動服務

執行以下命令:

systemctl start nginx php-fpm

如需開機啟動,請執行以下命令:

systemctl enable nginx php-fpm

11.5 配置 Roundcube

打開瀏覽器,輸入  ,回車打開。然后按圖片提示進行配置。

配置完成后,關閉瀏覽器頁面。執行以下命令來使安裝程序不可用:

chmod -R 000 /usr/share/roundcube/installer/

11.6 登錄

打開瀏覽器,輸入 https://mail.example.com ,然后輸入您的用戶名密碼登錄。

登錄之后,默認只會有一個收件箱,我們再設置一下就完美了!

最終效果如下圖:

十二、收發件測試

12.1 收件測試

非常簡單,從 QQ 或者 Gmail 給自己的郵箱發一封郵件,如果可以收到,說明外網已經可以連通這台服務器了。

12.2 發件測試

打開瀏覽器,輸入 http://www.mail-tester.com ,回車打開。發一封郵件到它指定的郵箱里。然后過一分鍾左右查看下結果,重點檢查 SPF 記錄、DMARC 記錄和 DKIM 簽名是不是有效的。如果都是有效的,那恭喜您!您的郵件系統已經搭建完了!至於這個得分,由於受 IP 地址可能被拉黑的影響,因此各人的分數有可能不同。如果有 8 分以上的話發出去的郵件基本上就不會被拒收了。如果很不幸 IP 地址被拉黑了,建議換一個 IP 地址。

十三、防火牆的設置(可選)

如果服務器需要部署防火牆,請放行 TCP 25TCP 465TCP 587 以及 TCP 993 這四個端口的傳入鏈接。

以 iptables 為例,配置命令為:

iptables -A INPUT -p tcp -m multiport --dports 25,465,587,993 -j ACCEPT

然后根據需要自行保存防火牆的配置。

十四、不完美的地方 & 總結

  • 之所以標題上的完美打了個雙引號,原因之一是本來我計划配置垃圾郵件過濾功能的,但是不知道是不是我設置錯誤還是網絡問題,很多非垃圾郵件都被拒收了,在網上搜索了兩天還是無解,所以暫時放棄。(PS :幾個月前我用過一次 iRedMail ,里面的垃圾郵件過濾模塊也同樣導致很多非垃圾郵件被拒收,所以我感覺網絡問題大一些。)
  • 此外,這個郵件系統並沒有實現使用 Web 界面管理郵件系統(如增減用戶)的功能,由於我搭建的郵件系統只有我一個人在用,所以也就不折騰啦。
  • 最后非常感謝能夠耐心讀完這篇文章的人,希望您有所收獲!

十五、參考文獻

文章來源:https://zhuanlan.zhihu.com/p/28816035

  1. Email with Postfix, Dovecot, and MySQL
  2. How To Configure a Mail Server Using Postfix, Dovecot, MySQL, and SpamAssassin
  3. Postfix + Dovecot + MySQL 搭建郵件服務器
  4. Ubuntu Postfix Mail Server 設定筆記 (一) MTA (SPF, DKIM, rDNS 及 DMARC)
  5. Debian 8 Server 搭建 Postfix + Dovecot 郵件服務器
  6. Postfix and TLS encryption
  7. Postfix Configuration Parameters
  8. How to install Roundcube
  9. Running Roundcube 0.7.1 On Nginx (LEMP) On Debian Squeeze/Ubuntu 11.10


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM