在 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、不建议直接使用系统自带的
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
打开浏览器,输入 https://mail.example.com/installer/?_step=1 ,回车打开。然后按图片提示进行配置。
配置完成后,关闭浏览器页面。执行以下命令来使安装程序不可用:
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 25
、TCP 465
、TCP 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
- Email with Postfix, Dovecot, and MySQL
- How To Configure a Mail Server Using Postfix, Dovecot, MySQL, and SpamAssassin
- Postfix + Dovecot + MySQL 搭建邮件服务器
- Ubuntu Postfix Mail Server 設定筆記 (一) MTA (SPF, DKIM, rDNS 及 DMARC)
- Debian 8 Server 搭建 Postfix + Dovecot 邮件服务器
- Postfix and TLS encryption
- Postfix Configuration Parameters
- How to install Roundcube
- Running Roundcube 0.7.1 On Nginx (LEMP) On Debian Squeeze/Ubuntu 11.10
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通