快速搭建一个SMTP邮件服务

由于最近一台VPS要到期不打算续费了,上面有一个SMTP发邮件的服务,因此需要转移。

当时配置的时候,是直接在宿主机搞的,转移起来有些麻烦。

为了以后转移方便,这次打算使用 docker 部署。

在网上找了半天,有很多类似的快速搭建的 Docker 镜像。

我找到的是这个 https://github.com/cainwise/docker-postfix

但是这个库里记录的 Docker 镜像已经不存在或者被作者设置为私有了。

而 Dockerfile 编译也因为软件包过时的原因,无法编译了。

于是花了三天三夜的时间重写了 Dockerfile。

新的代码库:https://github.com/ety001/docker-postfix

现在可以基于我新做的 Docker 镜像来快速部署 SMTP 服务了。

假设要为 example.com 域设置一个邮件服务器 mail.example.com(IP 地址为 1.2.3.4),并开启 STARTTLS 的支持。

创建 Postfix 容器

创建目录 /etc/postfix_conf/dkim_keys/etc/postfix_conf/tls

1
2
mkdir -p /etc/postfix_conf/dkim_keys
mkdir -p /etc/postfix_conf/tls

运行临时容器,不带 STARTTLS 功能

1
2
3
4
5
6
7
8
9
shell> docker run --name postfix \
-itd --rm\
--restart always \
-p 25:25 \
-e MTA_DOMAIN=example.com \
-e MTA_HOST=mail.example.com \
-e MTA_USERS=user:passwd \
-v /etc/postfix_conf/dkim_keys:/etc/opendkim/keys \
ety001/postfix

使用 acme.sh 来申请证书并安装证书

1
2
3
4
5
6
shell> acme.sh --issue -d mail.example.com --dns dns_cf
shell> acme.sh --installcert \
-d mail.example.com \
--key-file /etc/postfix_conf/tls/mail.example.com.key \
--fullchain-file /etc/postfix_conf/tls/mail.example.com.crt \
--reloadcmd "docker restart postfix"

停止容器,启动正式容器(即多增加一个证书目录的映射)

1
2
3
4
5
6
7
8
9
10
shell> docker stop postfix
shell> docker run --name postfix \
-itd --restart always \
-p 25:25 \
-e MTA_DOMAIN=example.com \
-e MTA_HOST=mail.example.com \
-e MTA_USERS=user:passwd \
-v /etc/postfix_conf/dkim_keys:/etc/opendkim/keys \
-v /etc/postfix_conf/tls:/etc/postfix/tls \
ety001/postfix

配置 MX 记录 和 A 记录

Type Host Answer
MX example.com mail.example.com
A mail.example.com 1.2.3.4
  • MX 保证向 example.com 域发送的邮件就会被递送到 mail.example.com
  • A 记录保证能解析到 mail.example.com 的 IP 地址。

配置 PTR 记录 (rDNS)

1.2.3.4 配置反向解析,值为 mail.example.com

配置 SPF 记录

Type Host Answer
TXT example.com v=spf1 mx ~all
SPF example.com v=spf1 mx ~all

配置 DKIM 记录

容器创建后,会在容器日志中显示公钥值,将其中的值按如下方式填写即可:

Type Host Answer
TXT mail._domainkey.example.com v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCi3zFH65YkLK+Edfu3VeZH2ylOpNC3ADfkL2p1PjhWQXrzn65rvrh2YTqEEb8xGunWD9c422SBoxRdpVENhUqnbb1Tk0Xu58gfrN2muTIedFDtWx7irvySNtDgcWWIdXDaPFk/nodeutahtueaszEuLqI/DpKD/9mY9Mm5QIDAQAB

配置 DMARC 记录

Type Host Answer
TXT _dmarc.example.com v=DMARC1; p=reject; [email protected]

测试

用一个简单 Node 程序来测试邮件服务是否可以正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'use strict';

const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({
host: 'mail.example.com',
port: 25,
secure: false,
requireTLS: true,
auth: {
user: '[email protected]',
pass: 'passwd'
},
});

// setup e-mail data with unicode symbols
var mailOptions = {
from: '"BOSS" <[email protected]>', // sender address
to: '<your mail>', // list of receivers
subject: '风中的来信', // Subject line
text: '为了防止垃圾邮件,现在有许多 SMTP 服务器要求客户端的 IP 地址必须要能够查到有效的 PTR 记录。', // plaintext body
html: '为了防止垃圾邮件,现在有许多 SMTP 服务器要求客户端的 IP 地址必须要能够查到有效的 PTR 记录。' // html body
};

// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
})