【问题标题】:Greenmail SMTP server is not working properly as custom docker imageGreenmail SMTP 服务器无法作为自定义 docker 镜像正常工作
【发布时间】:2018-12-04 12:27:20
【问题描述】:

我试图在 Spring Boot 应用程序中启动一个 greenmail 服务器并将其 dockerize,以便我可以将它用作本地邮件模拟服务器,以在我的原始应用程序中对邮件功能进行行为测试。

当使用docker-compose up -d 命令和从 REST 客户端测试的端点开始时,docker 映像工作正常。

当我尝试从我的原始应用程序连接它以测试在容器中运行的 docker 映像时,就会出现此问题。

下面添加了我尝试向模拟服务器发送邮件时的异常跟踪。

org.springframework.mail.MailSendException:邮件服务器连接 失败的;嵌套异常是 javax.mail.MessagingException: 不能 连接到 SMTP 主机:127.0.0.1,端口:8585,响应:-1。失败的 消息:javax.mail.MessagingException:无法连接到 SMTP 主机:127.0.0.1,端口:8585,响应:-1 在 org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:446) ~[spring-context-support-5.1.2.RELEASE.jar:5.1.2.RELEASE] 在 org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:359) ~[spring-context-support-5.1.2.RELEASE.jar:5.1.2.RELEASE] 在 org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:354) ~[spring-context-support-5.1.2.RELEASE.jar:5.1.2.RELEASE] 在 com.test.controller.MailTestController.sendMail(MailTestController.java:80) 〜[主要/:na] 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171] 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171] 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171] 在 java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171] ..................................................... ..................................................... ... ..................................................... ..................................................... ...

原因:javax.mail.MessagingException:无法连接到 SMTP 主机:127.0.0.1,端口:8585,响应:-1 在 com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2197) ~[javax.mail-1.6.2.jar:1.6.2] 在 com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740) ~[javax.mail-1.6.2.jar:1.6.2] 在 javax.mail.Service.connect(Service.java:366) ~[javax.mail-1.6.2.jar:1.6.2] 在 org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:515) ~[spring-context-support-5.1.2.RELEASE.jar:5.1.2.RELEASE] 在 org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:435) ~[spring-context-support-5.1.2.RELEASE.jar:5.1.2.RELEASE] ...省略了 100 个常用帧

下面添加了mail-mock-server的DockerFile配置和docker-compose.yml。

DockerFile :-

FROM gcr.io/distroless/java:latest

VOLUME /opt/test/

ARG JAR_FILE
COPY libs/mock-mail-server-*.jar /opt/test/mock-mail-server-app.jar
WORKDIR /opt/test/
CMD ["mock-mail-server-app.jar"]

docker-compose.yml :-

version: '3'
services:
  app:
    image: test/mock-mail-server:0.0.1-SNAPSHOT
    container_name: mock-mail-server-app
    ports: 
      - 0.0.0.0:8484:8484
      - 127.0.0.1:8585:8585

并且greenmail服务器在主类中启动如下。

@SpringBootApplication
public class MailMockServerApplication {

  public static void main(String[] args) {
    SpringApplication.run(MailMockServerApplication.class, args);
  }

  @Bean
  public GreenMail greenMail() {
    GreenMail smtpServer = new GreenMail(new ServerSetup(8585, "127.0.0.1", "smtp"));
    smtpServer.setUser("test.mailer@test.com", "test", "test");
    smtpServer.start();
    return smtpServer;
  }
}

在构建 docker 映像并使用命令 docker-compose up -d 启动 docker 容器后,我在原始应用程序的 application.yml 文件中尝试了 JavaMailSender bean 的以下配置。

mail:
    default-encoding: UTF-8
    host: ${MAIL_SERVER_HOST:127.0.0.1}
    username: ${MAIL_SERVER_USER_NAME:test}
    password: ${MAIL_SERVER_PASSWORD:test}
    port: ${MAIL_SERVER_PORT:8585}
    properties:
      mail:
        debug: true
        smtp:
          debug: false
          auth: true
          starttls: true
    protocol: smtp
    test-connection: false

同时,当我的模拟邮件服务器应用程序从命令行使用java -jar 命令时,这可以正常工作。但是当我在 docker 中尝试相同的操作时,它会因连接异常而失败。

我的原始应用程序或模拟服务器应用程序中是否缺少任何其他配置?

任何帮助将不胜感激。

【问题讨论】:

  • 从您的应用程序的角度来看,SMTP 服务没有在localhost 上运行。
  • @DavidMaze :但是当我使用 netstat 检查时,SMTP 服务器正在侦听端口 8585。并且可以从 REST 客户端测试端点。
  • 你需要将端口而不是 127.0.0.1 暴露到 0.0.0.0 并暴露它。在 docker 内部,它是 docker 容器的本地。所以不会监听主机上运行的代码

标签: java spring docker docker-compose jakarta-mail


【解决方案1】:

在运行 docker 容器后,您是否检查过您指定的端口上是否有任何服务正在侦听?这个 [windows/linux] 有 netstat 命令。如果没有服务监听它会给你无法连接到服务器错误。

docker exec -ti <container> bash

可以像基础镜像一样用于linux。或者尝试从您的 smtp 服务中获取一些详细的日志。

CMD 将是容器中运行的唯一进程,除非它具有进程管理器。

目前尚不清楚“作为 java -jar 执行时它是否有效”是在您尝试命令 CMD 时还是在本地机器上的 docker 外部时。你能澄清一下吗?

如聊天中所述 -

服务器位于配置为侦听 127.0.0.1:8585 的容器内,并且您在主机上公开了相同的端口。
所以解决问题

您需要将 smtp 服务器配置为在 0.0.0.0 上侦听,因为使用 127.0.0.1 使其侦听源自容器内部的连接,因为容器的 127.0.0.1 和容器的 127.0.0.1 与主机的 localhost 不同客户端尝试连接的机器。 所以下面的改变会做 -

 GreenMail smtpServer = new GreenMail(new ServerSetup(8585, "0.0.0.0", "smtp"));

和应用程序的配置yaml文件

 host: ${MAIL_SERVER_HOST:0.0.0.0}

虽然 docker-compose 文件配置 127.0.0.1:8585:8585 可以更改为 8585:8585 以侦听所有主机地址,例如端口转发或除环回 ip 之外的主机 ip。

【讨论】:

  • 你可以更新它吗?对于其他也想帮助你的人来说会更好,你能在本地地址中看到端口 8585 - 试试 netstat -tulpen
  • ok 服务正在监听。但是您的代码如何尝试连接它?同一个容器还是形成其他容器?
  • 随着这个 docker 镜像的运行,我正在尝试从另一个作为 Spring Boot 应用程序启动的应用程序连接它。它在容器之外。
  • 正确。 127.0.0.1 的 IP 在容器内是本地的。所以暴露并不能解决问题。它不会监听外部连接。将其视为在 VM 中运行您的代码,您可以在 0.0.0.0:8585 上监听并公开它,分享进一步的问题
  • 那么应该怎么做才能解决这个问题呢?如果你能在我的 docker-compose.yml 中建议配置会更好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 2021-10-21
  • 2016-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多