已实现内容:发送给 *.me@toocent.cn 的内容自动转发给 wang.coder@foxmail.com

未实现内容:回复 *.me@toocent.cn 的转发内容,会被自动转发给源邮箱

用户让我总结本次对话的所有内容,形成一篇可以发表的文章。需要包括:

    1. 目的
    2. 方案
    3. 遇到的坑

让我回顾一下整个过程:

    1. 目的:在 1Panel 管理的 docker-mailserver 中添加邮件转发功能,将 *.me@toocent.cn 的邮件自动转发到 wang.coder@foxmail.com
    2. 方案:
    
    
        * 使用 Postfix 的 `virtual_alias_maps` 配合 `pcre` 正则表达式映射实现通配符转发
    
        * 启用 SRS (Sender Rewriting Scheme) 解决 SPF 检查失败问题
    
        * 创建持久化脚本确保容器重启后配置生效
    3. 遇到的坑:
    
    
        * Postfix 的 texthash 类型不支持通配符,需要使用 pcre/regexp 类型
    
        * 转发后 SPF 检查失败(发件人地址仍然是原发件人,但服务器 IP 不在原发件人域名的 SPF 记录中)
    
        * 需要启用 SRS 来重写发件人地址
    
        * 域名没有 SPF 记录也会导致问题
    
        * 容器重启后配置会丢失,需要持久化

我来写一篇详细的技术文章。

CodeFlicker
Docker-Mailserver 邮件转发配置实战:从踩坑到完美解决

一、背景与目的

近期项目中需要在运行于 1Panel 管理的 Docker 邮件服务器上添加邮件转发功能。具体需求如下:

    * **需求**:将所有发送到 `*.me@toocent.cn` 的邮件自动转发到 `wang.coder@foxmail.com`
    * **环境**:Docker-Mailserver(ghcr.io/docker-mailserver/docker-mailserver:15.1.0)运行在 1Panel 中
    * **难点**:`*` 是通配符,需要匹配任意前缀

二、技术方案

2.1 环境分析

首先确认了邮件服务器的运行状态和配置:

    # 查看运行中的容器
    docker ps | grep mailserver

    # 输出:
    # 1Panel-mailserver-9FuA   ghcr.io/docker-mailserver/docker-mailserver:15.1.0

关键配置目录挂载信息:

    * 宿主机:`/opt/1panel/apps/mailserver/mailserver/data/dms/config`
    * 容器内:`/tmp/docker-mailserver`

2.2 方案一:Postfix Virtual Alias Maps(失败)

最初尝试使用 Postfix 的 virtual_alias_maps,但发现:

    # Postfix 配置检查
    docker exec mailserver postconf virtual_alias_maps
    # 输出:virtual_alias_maps = texthash:/etc/postfix/virtual

问题:texthash 类型不支持通配符,只能明确列出每个地址。这意味着如果要实现 *.me@toocent.cn 的转发,需要穷举所有可能的地址,这显然不现实。

2.3 方案二:PCRE 正则表达式映射(成功)

Postfix 支持 pcre(Perl Compatible Regular Expressions)类型的映射表,可以完美解决通配符问题。

    # 确认 Postfix 支持 pcre
    docker exec mailserver postconf -m | grep pcre
    # 输出:pcre

实施步骤:

    1. **创建 PCRE 映射文件**

在宿主机创建 /opt/1panel/apps/mailserver/mailserver/data/dms/config/postfix-virtual.pcre:

    # 通配符转发:*.me@toocent.cn -> wang.coder@foxmail.com
    /^[^@]+\.me@toocent\.cn$/    wang.coder@foxmail.com

正则表达式解析:

    * `^[^@]+` - 匹配 @ 符号前的任意字符(至少一个)
    * `\.me@` - 匹配 `.me@` 字符串
    * `toocent\.cn$` - 匹配域名结尾

    1. **更新 Postfix 配置**

    # 复制文件到容器内
    docker exec mailserver cp /tmp/docker-mailserver/postfix-virtual.pcre /etc/postfix/virtual.pcre

    # 添加 pcre 映射到 virtual_alias_maps
    docker exec mailserver postconf -e 'virtual_alias_maps = texthash:/etc/postfix/virtual, pcre:/etc/postfix/virtual.pcre'

    # 重新加载 Postfix
    docker exec mailserver postfix reload

    1. **验证转发规则**

    docker exec mailserver postmap -q "test.me@toocent.cn" pcre:/etc/postfix/virtual.pcre
    # 输出:wang.coder@foxmail.com

    docker exec mailserver postmap -q "hello.me@toocent.cn" pcre:/etc/postfix/virtual.pcre
    # 输出:wang.coder@foxmail.com

    docker exec mailserver postmap -q "no-reply@toocent.cn" pcre:/etc/postfix/virtual.pcre
    # 输出:(空,不匹配)

