简介
Maddy 是一款用 Go 语言开发的邮件服务器,部署方便,资源占用少,是一款适合个人使用的邮箱服务器。
- 一台 VPS,支持开启 25 端口和 rDNS
- 一个域名,支持管理 A/AAAA 记录、MX 记录、TXT 记录等
- 邮箱域名的证书和密钥(使用 Certbot 申请)
maddy.yml
version: "3.8" services: maddy: image: foxcpp/maddy:latest container_name: maddy ports: - 25:25 - 143:143 - 465:465 - 993:993 volumes: - /opt/docker/data/maddy:/data - /etc/letsencrypt/live/mail.example.com/fullchain.pem:/data/local_certs/cert.pem:ro - /etc/letsencrypt/live/mail.example.com/privkey.pem:/data/local_certs/key.pem:ro environment: - TZ=Asia/Shanghai - MADDY_HOSTNAME=mail.example.com - MADDY_DOMAIN=example.com
启动后开放的端口及作用
- 25 SMTP Transfer->Exchange ClearText
- 465 SMTPs User->Submission TLS
- 143 IMAP Delivery->User ClearText
- 993 IMAPs Delivery->User TLS
- 587 ESMTP User->Submission ClearText/STARTTLS
获取 tls 证书
安装 Certbot
# Ubuntu/Debian sudo apt-get install certbot # Centos sudo yum install certbot
获取 tls 证书:
sudo certbot certonly --standalone -d mail.example.com
按照提示操作,将获得证书和私钥,存储在 /etc/letsencrypt/live/mail.example.com/ 目录下。
maddy 配置
# 预设了三个变量,方便后续使用 $(hostname) = mail.example.com # 外界通过这个域名找到你的邮件服务器 $(primary_domain) = example.com # 你的邮箱 @ 后面的域名 $(local_domains) = $(primary_domain) # 如果要使用 nginx 反代,这里可以选择 tls off,但如此一来没法生成 dkim 密钥对 # 在之后检查时日志内会有安全警告,故推荐直接用 maddy 管理 # tls off # tls file /etc/letsencrypt/live/$(local_domains)/fullchain.pem /etc/letsencrypt/live/$(local_domains)/privkey.pem tls file /data/local_certs/cert.pem /data/local_certs/key.pem # 数据用 SQLite3 存储较为简单、轻量 auth.pass_table local_authdb { table sql_table { driver sqlite3 dsn credentials.db table_name passwords } } storage.imapsql local_mailboxes { driver sqlite3 dsn imapsql.db } # ---------------------------------------------------------------------------- # SMTP endpoints + message routing hostname $(hostname) table.chain local_rewrites { optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3" optional_step static { entry postmaster postmaster@$(primary_domain) } optional_step file /data/aliases } msgpipeline local_routing { destination postmaster $(local_domains) { modify { replace_rcpt &local_rewrites } deliver_to &local_mailboxes } default_destination { reject 550 5.1.1 "User doesn't exist" } } # smtp 使用 25 号端口发送邮件 smtp tcp://[::]:25 { # tls self_signed limits { # Up to 20 msgs/sec across max. 10 SMTP connections all rate 20 1s all concurrency 10 } dmarc yes check { require_mx_record dkim # 若无则不检查 spf } source $(local_domains) { reject 501 5.1.8 "Use Submission for outgoing SMTP" } default_source { destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { reject 550 5.1.1 "User doesn't exist" } } } # 如果使用 nginx 反代则这里监听到本地端口即可 tcp://127.0.0.1:587 # 不使用则邮件客户端以 SSL/TLS 方式直接访问该地址 submission tls://[::]:465 { limits { # Up to 50 msgs/sec across any amount of SMTP connections all rate 50 1s } auth &local_authdb source $(local_domains) { check { authorize_sender { prepare_email &local_rewrites user_to_email identity } } destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { modify { dkim $(primary_domain) $(local_domains) default } deliver_to &remote_queue } } default_source { reject 501 5.1.8 "Non-local sender domain" } } target.remote outbound_delivery { limits { # Up to 20 msgs/sec across max. 10 SMTP connections # for each recipient domain. destination rate 20 1s destination concurrency 10 } mx_auth { dane mtasts { cache fs fs_dir mtasts_cache/ } local_policy { min_tls_level encrypted min_mx_level none } } } target.queue remote_queue { target &outbound_delivery autogenerated_msg_domain $(primary_domain) bounce { destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" } } } # ---------------------------------------------------------------------------- # IMAP endpoints # 同上,使用 nginx 反代则改为监听本地端口 tcp://127.0.0.1:143 imap tls://[::]:993 { auth &local_authdb storage &local_mailboxes
启动 maddy
docker compose up -d
创建 maddy 用户
# 进入容器 docker exec -it maddy /bin/sh # 创建邮箱 maddy creds create hello@example.com maddy imap-acct create hello@example.com
获取 DKIM 的公钥
/ # cat data/dkim_keys/*.dns v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG...zAuhVJKPYUPTnJ3yTIzi4R2XbzfwIDAQAB
设置 DNS 记录
- A 记录,将邮箱域名(mail.example.com)指向你的服务器 IP 地址
- MX(Mail Exchange)记录指向你的邮件服务器地址,确保可以接收邮件。将邮件域(hello@example.com,其中 example.com 就代表邮件域)指向第一步的邮箱域名,优先级默认为 10(数字越低,优先级越高)
- PTR 记录(或者叫 rDNS),可以通过 ip 地址反向解析出邮箱域名。不设置也没关系,但是会被某些服务器标记为垃圾邮件
- SPF(Sender Policy Framework)是用来指定哪些服务器有权限代表你的域名发送邮件
- DMARC(Domain-based Message Authentication, Reporting, and Conformance) 用于指定邮件的处理策略,以及接收未通过验证的邮件报告
- DKIM(DomainKeys Identified Mail) 用于对邮件进行数字签名,验证邮件是否被篡改
DNS 验证
# install dig apt-get install dnsutils # 验证 MX 记录 $ dig +short MX example.com mail.example.com # 验证 A 记录 $ dig +short A mail.example.com 71.2.3.1 # 验证 rDNS(PTR) 记录 $ dig +short -x 71.2.3.1 mail.example.com
以 mail.example.com 为邮件服务器的域名为例
序号 | 名称 | 类型 | 内容 | 说明 |
---|---|---|---|---|
1 | A | 71.2.3.1 | A | |
2 | AAAA | 2607:b102::e | ||
3 | smtp | CNAME | mail.example.com | CNAME |
4 | imap | CNAME | mail.example.com | |
5 | @ | MX | mail.example.com | MX |
6 | @ | TXT | v=spf1 mx ~all | SPF |
7 | TXT | v=spf1 mx ~all | ||
8 | _dmarc | TXT | v=DMARC1; p=quarantine; ruf=mailto:hello@example.com | DMARC |
9 | default._domainkey | TXT | v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG...zAuhVJKPYUPTnJ3yTIzi4R2XbzfwIDAQAB | DKIM |
在 cloudflare 新添加的 DNS 记录如下
测试检查
测试自建邮件服务器 mail.example.com,邮箱 hello@example.com 收发邮件情况。
- 垃圾邮件匹配度检测 https://www.mail-tester.com/?lang=zh
- MxtoolBox,查询 MX 记录,DKIM 等用于检查是否配置正确 https://mxtoolbox.com/SuperTool.aspx
0 评论