彻底解决Podman运行PMail无法发出信件和偶发性接收失败的网络问题
这是困扰我许久的问题,但是一直没有时间解决,我已经无法忍受这种局面今天务必解决。
错误日志
通过podman logs -f 命令可以看到关键报错如下
[error][2025-11-27 20:26:34][0a5900036928433ebea500015475dab0][/work/utils/send/send.go:80][email protected]%!(EXTRA string=域名mx记录查询失败,检查邮箱是否存在!)
[debug][2025-11-27 20:26:34][/work/utils/smtp/smtp.go:415]SendMail, ,smtp.gmail.com:25 ,[email protected] ,linuxuser.site ,[[email protected]]
[info][2025-11-27 20:26:36][0a5900036928433ebea500015475dab0][/work/utils/send/send.go:135]SMTP STARTTLS on 25 Send Error. dial tcp: lookup smtp.gmail.com: i/o timeout
[info][2025-11-27 20:26:38][0a5900036928433ebea500015475dab0][/work/utils/send/send.go:142]SMTPS on 587 Send Error. dial tcp: lookup smtp.gmail.com: i/o timeout
[info][2025-11-27 20:26:40][0a5900036928433ebea500015475dab0][/work/utils/send/send.go:149]SMTPS on 465 Send Error. dial tcp: lookup smtp.gmail.com: i/o timeout
[error][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/utils/send/send.go:159][0xc000290380] 邮件投递失败dial tcp: lookup smtp.gmail.com: i/o timeout
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/controllers/email/send.go:210]插件执行--SendAfter
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/hooks/base.go:74][wechat_push]Plugin SendAfter Start
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/hooks/base.go:74][spam_block]Plugin SendAfter Start
[error][2025-11-27 20:26:42][/work/hooks/framework/framework.go:123]params error json: cannot unmarshal object into Go struct field HookDTO.ErrMap of type error
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/hooks/base.go:88][wechat_push]Plugin SendAfter End
[error][2025-11-27 20:26:42][/work/hooks/framework/framework.go:123]params error json: cannot unmarshal object into Go struct field HookDTO.ErrMap of type error
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/hooks/base.go:88][spam_block]Plugin SendAfter End
[debug][2025-11-27 20:26:42][0a5900036928433ebea500015475dab0][/work/controllers/email/send.go:222]插件执行--SendAfter分析问题
显然DNS解析有问题,容器的网络似乎存在异常。
现在宿主机nslookup smtp.gmail.com确定主机网络无异常。podman exec -it pmail /bin/ash 进入容器内再次执行ping等测试均失败确定容器网络确实有问题。
接下来又遇到了经典的问题:停止容器时报错send signal to pidfd: Permission denied
我仔细看了自己的配置文件怀疑这和restart=always有关,因为文档对这一选项的描述是:总是重启。无论容器因何退出(即使是正常退出),都会无条件重启。
但是改用unless-stop或者no也存在这个问题:
root@racknerd-14a7c8:~/pmail# podman-compose down
ERRO[0000] unable to signal init: permission denied
Error: timed out waiting for file /run/libpod/exits/ff442b3e80859da0d59c021764d9896b514b50b721b8a1d92df0dc673de5031c: internal libpod error
^CERRO[0010] container init still running
Error: 1 error occurred:
* removing container ff442b3e80859da0d59c021764d9896b514b50b721b8a1d92df0dc673de5031c from pod 981b7ae00e26382f42f160106dc882f60a816b50b0db81d0b09196aa5aac4a50: cleaning up container ff442b3e80859da0d59c021764d9896b514b50b721b8a1d92df0dc673de5031c: removing container ff442b3e80859da0d59c021764d9896b514b50b721b8a1d92df0dc673de5031c from runtime: `/usr/bin/runc delete --force ff442b3e80859da0d59c021764d9896b514b50b721b8a1d92df0dc673de5031c` failed: exit status 1我暂时放下这个问题,因为这似乎并不影响容器正常工作,只是在停止时带来了一些麻烦。
另外通过
podman run --rm alpine ping -c 3 8.8.8.8
podman run --rm alpine nslookup google.com测试发现桥接模式的容器均无法访问外部网络,而且使用podman system reset --force重置也无法改变这个问题,怀疑和Racknerd的VPS配置或者VPS系统镜像的某些配置有关。通过一番繁琐的尝试,我确定自己暂时也无法解决桥接模式的网络问题,所以我决定先切换到host模式试试看。
切换到Host模式后容器的网络就等于主机网络,测试邮件发送和ping,nslookup确定Pmail容器在Host网络模式下终于正常了。
那么主要问题就明确为:podman容器 bridge模式下网络的异常。
考虑到Github上暂时还没有发现这一问题,并且作者的容器本身的目标平台是使用Docker,所以这个问题可能和podman本身的问题有关。
通过DeepSeek和ChatGPT结合当前情况检索信息后,我认为有比较大可能和Podman当前版本默认使用的网络后端 netavark 有关。
Podman 4.0 开始,Netavark 被设为默认网络后端。
CNI 虽然仍被支持(“deprecated” — 已弃用),但默认情况下不会启用;如果需要使用 CNI,则必须在配置文件(containers.conf)中明确将 network_backend = "cni" 设置启用。
root@racknerd-14a7c8:~/pmail# podman info --format '{{.Host.NetworkBackend}}'
netavark毫无疑问接下来得试试切换回CNI模式的桥接网络容器是否正常工作。 nano /etc/containers/containers.conf 添加:
[network]
network_backend = "cni"
再次执行podman system reset --force确保除刚才写入的配置之外的非默认修改完全清除
podman info --format '{{.Host.NetworkBackend}}'
发现已经切换到CNI了,再次以桥接模式启动容器,测试是否正常:
podman-compose up -d
podman exec pmail nslookup smtp.gmail.com
podman exec pmail ping -c 3 8.8.8.8
发现对外网络访问仍然不正常,真令人头大😭
也许只能暂时切到host模式了(其实也没啥不好的,甚至性能更高),而我不打算使用Docker再进行一遍测试。
告知DS后,DS也建议使用Host模式,并且提醒我考虑尝试 slirp4netns 网络模式(一个用户空间的网络栈,可能绕过 VPS 限制)。podman run --rm --network slirp4netns alpine ping -c 3 8.8.8.8
居然成功了!几乎确定就是Racknerd导致的,他们的某些配置禁用了VPS的桥接网络。
开始部署可用的方案
先删了刚才创建用于测试的网络podman network prune -f
接着干脆再podman system reset --force重置一下。
修改配置文件:
version: '3'
services:
pmail:
image: ghcr.io/jinnrry/pmail:latest
container_name: pmail
restart: unless-stopped # 避免未来使用shell脚本控制更新容器镜像时停止容器潜在的失败问题。
network_mode: "slirp4netns" # 使用已验证可用的网络模式
ports:
- "25:25"
- "2080:80"
- "20443:443"
- "110:110"
- "465:465"
- "995:995"
- "993:993"
volumes:
- "/root/podman/pmail/config:/work/config"
注意slirp4netns不支持自定义DNS,作为一个用户空间的网络栈实现会使用宿主机的DNS配置,并且不需要创建自定义网络。(后来发现,Podman rootless下默认使用的就是slirp4netns ,对我来说主要的缺陷就是容器之间无法直接通过 slirp4netns 进行通信。)
至此,影响发件的主要问题已经基本解决,潜在的的性能问题暂时也不会对我的服务构成可用性威胁。