三、遇到的坑

坑一:SPF 检查失败

现象:邮件确实被转发了,但被 QQ 邮箱拒绝:

    status=bounced (host mx3.qq.com said: 550 SPF check failed)

日志分析:

    # 邮件流程:
    # 1. wang.coder@foxmail.com 发送邮件到 wang.me@toocent.cn
    # 2. 服务器转发到 wang.coder@foxmail.com
    # 3. 发件人仍然是 wang.coder@foxmail.com
    # 4. QQ邮箱检查 SPF:服务器 IP (101.42.30.99) 不在 foxmail.com 的 SPF 记录中
    # 5. 拒绝邮件

根本原因:邮件转发时,发件人地址没有改变。接收方(QQ邮箱)检查 SPF 记录时,发现邮件来自非授权服务器。

解决方案:启用 SRS(Sender Rewriting Scheme)

坑二:SRS 未启用

检查 SRS 状态:

    docker exec mailserver env | grep -i srs
    # 输出:
    # SRS_SENDER_CLASSES=envelope_sender
    # ENABLE_SRS=0  <-- 未启用

启用 SRS:

    1. **生成密钥**:

    docker exec mailserver bash -c 'openssl rand -base64 24 > /etc/postsrsd.secret && chmod 600 /etc/postsrsd.secret'

    1. **修改 postsrsd 配置**:

    docker exec mailserver sed -i 's/SRS_DOMAIN=localdomain/SRS_DOMAIN=toocent.cn/' /etc/default/postsrsd

    1. **启动 postsrsd 服务**:

    docker exec mailserver postsrsd -d toocent.cn -s /etc/postsrsd.secret -f 10001 -r 10002 -p /var/run/postsrsd.pid

    1. **配置 Postfix 使用 SRS**:

    docker exec mailserver postconf -e 'sender_canonical_maps = tcp:127.0.0.1:10001'
    docker exec mailserver postconf -e 'sender_canonical_classes = envelope_sender'
    docker exec mailserver postconf -e 'recipient_canonical_maps = tcp:127.0.0.1:10002'
    docker exec mailserver postconf -e 'recipient_canonical_classes = envelope_recipient, header_recipient'
    docker exec mailserver postfix reload

SRS 工作原理:

    原始邮件:
      From: wang.coder@foxmail.com
      To: wang.me@toocent.cn

    转发后(SRS 重写):
      From: SRS0+xxxx=xx=foxmail.com=wang.coder@toocent.cn
      To: wang.coder@foxmail.com

    SPF 检查:检查 toocent.cn 的 SPF 记录(而非 foxmail.com)

坑三:域名缺少 SPF 记录

检查 SPF 记录:

    host -t TXT toocent.cn
    # 输出:toocent.cn has no TXT record

解决方案:在 DNS 服务商(DNSPod)添加 SPF 记录:

┌──────┬──────┬──────────────────────────────┐
│ 类型 │ 主机 │ 值                           │
├──────┼──────┼──────────────────────────────┤
│ TXT  │ @    │ v=spf1 ip4:101.42.30.99 -all │
└──────┴──────┴──────────────────────────────┘

或者更宽松的配置:

┌──────┬──────┬──────────────────┐
│ 类型 │ 主机 │ 值               │
├──────┼──────┼──────────────────┤
│ TXT  │ @    │ v=spf1 a mx -all │
└──────┴──────┴──────────────────┘

坑四:容器重启后配置丢失

Docker 容器重启后,容器内的修改会丢失。需要持久化配置。

解决方案:使用 docker-mailserver 的 user-patches.sh 机制

