本文适用于:需要自建域名邮箱来注册平台账号、接收验证码的场景。全程命令行, 不用写 Python 脚本也能收码。
只讲收信。 对外发信要额外处理 rDNS、DKIM、DMARC 和 IP 信誉, 自建服务器发出去的信大概率进垃圾箱,那是另一件事。
一、背景说明
很多平台注册账号时会要求填写邮箱地址并接收验证码。为了批量注册或控制邮箱来源,一些用户希望自建域名邮箱系统,从而:
- 自己控制域名和邮箱地址
- 本地接收邮件,免费无限用
- 配合脚本自动抽取验证码
二、工作环境准备
1. 需要的条件
| 项目 | 说明 |
|---|---|
| 一台 VPS | Ubuntu 20.04+,25 端口必须能入站。多数云厂商默认封 25,要向主机商申请解封 |
| 一个可配置 DNS 的域名 | 如 mail.example.com |
2. 安装必要软件
apt update
apt install postfix dovecot-core dovecot-imapd -y
postfix= SMTP 邮件服务器,用于接收邮件dovecot= IMAP 邮箱读取服务器,允许脚本/网页读邮件
三、配置 DNS 记录
到域名控制面板(如 Cloudflare、阿里云、Namecheap)添加以下 DNS 记录:
| 类型 | 主机记录 | 值 |
|---|---|---|
| A | VPS IP | |
| MX | @ | mail.example.com (10) |
| TXT | @ | v=spf1 mx ~all |
说明:MX 是接收邮件的域名服务器,SPF 是为了防止邮件被伪造,非必但建议配置
四、配置 Postfix + Dovecot
配置 Postfix
编辑 /etc/postfix/main.cf ,加入或确保:
myhostname = mail.example.com
mydestination = $myhostname, localhost.$mydomain, localhost, example.com
home_mailbox = Maildir/
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
inet_interfaces = all
几个关键项的含义:
| 配置项 | 作用 | 写错的后果 |
|---|---|---|
myhostname |
这台机器对外自称的名字 | 对方服务器可能拒收 |
mydestination |
哪些域名的信算「本机的」并投递到本地 | 域名不在这个列表里,Postfix 会当成中转请求拒掉 |
home_mailbox = Maildir/ |
用 Maildir 格式,一封信一个文件 | 默认是 mbox(整个邮箱一个大文件),后面按文件取信的命令全都用不了 |
inet_interfaces = all |
监听所有网卡 | 默认只听 localhost,外面的信根本进不来 |
ssl-cert-snakeoil 是系统自带的自签证书,用于收信足够了;要用正式证书就换成
Let’s Encrypt 签发的路径。
配置 Dovecot
编辑 /etc/dovecot/conf.d/10-mail.conf:
mail_location = maildir:~/Maildir
这一行必须和 Postfix 的 home_mailbox 对上。 Postfix 按 Maildir 格式写信、
Dovecot 却按 mbox 格式找,结果就是「信收到了,但客户端里一封都看不到」——
两边都不报错,最难查的就是这种。
五、创建邮箱用户
每个 Linux 用户 = 一个邮箱地址
adduser code # 即创建 code@example.com
重启服务:
systemctl restart postfix dovecot
六、测试接收
- 用你的 Gmail/QQ/163,给
code@example.com发一封邮件 - 在服务器上查看
ls /home/code/Maildir/new
cat /home/code/Maildir/new/文件名
- 接收成功,表明邮箱配置已成功
七、命令行接收验证码
提取最新邮件:
cd /home/code/Maildir/new
latest=$(ls -t | head -n1)
cat "$latest"
只看正文:
sed -n '/^$/,$p' "$latest"
提取6位数验证码:
sed -n '/^$/,$p' "$latest" | grep -oE '\b[0-9]{6}\b'
八、收不到信时按这个顺序查
| 现象 | 先查什么 |
|---|---|
| 发过去直接退信 | MX 记录解析对不对:dig MX example.com |
| 没退信也没收到 | 25 端口通不通:从别的机器 telnet 你的IP 25 |
| Postfix 收到了但目录是空的 | mail_location 和 home_mailbox 格式是否一致 |
| 都正常但就是没有 | tail -f /var/log/mail.log,Postfix 的日志写得很清楚 |
小结
| 环节 | 用什么 |
|---|---|
| 收信 | Postfix(SMTP) |
| 读信 | Dovecot(IMAP) |
| 存储格式 | Maildir,一封信一个文件,落在 /home/用户名/Maildir/new/ |
| DNS | A + MX + SPF |
| 抽验证码 | sed 取正文 + grep -oE 匹配 6 位数字 |
走完这一遍就有了一套自己可控的收信系统:接验证码、配合脚本自动注册、把抽到的码 推给 API 都可以。
一台服务器要接多个域名的话,不再靠系统用户,改用虚拟邮箱——参考 Postfix 官方的 VIRTUAL_README。
附录:用到的 Shell 命令
本节整理了一些在邮件接收流程中用到的常见命令及参数说明,方便读者理解并活用。
| 命令 | 示例 | 说明 |
|---|---|---|
ls -t |
ls -t | head -n1 |
-t 表示按修改时间排序,配合 head -n1 获取最新邮件文件名 |
head -n1 |
head -n1 |
获取输出的第一行(如最新文件名) |
cat |
cat 文件名 |
查看文件全部内容,包括邮件头和正文 |
sed -n '/^$/,$p' |
sed -n '/^$/,$p' "$latest" |
sed -n 不自动打印;/^$/,$ 表示从空行开始到文件结尾;p 表示打印匹配的部分;用于提取邮件正文 |
grep -oE '\b[0-9]{6}\b' |
grep -oE '\b[0-9]{6}\b' |
-o 只输出匹配内容,-E 使用扩展正则;\b[0-9]{6}\b 匹配完整的 6 位数字验证码 |
adduser 用户名 |
adduser code |
创建 Linux 系统用户,对应邮箱 code@example.com |