You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TestContainers部署Apache James遇SMTP端口连接拒绝求助

Apache James TestContainers 连接拒绝问题解决

问题场景

通过TestContainers运行Apache James容器,等效于以下Docker命令:

docker run --name james_run -p "25:25" -p "465:465" -p "587:587" -p "143:143"  -p "993:993" --volume "$PWD/conf:/root/conf/" --volume "$PWD/var:/root/var/" apache/james:latest

对应的TestContainers代码:

james = new GenericContainer(DockerImageName.parse("apache/james")).withExposedPorts(25, 465, 587, 143, 993, 8000).withFileSystemBind(EmailServerIT.class.getClassLoader().getResource("conf").getPath(),"/root/conf", BindMode.READ_WRITE).withFileSystemBind(EmailServerIT.class.getClassLoader().getResource("var").getPath(),"/root/var", BindMode.READ_WRITE);

尝试向SMTP端口发送邮件时出现连接拒绝错误:

Caused by: javax.mail.MessagingException: Connection error (java.net.ConnectException: Connection refused (Connection refused))

解决方案

1. 修正端口映射逻辑

TestContainers不会直接绑定主机固定端口,而是采用随机端口映射。不能直接使用25/587等原始端口,需通过getMappedPort()获取容器映射到主机的实际端口:

// 获取SMTP提交端口的实际映射端口
int smtpPort = james.getMappedPort(587);
// 发送邮件时使用该端口连接
Properties props = new Properties();
props.put("mail.smtp.port", smtpPort);

2. 修复资源路径绑定问题

ClassLoader.getResource("conf")可能返回Jar包内的路径,TestContainers无法直接挂载。改用withClasspathResourceMapping简化classpath资源挂载,或使用正确的本地文件路径:

// 推荐:直接挂载classpath中的资源目录
james = new GenericContainer(DockerImageName.parse("apache/james:latest"))
    .withExposedPorts(25, 465, 587, 143, 993, 8000)
    .withClasspathResourceMapping("conf", "/root/conf", BindMode.READ_WRITE)
    .withClasspathResourceMapping("var", "/root/var", BindMode.READ_WRITE);

若必须使用withFileSystemBind,需确保资源路径指向本地文件系统:

Path confPath = Paths.get(EmailServerIT.class.getResource("/conf").toURI());
Path varPath = Paths.get(EmailServerIT.class.getResource("/var").toURI());

james = new GenericContainer(DockerImageName.parse("apache/james:latest"))
    .withExposedPorts(25, 465, 587, 143, 993, 8000)
    .withFileSystemBind(confPath.toString(), "/root/conf", BindMode.READ_WRITE)
    .withFileSystemBind(varPath.toString(), "/root/var", BindMode.READ_WRITE);

3. 添加容器就绪检查

Apache James启动需要一定时间,需等待服务完全就绪后再发起连接:

james = new GenericContainer(DockerImageName.parse("apache/james:latest"))
    // 其他配置...
    .waitingFor(Wait.forLogMessage(".*James server is ready.*", 1)
        .withStartupTimeout(Duration.ofMinutes(2)));

4. 验证配置文件有效性

检查挂载的conf目录下配置:

  • 确保smtpserver.xml开启了非SSL端口(25/587),未强制要求SSL认证
  • 若使用SSL端口(465),需确保配置了正确的密钥库,或在测试环境下允许自签名证书

内容的提问来源于stack exchange,提问作者ca55idy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:45:05