GitHub Actions出站SMTP被拦截,如何解决该问题?
解决方案
1. 在GitHub Actions中启动本地支持认证的SMTP+IMAP测试服务器
这是最直接的替代方案,既能避开出站端口拦截问题,又能完整验证邮件投递+接收的全流程。推荐使用GreenMail——它是专为测试场景设计的邮件服务器,支持SMTP、IMAP、POP3协议,还自带认证功能。
在你的GitHub Actions工作流文件(比如.github/workflows/test.yml)中添加服务容器配置:
jobs: test: runs-on: ubuntu-latest services: greenmail: image: greenmail/standalone:latest ports: - 3025:3025 # 映射本地SMTP端口 - 3143:3143 # 映射本地IMAP端口 env: GREENMAIL_OPTS: "-Dgreenmail.setup.test.all -Dgreenmail.users=test:test" # 预设测试账号:用户名test,密码test
之后在单元测试代码中,把SMTP和IMAP服务器地址改为localhost,端口对应上面的3025和3143,用预设的账号密码完成认证即可。这样就能在GitHub Actions环境中完成完整的发件+收件验证,无需禁用测试。
2. 自己在测试代码中启动轻量SMTP+IMAP服务器(Go语言)
如果不想依赖容器,可以在测试的Setup阶段直接启动本地的SMTP和IMAP服务器,借助Go生态的库实现:
- 用
github.com/emersion/go-smtp搭建带认证的SMTP服务器 - 用
github.com/emersion/go-imap/server搭建IMAP服务器
核心思路示例代码:
func TestEmailDelivery(t *testing.T) { // 启动带认证的SMTP服务器 smtpBackend := &smtpBackend{users: map[string]string{"test": "test"}} smtpServer := smtp.NewServer(smtpBackend) smtpServer.Addr = ":3025" go func() { if err := smtpServer.ListenAndServe(); err != nil { t.Fatalf("SMTP server start failed: %v", err) } }() defer smtpServer.Close() // 启动IMAP服务器 imapBackend := &imapBackend{mailbox: make(map[string][]*imap.Message)} imapServer := imapserver.New(imapBackend) imapServer.Addr = ":3143" go func() { if err := imapServer.ListenAndServe(); err != nil { t.Fatalf("IMAP server start failed: %v", err) } }() defer imapServer.Close() // 执行发邮件逻辑,目标地址localhost:3025,账号test/test // 然后通过IMAP连接localhost:3143,检查邮件是否成功投递 }
自行实现backend处理认证和邮件存储,完全在测试进程内完成,不需要外部依赖,也能解决认证和投递验证的核心需求。
3. 临时过渡方案(仅作补充)
如果以上方案暂时没时间落地,可以用条件编译或测试标签,在GitHub Actions运行时跳过该测试,同时单独维护一个每月手动触发的工作流专门测试邮件功能。这种方案能暂时兼顾CI覆盖率和邮件逻辑验证,但不如前两种方案彻底。
内容的提问来源于stack exchange,提问作者vy32
相关产品推荐
相关产品推荐

