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

Spring JavaMailSender与Testcontainers Mailpit集成失败排查

问题分析与解决:Testcontainers中Mailpit邮件发送失败

问题场景

测试环境通过Testcontainers运行Mailpit实例:

@Container
static MailpitContainer mailpitContainer = new MailpitContainer()
    .withNetwork(TESTCONTAINERS_NETWORK);

被测服务本身也部署在Testcontainers实例中:

public class MyServiceUnderTestContainer extends GenericContainer<ArgusBatchContainer> {

    private static final String IMAGE_NAME...

    static {
        Testcontainers.exposeHostPorts(1025);
    }

    public MyServiceUnderTestContainer(Map<String, String> environmentVariables) {
        super(IMAGE_NAME);
        this.withAccessToHost(true);
        this.withNetwork(TESTCONTAINERS_NETWORK);
    }
}

Spring JavaMailSender配置如下:

@Bean
public JavaMailSenderImpl createJavaMailSenderBean() {
    final JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
    mailSender.setHost("host.testcontainers.internal");
    mailSender.setPort(1025);
    mailSender.setUsername("");
    mailSender.setPassword(null);
    mailSender.setProtocol("smtp");
    mailSender.setJavaMailProperties(createJavaMailProperties());
    return mailSender;
}

private Properties createJavaMailProperties() {
    final Properties properties = new Properties();
    properties.put("mail.smtp.auth", false);
    properties.put("mail.smtp.starttls.enable", false);
    properties.put("mail.smtp.connectiontimeout", 180000);
    properties.put("mail.smtp.timeout", 180000);
    return properties;
}

运行时出现如下错误:

org.springframework.mail.MailSendException: Mail server connection failed. Failed messages: jakarta.mail.MessagingException: Got bad greeting from SMTP host: host.testcontainers.internal, port: 1025, response: [EOF]

错误原因

  • 访问目标错误:host.testcontainers.internal指向Testcontainers宿主机,但Mailpit容器运行在Testcontainers内部的TESTCONTAINERS_NETWORK网络中,并未将1025端口映射到宿主机,导致服务容器访问宿主机1025端口时无任何响应,返回EOF。
  • 冗余操作干扰:被测服务容器中的Testcontainers.exposeHostPorts(1025);完全多余,Mailpit不在宿主机运行,该操作不仅无效,还可能造成端口逻辑混淆。

解决方法

1. 通过容器内部网络访问Mailpit

由于Mailpit容器和被测服务容器同属TESTCONTAINERS_NETWORK网络,可直接使用Mailpit容器的名称或自定义别名作为SMTP主机地址:

  • 方法一:直接传递Mailpit容器名称
    修改JavaMailSender的主机配置:
    mailSender.setHost(mailpitContainer.getContainerName());
    mailSender.setPort(1025); // 容器内部默认SMTP端口
    
  • 方法二:给Mailpit设置固定网络别名
    先给Mailpit容器配置固定别名:
    @Container
    static MailpitContainer mailpitContainer = new MailpitContainer()
        .withNetwork(TESTCONTAINERS_NETWORK)
        .withNetworkAliases("mailpit"); // 设置固定别名
    
    然后在JavaMailSender中使用该别名:
    mailSender.setHost("mailpit");
    mailSender.setPort(1025);
    
  • 方法三:通过环境变量传递配置(推荐,解耦代码与配置)
    构建被测服务容器时传入Mailpit连接信息:
    Map<String, String> env = new HashMap<>();
    env.put("MAIL_HOST", mailpitContainer.getContainerName());
    env.put("MAIL_PORT", "1025");
    MyServiceUnderTestContainer serviceContainer = new MyServiceUnderTestContainer(env);
    
    再在JavaMailSender配置中读取环境变量:
    mailSender.setHost(System.getenv("MAIL_HOST"));
    mailSender.setPort(Integer.parseInt(System.getenv("MAIL_PORT")));
    

2. 移除冗余的端口暴露代码

删除被测服务容器中的静态代码块:

// 移除该冗余代码
static {
    Testcontainers.exposeHostPorts(1025);
}

3. 验证网络连通性(可选)

可在被测服务容器内执行以下命令,验证与Mailpit的网络连通性:

telnet mailpit 1025
# 或使用nc命令
nc -zv mailpit 1025

若能成功连通,说明网络配置正确。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 21:44:53