自建邮件服务器教程
准备工作
首先需要设置好主机名并申请好证书
测试服务器25端口是否可以发信
测试25端口出站方向是否开放,出站方向的25端口打开,才能通过自己的服务器发送邮件。
(base) echo@neko:~$ telnet smtp.qq.com 25
Trying 2402:4e00:8012:58::40...
Connected to smtp.qq.com.
Escape character is '^]'.
220 newxmesmtplogicsvrsza7.qq.com XMail Esmtp QQ Mail Server.
^]
telnet> close
Connection closed.
telnet
命令行的使用可以参考帖子
主机名设置
需要设置/etc/hosts
和/etc/hostname
这两个与主机名相关的文件,文件内容如下图
# /etc/hosts,xx.xx.xx.xx是你服务器的公网IP
127.0.0.1 localhost
xx.xx.xx.xx mail.example.org mail
# /etc/hostname
mail
终端执行hostname -F /etc/hostname
更新主机名,最后短主机名和FQDN均正常就没有问题
root@mail:~# hostname -F /etc/hostname
root@mail:~$ hostname
mail
root@mail:~$ hostname -f
mail.example.org
DNS记录
去你的服务器提供商或者DNS服务商增加DNS记录
- 添加一个A记录,主机记录名与下一步对应,即
mail.example.org
或者mx.example.org
,IP填你的邮件服务器的IP。 - 增加一个MX记录,一般MX记录设置为
mail.example.org
或者mx.example.org
,不过你也设置为其他的。 添加CNAME记录,这一步是可选步骤,一般会增加下面三个CNAME记录,均指向第一步的
mail.example.org
或者mx.example.org
。imap.example.org pop.example.org smtp.example.org
申请ssl证书
申请通配符证书/泛域名证书,我由于服务器也在使用lnmp建站,直接使用的lnmp工具申请的证书。本质也还是使用acme.sh
申请证书,这个自行研究吧。
建立数据库并插入用户
执行下面的SQL建库建表,用于邮箱登录认证,并插入数据,建议插入[email protected]
用户,具体原因下面再说。
create database mailsys;
use mailsys;
CREATE TABLE `virtual_domains` (
`id` int NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `virtual_users` (
`id` int NOT NULL auto_increment,
`domain_id` int 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=utf8mb4;
CREATE TABLE `virtual_aliases` (
`id` int NOT NULL auto_increment,
`domain_id` int 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=utf8mb4;
insert into virtual_domains(id,name) values(1,'example.org');
insert into virtual_domains(id,name) values(2,'mail.example.org');
# mysql8 中使用
insert into virtual_users(id,domain_id,password,email) values (1,1,left(TO_BASE64(UNHEX(SHA2('13456', 512))),12),'[email protected]');
insert into virtual_users(id,domain_id,password,email) values (1,2,left(TO_BASE64(UNHEX(SHA2('13456', 512))),12),'[email protected]');
# mysql5 中使用
insert into virtual_users(id,domain_id,password,email) values (1,1,ENCRYPT('654321'),'[email protected]');
insert into virtual_users(id,domain_id,password,email) values (1,2,ENCRYPT('123456'),'[email protected]');
insert into virtual_aliases(id,domain_id,source,destination) values (1,1,'[email protected]','[email protected]');
insert into virtual_aliases(id,domain_id,source,destination) values (2,1,'[email protected]','[email protected]');
需要注意的是,MySQL5.7版本之后,ENCRYPT()
函数被弃用,所以密码加密方式稍有区别,下文进行dovecot登录验证设置的时候需要与此对应。
创建邮件系统专用用户并设置邮件文件夹权限
groupadd -g 2000 vmail
useradd -g vmail -u 2000 vmail -d /var/mail/ -s /sbin/nologin
# 设置邮件存储目录权限
ll /var/mail/
chown -R vmail:vmail /var/mail/
ll /var/mail/
邮箱服务器搭建
MTA
MTA (Mail Transfer Agent) 是邮件传输代理,其工作职责是转发处理不同电子邮件服务供应商之间的邮件,把来自于MUA的邮件转发到合适的MTA服务器。
安装Postfix: sudo apt-get install postfix postfix-mysql postfix-doc
安装过程中的配置选项:
mail configuration: Internet Site
System mail name: example.org
安装完成之后,修改/etc/postfix/main.cf
文件,
# TLS parameters
smtpd_tls_cert_file=********.cer
smtpd_tls_key_file=********.key
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
# smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
# smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
# smtp config
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
message_size_limit = 15728640
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
smtpd_helo_restrictions = permit_mynetworks permit_sasl_authenticated reject_invalid_helo_hostname reject_non_fqdn_helo_hostname
smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_non_fqdn_recipient reject_unknown_recipient_domain reject_unlisted_recipient reject_unauth_destination
smtpd_sender_restrictions = permit_mynetworks permit_sasl_authenticated reject_non_fqdn_sender reject_unknown_sender_domain
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
# host config
myhostname = mail.example.org
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = localhost
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
html_directory = /usr/share/doc/postfix/html
# lmtp
virtual_transport = lmtp:unix:private/dovecot-lmtp
# MySQL
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的相关信息
# nano /etc/postfix/mysql-virtual-mailbox-domains.cf
user = username
password = yourpassword
hosts = 127.0.0.1
dbname = mailsys
query = SELECT 1 FROM virtual_domains WHERE name='%s'
# nano /etc/postfix/mysql-virtual-mailbox-maps.cf
user = username
password = yourpassword
hosts = 127.0.0.1
dbname = mailsys
query = SELECT 1 FROM virtual_users WHERE email='%s'
# nano /etc/postfix/mysql-virtual-alias-maps.cf
user = username
password = yourpassword
hosts = 127.0.0.1
dbname = mailsys
query = SELECT destination FROM virtual_aliases WHERE source='%s'
重启postfix并验证是否可以正常连接数据库systemctl restart postfix
postmap -q example.org mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
1
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
1
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-alias-maps.cf
[email protected]
配置 /etc/postfix/master.cf
,去掉里面 submission和smtps所在的两行所属配置项的注释。
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_helo_restrictions=$mua_helo_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_helo_restrictions=$mua_helo_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_recipient_restrictions=
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
配置文件夹权限chmod -R o-rwx /etc/postfix
MDA
MDA (Mail Delivery Agent) 是邮件投递代理,是一个用于保存用户邮件的“信箱”服务器,其工作职责是把来自于 MTA 的邮件保存到本地的收件箱中。
安装Dovecot并设置配置文件目录权限
sudo apt-get install dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql
chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
Dovecot的配置文件有一点点多:
修改
/etc/dovecot/dovecot.conf
配置文件,该文件配置 Dovecot 的全局参数。# Enable installed protocols !include_try /usr/share/dovecot/protocols.d/*.protocol protocols = imap pop3 lmtp
修改
/etc/dovecot/conf.d/10-mail.conf
配置文件,该文件配置邮箱文件存储的位置和命名空间。mail_location = maildir:/var/mail/vhosts/%d/%n
创建邮箱文件存储目录并设置权限
mkdir -p /var/mail/vhosts/example.org chown -R vmail:vmail /var/mail/
修改
/etc/dovecot/conf.d/10-auth.conf
配置文件,该文件配置用户身份认证流程。auth_mechanisms = plain login disable_plaintext_auth = yes #!include auth-system.conf.ext !include auth-sql.conf.ext
修改
/etc/dovecot/conf.d/auth-sql.conf.ext
配置文件,该文件配置数据库认证的参数。passdb { driver = sql # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n }
修改
/etc/dovecot/dovecot-sql.conf.ext
配置文件,该文件配置验证用户名密码所用的数据表以及认证方法。driver = mysql connect = host=127.0.0.1 dbname=mailsys user=username password=yourpassword default_pass_scheme = CRYPT password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'
注意此处的加密存储算法,上文如果是使用
ENCRYPT()
函数,此处加密方式就选择default_pass_scheme = CRYPT
,而TO_BASE64(UNHEX(SHA2('password', 512)))
对应的就是default_pass_scheme = SHA512
修改
/etc/dovecot/conf.d/10-master.conf
配置文件,该文件配置 Dovecot 中各服务的主要参数。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 }
修改
/etc/dovecot/conf.d/10-ssl.conf
配置文件,该文件配置 SSL 加密参数。# ssl = yes ssl = required # PEM encoded X.509 SSL/TLS certificate and private key. They're opened before # dropping root privileges, so keep the key file unreadable by anyone but # root. Included doc/mkcert.sh can be used to easily generate self-signed # certificate, just make sure to update the domains in dovecot-openssl.cnf ssl_cert = <******.cer ssl_key = <******.key
注意
<
不要漏掉了修改
/etc/dovecot/conf.d/15-lda.conf
配置文件,该文件配置特定域的 postmaster 邮箱。#postmaster_address = postmaster_address = postmaster@%d
修改
conf.d/15-mailboxes.conf
配置文件,该文件配置邮箱内部的目录结构。namespace inbox { mailbox Drafts { auto = create special_use = \Drafts } mailbox Trash { auto = create special_use = \Trash } mailbox Sent { auto = create special_use = \Sent } }
这个配置文件根据个人对邮件文件夹的管理安排来决定是否修改,默认的邮件管理目录也不错。
至此邮件服务器就已经安装完成了,可以进行正常的收发邮件了。
重启postfix服务:systemctl restart postfix
重启dovecot服务:systemctl restart dovecot
查看端口监听情况:netstat -lnpt
MUA
MUA (Mail User Agent) 是邮件用户代理,是为用户收发邮件的服务器。例如Outlook、Foxmail等。
常见的 Webmail有:squirrelmail, Rainloop, Roundcube
大家想登陆的话,随便找个邮箱客户端,添加账户,配置好传入邮件服务器与传出邮件服务器即可。传入服务器可以填imap.example.org
,传出服务器可以填smtp.example.org
,如果你之前DNS记录是这样设置的话,如果没有,两个都填mail.example.org
DNS设置
为了让自己的邮件不被当作垃圾邮件,还需要进行 SPF 记录、DMARC 记录和 DKIM 签名的设置
PTR记录:这个需要你的服务器提供商支持,简单来说就是把你的IP反向解析到对应的域名,如果你的服务器提供商支持的话,去后台修改rDNS为mail.example.org
,或者提交工单
SPF记录:在DNS中,主机记录填@
,新增下面的TXT记录即可
v=spf1 mx:mail.example.org ip4:xxx.xxx.xxx.xxx ~all
DMARC 记录:在DNS中,主机记录填_dmarc
,新增下面的TXT记录即可
v=DMARC1;p=reject;[email protected]
[email protected]
表示当收件方检测到伪造邮件时,收件方须将该伪造信息的报告发送到哪个邮箱地址,所以一开始让你添加一个[email protected]
用户,不过你也可以设置为其他的,但是设置为自己的域名邮箱不是更好么(●'◡'●)
DKIM记录:
- 安装OpenDKIM:
apt install opendkim opendkim-tools
修改
/etc/opendkim.conf
配置文件,直接改为下面的配置就行,socket端口可以改成你自己喜欢的# AutoRestart AutoRestart Yes AutoRestartRate 10/1h # Log to syslog Syslog yes UMask 002 SyslogSuccess Yes LogWhy Yes Canonicalization relaxed/simple Mode sv Socket inet:12321@localhost PidFile /var/run/opendkim/opendkim.pid SignatureAlgorithm rsa-sha256 OversignHeaders From TrustAnchorFile /usr/share/dns/root.key UserID opendkim:opendkim ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable
修改
/etc/default/opendkim
配置文件,修改socket端口SOCKET=inet:12321@localhost
修改
/etc/postfix/main.cf
配置文件,追加以下内容# DKIM milter_protocol = 6 milter_default_action = accept smtpd_milters = inet:localhost:12321 non_smtpd_milters = inet:localhost:12321
当postfix版本为2.6+,milter_protocol=6;版本为2.3到2.5,milter_protocol=2,其中postfix版本由postconf -d | grep mail_version
查看。
修改
/etc/opendkim/TrustedHosts
配置文件127.0.0.1 localhost 192.168.0.1/24 *.example.org
创建目录并创建opendkim所需要的key
mkdir -p /etc/opendkim/keys mkdir -p /etc/opendkim/keys/example.org cd /etc/opendkim/keys/example.org opendkim-genkey -s mail –d example.org chown opendkim:opendkim mail.private ll /etc/opendkim/keys/example.org total 16 drwxr-xr-x 2 root root 4096 Sep 30 00:15 ./ drwxr-xr-x 3 root root 4096 Sep 30 00:15 ../ -rw------- 1 opendkim opendkim 1679 Sep 30 00:15 mail.private -rw------- 1 root root 499 Sep 30 00:15 mail.txt
修改相应配置文件,对应的文件内容如下
# cat /etc/opendkim/KeyTable mail._domainkey.example.org example.org:mail:/etc/opendkim/keys/example.org/mail.private # cat /etc/opendkim/SigningTable *@example.org mail._domainkey.example.org
新增一条DNS记录,主机记录填
mail._domainkey
,新增下面的TXT记录即可v=DKIM1; h=sha256; k=rsa; p=MIIBsrtfhkjnnijksjjoiojjbhgtafghjjooiqgqghkl7/rwdeswfsH3/wdesfef7e8ave/dwesfsBP02nlfeswfserkz8eOxCzrZ7P/iasdxfcgbvhftdrtfdXiT3EhVmKpyBZs0KUyVpasdfsfgthgmgoM7KvtWApTkRZMHTwR29EzN3tf2wKbrjMcb/i8AmfhdsasfcdvdbgfoZd7Osdgsfwdesfgthmjgfdsdfcgbh
这个值由
/etc/opendkim/keys/example.org
目录下的mail.txt得到,注意P的值可能是分两行显示的,你自己合为一行。
重启postfix、opendkim服务并测试
systemctl restart postfix
systemctl restart dovecot
systemctl restart opendkim
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key 'mail._domainkey.example.org'
opendkim-testkey: key secure
opendkim-testkey: key OK
发件测试
Newsletters spam,至于这个得分,由于受 IP 地址可能被拉黑的影响,因此各人的分数有可能不同。如果有 8 分以上的话发出去的邮件基本上就不会被拒收,建议用谷歌邮箱或者163邮箱测试收发。
QA
日志文件路径是
/var/log/mail.log
,如果postfix日志不在/var/log/mail.log
中您(或您的提供商)似乎更改了您的syslog工具配置。使用普通的syslogd而不是rsyslogd是非常有可能的,但是你可以期望事情与你的期望不同。通过安装
apt-get install rsyslog
,日志文件重新出现。fatal: no SASL authentication mechanisms
解决办法:ln -s /usr/local/lib/sasl2 /usr/lib/sasl2
,自己编译安装Cyrus SASL,具体参考Cyrus-SASL- 测试
opendkim-testkey -d example.org -s mail -vvv
出现opendkim-testkey: key not secure
没有启用DNSSEC
,去DNS服务商那里开启即可 - 发信有时成功,有时被退回。
建议查看退回邮件写的退回原因,主要就是PTR,SPF,DMARC 和 DKIM 这几块。有的VPS提供商只支持IPv4的rDNS,不支持IPv6,可以设置postfix的inet_protocols = ipv4
,经过测试发信谷歌邮箱只要PTR不符合就会拒收。
参考资料:
Configure an Email Server with Postfix, Dovecot, and MySQL on Debian and Ubuntu
邮件服务器添加SPF、DKIM、DMARC、PTR提高送达率
如果你认为这篇文章还不错,可以考虑 为作者充电 ⚡️