暑假的时候见识了Vestacp,用它可以方便快捷的搭建一个邮局。但是邮局经常崩,常收不到邮件。寒假了就折腾了一下Docker。
PS(2017.2.13更新):将近一个月了,期间收了已经有上百封邮件。我用uptime robot检测的还没有一例宕机事故,监控页面在这里。docker容器的稳定性是有目共睹的。
一、基础知识
1.常见邮局端口&&协议:
发邮件的协议有SMTP,收邮件的协议有POP3和IMAP。
- SMTP:明文使用25端口。加密后使用25/587/465端口。
- IMAP:明文使用143端口。加密后使用143/993端口。
- POP3:明文使用110端口。加密后使用110/995端口。
2.常见邮局软件和安全软件:
- sendmail:用于发邮件。资格最老的邮局,所有Linux发行版基本都带。但是配置麻烦。
- postfix:Wietse Venema觉得sendmail配置太麻烦了,就开发了一个“简化配置版sendmail”,即postfix。支持smtp协议。
- dovecot:用于收邮件,支持imap/pop3。
- spamassasin:垃圾邮件过滤器。可以自订规则。
- clamav:邮件杀毒工具。
- opendkim:生成dkim签名。有什么用?详见下面的“反垃圾邮件技术”。
- fail2ban:防止别人暴力破解用户名密码的工具。
3.反垃圾邮件技术:
假设我要在1.1.1.2这台机器上配置best.pm、best.nl这两个域名用于发邮件。1.1.1.2的主机名是mail1.wangchenyu.net.cn。那么我们需要
- 设置rDNS,将1.1.1.2映射到mail1.wangchenyu.net.cn。DNS是域名->IP的解析。rDNS即IP->域名的解析。有了这个rDNS记录,收到邮件的服务器就能确认mail1.wangchenyu.net.cn可以被用在1.1.1.2这个IP上。一般在主机商后台可以添加rdns记录,找不到的话提交一个工单即可。
- 设置best.pm和best.nl的MX记录,记录名为@,值为mail1.wangchenyu.net.cn,优先级为10。MX记录用于别人向best.pm这个域发送邮件时查找收信服务器。不设置的话无法收到别人发的邮件,并且自己发出的邮件的“可信度”也会大大降低。优先级
- 设置DKIM签名。DKIM先由发件服务器生成,之后每封邮件都会带上这个签名。接着,还要在best.pm和best.nl上各添加一条TXT记录,记录名和值在发件服务器生成DKIM时都会提供。收到邮件后会对比邮件中的DKIM签名和DNS中的TXT记录是否一致。
- 设置SPF记录。这个记录规定了可以用这个域发邮件的主机。在best.pm和best.nl上各添加一条TXT记录,记录名为
@
,值为v=spf1 mx ~all
即可允许所有IP使用此域。 - 设置DMARC记录。这个记录指出他们的地址被 SPF 和/或 DKIM/或别的方法保护。在best.pm和best.nl上各添加一条TXT记录,记录名为
_dmarc
,值为v=DMARC1; p=none
二、操作步骤
这里我选择了一个Github上的docker-mailserver。正如介绍中所言,它的功能齐全,配置简单,并且不需要*sql数据库。部署和升级都相对简单得多。在服务器上安装docker和docker-compose。
1.参照着上面给的说明,首先拉取镜像:
docker pull tvial/docker-mailserver:latest
2.创建docker-compose.yml
version: '2'
services:
mail:
image: tvial/docker-mailserver:2.1
hostname: mail1
domainname: wangchenyu.net.cn
container_name: mail
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
volumes:
- /home/mail:/var/mail
- /home/mail-state:/var/mail-state
- /root/config/:/tmp/docker-mailserver/
- /etc/letsencrypt:/etc/letsencrypt
environment:
- ENABLE_SPAMASSASSIN=0
- ENABLE_CLAMAV=0
- ENABLE_FAIL2BAN=1
- ONE_DIR=1
- DMS_DEBUG=0
- SSL_TYPE=letsencrypt
cap_add:
- NET_ADMIN
3.添加邮件账户:
mkdir -p /root/config
touch /root/config/postfix-accounts.cf
docker run --rm \
-e MAIL_USER=user1@best.pm \
-e MAIL_PASS=mypassword \
-ti tvial/docker-mailserver:latest \
/bin/sh -c 'echo "$MAIL_USER|$(doveadm pw -s SHA512-CRYPT -u $MAIL_USER -p $MAIL_PASS)"' >> /root/config/postfix-accounts.cf
如果有多个邮箱账户,则多次执行上面的docker run
语句就行。
4.创建DKIM key:
docker run --rm \
-v "/root/config":/tmp/docker-mailserver \
-ti tvial/docker-mailserver:latest generate-dkim-config
执行完之后查看/root/config/opendkim/keys/best.pm/mail.txt
的内容就是我们要设置的dns解析。我的内容是:
cat /root/config/opendkim/keys/best.pm/mail.txt
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DPENNNNNNNNNNCBiQKBgQCy9JV3FnXjLjsRJs/N0fy1C233333IV7t3f7fWpv/lo4NsoPEtG693hTgApkhuLl9KeV233333DMTagtXN898lXenKFEIS4COi7X/RjbGuOoApg4qS23333333TfXsrjN3xVC78E9T/HrS6pJN5fX+1s+1s+1s+1s+1s+1sIDAQAB" ) ; ----- DKIM key mail for best.pm
如果是自己搭建的bind,直接把这段塞进域名的hosts文件就行。如果使用的是第三方解析,就去后台添加一条TXT记录,记录名是mail._domainkey,记录值是将两段引号内的字符串拼接起来即可,如我的就是:
v=DKIM1; k=rsa;p=MIGfMA0GCSqGSIb3DPENNNNNNNNNNCBiQKBgQCy9JV3FnXjLjsRJs/N0fy1C233333IV7t3f7fWpv/lo4NsoPEtG693hTgApkhuLl9KeV233333DMTagtXN898lXenKFEIS4COi7X/RjbGuOoApg4qS23333333TfXsrjN3xVC78E9T/HrS6pJN5fX+1s+1s+1s+1s+1s+1sIDAQAB
5.申请letsencrypt证书并自动续费:
非CentOS请参考certbot.eff.org。
安装certbot工具:
sudo yum install -y certbot
确保将mail1.wangchenyu.net.cn解析到了1.1.1.2,然后执行:
certbot certonly --standalone -d mail1.wangchenyu.net.cn
即可申请到mail1.wangchenyu.net.cn的证书,申请后证书就放在
/etc/letsencrypt/live/mail1.wangchenyu.net.cn
下,其中
fullchain.pem
是机构证书+域名证书chain.pem
是机构证书cert.pem
是域名证书privkey.pem
是域名私钥
因为上面的docker-compose.yml
中已经把/etc/letsencrypt
映射到了容器中所以到这里就完成了证书的工作。
输入crontab -e
打开定时任务设置面板,然后按i进入编辑模式,粘贴进这段代码即可每周一凌晨5点0分给证书续期:
0 5 * * 1 /usr/bin/certbot renew --quiet
到这里已经万事大吉了。
如何检测SSL配置是否成功?
参照https://github.com/tomav/docker-mailserver/wiki/Configure-SSL,
启动容器后运行:
docker exec mail openssl s_client -connect 0.0.0.0:587 -starttls smtp -CApath /etc/letsencrypt/
和
docker exec mail openssl s_client -connect 0.0.0.0:993 -starttls imap -CApath /etc/letsencrypt/
看到这个说明成功了:
Verify return code: 0 (ok)
6.启动容器:
执行下列命令即可:
docker-compose up -d mail
三、客户端配置
服务器配置好了,如何连接?
在任一个邮件客户端中这么配置:
收信:
- 服务器地址:
mail1.wangchenyu.net.cn
- 协议:
IMAP
- 端口:
993
- 用户名:
user1@best.pm
- 密码:
mypassword
- 使用SSL:是
发信:
- 服务器地址:
mail1.wangchenyu.net.cn
- 协议:
SMTP
- 端口:
587
- 用户名密码同上
- 使用SSL:是
Enjoy it!
Comments | 19 条评论
怎么我搭建了邮件服务器接收邮件正常(ssl方式),发送邮件25端口发送邮件提示发送成功,但是对方就是收不到,但也不是到对方的垃圾箱中,换了不同邮箱帐号还是一样,我使用ssl 587端口发送直接报无法连接。请问你知道这是什么情况吗?
@音符
要是你也是用docker搭建的话,docker logs mail这样看一下dovecot日志,看看有没有发出去。
至于端口无法连接,检查一下建立容器的时候绑定587端口了不?无法连接是报什么错误?证书有问题还是什么?
你好,docker-compose.yml 这个文件放在那个目录下啊。还是在任意目录都可以,只要执行到时候指定文件路径比如,docker-compose ./docker-compose.yml up -d mail
@coompoy
已经搞定了,谢谢
@coompoy
没记错的话,如果执行的是
docker-compose up -d
会在当前目录寻找docker-compose.yml
如果手动指定配置文件的话,那就无所谓 放在哪里/文件名是什么 啦
搞定了就好~
@cheney
你这个域名是不是被墙了,还是你腾讯云这个香港ip被墙了,现在要翻墙才能访问哈哈😄
@coompoy
Orz 不是被墙啦,是备案期间不想被谷歌惩罚,就屏蔽了所有国内ip不解析😏
至于为啥又备案了呢,为了“覆盖”历史记录:)
非常抱歉打扰你,需要自己搭建邮件服务器,没有配置反向解析,配置了域名-->IP的记录,其他的都是按照你的文章里写的步骤操作的,最后用outlook连接,总是连不上,我用其他的邮件发送了邮件,通过docker logs mail,是能看到成功收到邮件了,好纠结,希望你能帮我分析下问题
@xiaoxiao
如果docker logs mail能看见的话,说明dovecot收到收件了,也就说明收信端口25正常打开。客户端能不能连上的话,可以看看
1. docker容器是否把端口993成功映射到了主机
- 执行docker port mail查看
2. 主机是否有防火墙未开放993
- 确认容器映射正确的话,在主机上执行telnet 127.0.0.1 993能否连通
- 上面能连通的话,在本地执行telnet your.mail.server 993能否连通
3. 收信软件的协议是否选择正确
- 上面都能连通的话,检查outlook客户端配置的是不是imap协议
谢谢,已经可以正常收发邮件了
@xiaoxiao
好极啦 🙂
为什么我按着博主的步骤做最后还是发不了邮件?更不用说收邮件了。。。
有谁可以帮助下我?qq或微信: 2 8 9 9 3 1 6 5 0
@KennyZhang
看上面的评论哦,按照这个流程检查一下:
如果docker logs mail能看见的话,说明dovecot收到收件了,也就说明收信端口25正常打开。客户端能不能连上的话,可以看看
1. docker容器是否把端口993成功映射到了主机
– 执行docker port mail查看
2. 主机是否有防火墙未开放993
– 确认容器映射正确的话,在主机上执行telnet 127.0.0.1 993能否连通
– 上面能连通的话,在本地执行telnet your.mail.server 993能否连通
3. 收信软件的协议是否选择正确
– 上面都能连通的话,检查outlook客户端配置的是不是imap协议
该评论为私密评论
@始皇哥
1. 搭建邮件服务器最好要一个域名,MX记录是必须填写域名的。不过,你可以在freenom.com免费申请一个.tk/.cf/.ga/.ml的域名。
2. DNS、MX这些都是最基础的东西啦,如果你想自建邮件服务器,最好先把他们搞明白,这些概念并不难理解。
如果你实在无法理解,推荐你使用商用的邮件服务如mailgun、sendgrid。
如果不在乎邮箱的后缀,直接使用QQ邮箱、163邮箱等带的SMTP功能来发送邮件也行。
你好!获取证书失败,请问是什么原因。
相关流程:
1.使用命令“ sudo yum install -y certbotBash”,安装certbot工具已经成功。
2。使用电脑PING命令可以拼通"xxx.xxx.top"。
3。但是使用命令“ certbot certonly --standalone -d mail1.wangchenyu.net.cn”,申请证书失败。
以下是报错内容(邮箱 地址做了 隐藏):
-----------------------------------------------------------------------------------------------------------------
Please see the logfiles in /var/log/letsencrypt for more details.
[root@localhost ~]# certbot certonly --standalone -d xxx.xxx.top
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for xxx.xxx.top
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. icemail.fictime.top (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://xxx.xxx.top/.well-known/acme-challenge/i2TR9ASXtANyiJgtFotOyYmiEoJiAjaVB3bU1iyeCIw: Timeout during connect (likely firewall problem)
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: xxx.xxx.top
Type: connection
Detail: Fetching
http://xxx.xxx.top/.well-known/acme-challenge/i2TR9ASXtANyiJgtFotOyYmiEoJiAjaVB3bU1iyeCIw:
Timeout during connect (likely firewall problem)
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address. Additionally, please check that
your computer has a publicly routable IP address and that no
firewalls are preventing the server from communicating with the
client. If you're using the webroot plugin, you should also ver
-----------------------------------------------------------------------------------------------------------------
使用的命令是这个“ certbot certonly –standalone -d xxx.xxx.top”,申请证书失败。
@leron_lee
看起来错误信息是超时
1. 试试看自己手动访问xxx.xxx.top/.well-known可否访问?
2. 自己在.well-known目录下建个文件,然后访问xxx.xxx.top/.well-known/文件名 能否访问?
如果自己访问是正常的,而letsencrypt的验证服务器无法访问,可以试试用acme.sh脚本,用dns的方式申请证书,见这里:https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E
该评论为私密评论