Maddy 是一款用 Go 语言开发的邮件服务器,部署方便,资源占用少,是一款适合个人使用的邮箱服务器。

在我的 CloudCone 1C1G 机 docker 搭建后查看容器,CPU 使用 0.03%,内存使用 20M,所以 1C1G 跑起来毫无压力。

准备

  • 一台 VPS,支持开启 25 (telnet smtp.qq.com 25) 端口和 rDNS
  • 一个域名,支持管理 A/AAAA 记录、MX 记录、TXT 记录等
  • 邮箱域名的证书和密钥(使用 Certbot 申请)

安装 docker

docker-compose.yml 的内容如下

version: "3.8"
services:
  maddy:
    image: foxcpp/maddy:0.8.1
    container_name: maddy
    restart: always
    ports:
      - 25:25
      - 143:143
      - 587:587
      - 465:465
      - 993:993
    volumes:
      - ${APP_CONF}/maddy:/data
      - ${APP_CONF}/certbot/config/live/mail.example.com/fullchain.pem:/data/local_certs/cert.pem:ro
      - ${APP_CONF}/certbot/config/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
# VARIABLE=value #comment
WEB_ROOT=/var/www/html
APP_CONF=/opt/docker/data
APP_DATA=/opt/appdata

启动后开放的端口及作用

Port Usage Security Note
25 SMTP MTA PLAIN/TLS 用于接收和发送邮件
143 IMAP STARTTLS 收信,tls://imap.example.com:143
993 IMAP TLS ssl://imap.example.com:993
587 SMTP MTA STARTTLS 发信,tls://smtp.example.com:587
465 SMTP Submission TLS ssl://smtp.example.com:465

TLS 通常比 SSL 更安全,且是现代通信中偏好的选项。

使用 ssl://,意味着将以 SSL 直接加密整个连接。

使用 tls://,则通常是在初始连接时使用普通的明文连接,然后通过 STARTTLS 命令将其升级为加密连接。

建议尽可能使用 tls://,因其安全性更高且是当前的标准。如果您的邮件服务器支持 TLS,通常优先考虑它。

获取 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

# https://github.com/foxcpp/maddy/blob/master/maddy.conf

配置 nginx(可选)

启动 maddy

docker compose up -d

创建 maddy 用户

# 进入容器
docker exec -it maddy /bin/sh
# 创建邮箱
# maddy -h
maddy creds create [email protected]
maddy imap-acct create [email protected]
maddy creds password –password PASSWORD [email protected]
maddy creds list
maddy imap-acct list
# 密码生成器
maddy hash

# # 本地凭据和 IMAP 存储账户
# 本地凭据(用户名和密码)通常用于用户身份验证。
# IMAP 账户,主要涉及邮件存储和操作,关联到邮件数据的实际存储位置,通常对应于用户的邮箱。
# 本地凭据和 IMAP 存储账户通过用户名来关联:
# 用户登录:当用户尝试通过 IMAP 客户端登录时,Maddy 首先会检查本地凭据(通过 maddy creds 管理)来验证用户名和密码。
# 账户操作:一旦用户凭据验证通过,Maddy 会根据用户名从 IMAP 存储账户配置(通过 maddy imap-acct 管理)来获取相应的邮件# 数据存储信息。

获取 DKIM 的公钥

/ # cat data/dkim_keys/*.dns
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG...zAuhVJKPYUPTnJ3yTIzi4R2XbzfwIDAQAB

复制保存,将在设置 DNS 记录使用

设置 DNS 记录

  • A 记录,将邮箱域名(mail.example.com)指向你的服务器 IP 地址
  • MX(Mail Exchange)记录指向你的邮件服务器地址,确保可以接收邮件。将邮件域([email protected],其中 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 mail A 71.2.3.1 A
2 mail 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 mail TXT v=spf1 mx ~all
8 _dmarc TXT v=DMARC1; p=quarantine; ruf=mailto:[email protected] DMARC
9 default._domainkey TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG...zAuhVJKPYUPTnJ3yTIzi4R2XbzfwIDAQAB DKIM

最终,我在 cloudflare 新添加的 DNS 记录如下

测试检查

测试自建邮件服务器 mail.example.com,邮箱 [email protected] 收发邮件情况。

我们使用 Mailspring —— 一个支持 Mac、Linux 和 Windows 的、开源的,邮件客户端来操作。

使用 [email protected] 连接后

  1. 往自己的 Gmail 邮箱发邮件,检查能否收到邮件。
  2. Gmail 收到邮件后,在 Gmail 邮箱后回复,检查在邮件客户端 Mailspring 能否收到邮件。

如上图,可以正常收发邮件。

最后,mail-tester 测试下得分 9.5,这是未针对内容调整,调整后估计分值可以加高。

邮件通知到 Telegram(可选)

在 maddy.conf 中,找到 storage.imapsql local_mailboxes,添加一个 imap_filter :

storage.imapsql local_mailboxes {
    driver sqlite3
    dsn imapsql.db

    imap_filter {
       command /data/script/notice.sh  {sender} {original_rcpt_to} {subject}
    }
}

邮件通知的脚本内容:


                        

邮件 Web 客户端(可选)

使用 web 管理邮件,进行收发邮件。

version: "3.8"
services:
  roundcube:
    image: roundcube/roundcubemail:1.6.10-apache
    container_name: roundcube
    restart: unless-stopped
    volumes:
      #- ${WEB_ROOT}/roundcube:/var/www/html
      - ${WEB_ROOT}/roundcube/opt:/opt
    ports:
      - 127.0.0.1:8080:80
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=mysql
      - ROUNDCUBEMAIL_DB_HOST=x.x.x.x
      - ROUNDCUBEMAIL_DB_PORT=3306
      - ROUNDCUBEMAIL_DB_USER=root
      - ROUNDCUBEMAIL_DB_PASSWORD=xxxx
      - ROUNDCUBEMAIL_DB_NAME=app_roundcube
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://imap.196000.xyz
      - ROUNDCUBEMAIL_DEFAULT_PORT=993
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://smtp.196000.xyz
      - ROUNDCUBEMAIL_SMTP_PORT=465
# VARIABLE=value #comment
WEB_ROOT=/var/www/html
APP_CONF=/opt/docker/data
APP_DATA=/opt/appdata

使用前面创建的账号 [email protected] 和密码登入即可。

安全事项

  1. 推荐运行启用 DNSSEC 验证的自己的 DNS 解析器。
  2. 建议使用 MTA-STS 策略,使得发信服务器在发送电子邮件到接收服务器时,强制使用经过身份验证的 TLS 连接,以防止主动的网络攻击。
  3. 推荐设置 TLSA (DANE) 记录。
  4. 注释 maddy 常用端口,只通过 roundcubemail 提供的网页端访问。

在线工具

  • 垃圾邮件匹配度检测 https://www.mail-tester.com/?lang=zh
  • MxtoolBox,查询 MX 记录,DKIM 等用于检查是否配置正确 https://mxtoolbox.com/SuperTool.aspx