创建 /opt/1panel/apps/mailserver/mailserver/data/dms/config/user-patches.sh:

    #!/bin/bash
    # 复制 pcre 虚拟映射文件到 Postfix 配置目录
    cp /tmp/docker-mailserver/postfix-virtual.pcre /etc/postfix/virtual.pcre 2>/dev/null || true

    # 配置 SRS (Sender Rewriting Scheme)
    cp /tmp/docker-mailserver/postsrsd.secret /etc/postsrsd.secret 2>/dev/null || true
    chmod 600 /etc/postsrsd.secret 2>/dev/null || true

    # 启动 postsrsd
    if [ -f /etc/postsrsd.secret ]; then
        postsrsd -d toocent.cn -s /etc/postsrsd.secret -f 10001 -r 10002 -p /var/run/postsrsd.pid 2>/dev/null || true
    fi

    # 配置 Postfix 使用 SRS
    postconf -e 'sender_canonical_maps = tcp:127.0.0.1:10001' 2>/dev/null || true
    postconf -e 'sender_canonical_classes = envelope_sender' 2>/dev/null || true
    postconf -e 'recipient_canonical_maps = tcp:127.0.0.1:10002' 2>/dev/null || true
    postconf -e 'recipient_canonical_classes = envelope_recipient, header_recipient' 2>/dev/null || true

    # 重新加载 Postfix
    postfix reload 2>/dev/null || true

同时创建 postfix-main.cf 用于持久化 Postfix 配置:

    # 通配符转发配置
    virtual_alias_maps = texthash:/etc/postfix/virtual, pcre:/etc/postfix/virtual.pcre

    # SRS (Sender Rewriting Scheme) 配置
    sender_canonical_maps = tcp:127.0.0.1:10001
    sender_canonical_classes = envelope_sender
    recipient_canonical_maps = tcp:127.0.0.1:10002
    recipient_canonical_classes = envelope_recipient, header_recipient

四、最终配置文件清单

    /opt/1panel/apps/mailserver/mailserver/data/dms/config/
    ├── postfix-accounts.cf      # 邮箱账户配置
    ├── postfix-main.cf          # Postfix 自定义配置(持久化)
    ├── postfix-virtual.pcre     # PCRE 转发规则
    ├── postsrsd.secret          # SRS 密钥
    └── user-patches.sh          # 容器启动脚本

五、验证测试

    # 检查 postsrsd 运行状态
    docker exec mailserver ps aux | grep postsrsd
    # 输出:postsrsd -d toocent.cn -s /etc/postsrsd.secret ...

    # 检查端口监听
    docker exec mailserver ss -tlnp | grep -E '10001|10002'
    # 输出:
    # LISTEN 127.0.0.1:10001 (postsrsd)
    # LISTEN 127.0.0.1:10002 (postsrsd)

    # 检查 Postfix 配置
    docker exec mailserver postconf | grep -E 'sender_canonical|recipient_canonical|virtual_alias'
    # 输出:
    # sender_canonical_maps = tcp:127.0.0.1:10001
    # recipient_canonical_maps = tcp:127.0.0.1:10002
    # virtual_alias_maps = texthash:/etc/postfix/virtual, pcre:/etc/postfix/virtual.pcre

六、总结

本次配置涉及的关键技术点:

┌──────────────┬───────────────────────────────────┐
│ 问题         │ 解决方案                          │
├──────────────┼───────────────────────────────────┤
│ 通配符转发   │ PCRE 正则表达式映射               │
├──────────────┼───────────────────────────────────┤
│ SPF 检查失败 │ 启用 SRS 重写发件人地址           │
├──────────────┼───────────────────────────────────┤
│ 域名缺少 SPF │ 添加 TXT 记录                     │
├──────────────┼───────────────────────────────────┤
│ 配置持久化   │ user-patches.sh + postfix-main.cf │
└──────────────┴───────────────────────────────────┘

注意事项:

    1. SRS 的 secret 密钥需要妥善保存,更换后之前重写的地址将无法退信
    2. SPF 记录是邮件送达的基础,必须配置正确
    3. 建议同时配置 DKIM 和 DMARC 以提高邮件送达率
    4. 定期检查邮件日志,监控转发状态

参考文档:

    * [Docker-Mailserver 官方文档](https://docker-mailserver.github.io/docker-mailserver/)
    * [Postfix PCRE Table](http://www.postfix.org/pcre_table.5.html)
    * [Sender Rewriting Scheme](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme)