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

Java17+SpringBoot3.0.6部署K8s时JavaMailSender无法解析SMTP主机名

问题:Java17+SpringBoot3部署在AWS EKS 1.24后无法通过SMTP主机名发送邮件

背景

我们正在将Java服务从Java11+SpringBoot2.7.1迁移至Java17+SpringBoot3.0.6,通过Docker镜像部署到AWS Kubernetes 1.24(EKS)环境。原版本可正常发送邮件,但升级后使用SMTP主机名时出现连接失败错误。

关键现象

  • 使用SMTP服务器IP地址时,Java17+SpringBoot3.0.6版本可正常工作
  • 本地IDE中,两个版本使用主机名或IP均能正常发送邮件
  • 将代码打包为Jar在AWS虚拟机(EC2)上运行Java17版本,使用主机名也可正常触发邮件
  • 仅在EKS环境中部署Docker镜像后,使用SMTP主机名会抛出UnknownHostException

邮件发送报错日志

12:46:48 DEBUG SMTP: trying to connect to host "company smpt host", port 25, isSSL false
12:46:48 ("timestamp":"07-03-2023 GMT 07:14:19.672","level": "ERROR", "thread":"http-nio-8081-exec-6", "logger":"com.emailer.service.FreeMarkerEMailSevice", "message":"Email sending failed with exception : {}","context":"default", "exception":"com.sun.mail.util.MailConnectException: Couldn't connect to host, port: <company.smtpserver.com>, 5000
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2259)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:754)
    at jakarta.mail.Service.connect(Service.java:342)
    at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:518)
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:437)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:361)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:356)
    ...
    java.net.UnknownHostException: <company smtp host>
    at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
    at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:331)
    at java.base/java.net.Socket.connect(Socket.java:630)
    at com.sun.mail.util.WriteTimeoutSocket.connect(WriteTimeoutSocket.java:104)
    at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:355)

主机名解析报错日志

12:45:48 {"timestamp":"07-03-2023 GMT 07:16:35.225","level":"ERROR", "thread":"http-nio-8081-exec-7","logger":"com.emailer.service.FreeMarkerEMailSevice", "message":"error occurred while trying to get ipaddress <company smtp server>","context":"default"}
12:46:48 {"timestamp":"07-03-2023 GMT 07:16:35.226","level":"ERROR", "thread":"http-nio-8081-exec-7","logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]", "message":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: java.net.UnknownHostException <company smtp server>: Try again] with root cause", "context":"default", "exception":"java.net.UnknownHostException: <company smtp server>: Try again
    at java.base/java.net.InetAddressImpl.lookupAllHostAddr(Native Method)
    at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:932)
    at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1517)
    at java.base/java.net.InetAddress$ServiceAddresses.get(InetAddress.java:851)
    at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1587)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1366)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1300)
    at java.base/java.net.InetAddress.getByName(InetAddress.java:1250)
    ...

应用配置(application.yaml)

spring.mail.host = <company smtpserver>
spring.mail.port= 25
spring.mail.username = xxxxx
spring.mail.password = xxxx
spring.mail.properties.mail.smtp.auth = true;
spring.mail.properties.mail.smtp.starttls.enable = true
spring.mail.properties.mail.transport.protocol = smtp
spring.mail.properties.mail.smtp.timeout = 5000

核心代码

@Service
public class EmailService{

    private JavaMailSender emailSender;

    public EmailService(JavaMailSender emailSender){
        this.emailSender = emailSender;
    }
    
    @Override
    public void sendEmail(MailModel mailModel) {
        MimeMessage message = emailSender.createMimeMessage();
        try{
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message,true);
           
            Template template = emailConfig.getTemplate("email4.ftl");
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, mailModel.getModel());
            mimeMessageHelper.setTo(mailModel.getTo());
            mimeMessageHelper.setText(html, true);
            mimeMessageHelper.setSubject(mailModel.getSubject());
            mimeMessageHelper.setFrom(mailModel.getFrom());

            emailSender.send(mimeMessageHelper.getMimeMessage());
        }catch(Exception e){
            log.error("exception occurred {}", e.getCause());
        }
    }
}

解决方案

1. 检查EKS Pod的DNS配置

  • 确认EKS集群CoreDNS组件运行正常:
    kubectl get pods -n kube-system -l k8s-app=kube-dns
    
  • 进入问题Pod直接测试DNS解析:
    kubectl exec -it <你的Pod名称> -- nslookup <公司SMTP服务器主机名>
    
    如果解析失败,检查Pod的dnsPolicy是否为默认的ClusterFirst,是否存在自定义dnsConfig覆盖了默认配置。

2. 调整Java17的DNS缓存策略

Java17默认DNS缓存时长比Java11更长,可能导致无法及时获取最新DNS记录。在JVM启动参数中添加以下配置缩短缓存时间:

-Dsun.net.inetaddr.ttl=60 -Dsun.net.inetaddr.negative.ttl=10
  • sun.net.inetaddr.ttl:正向DNS记录缓存时长(单位:秒)
  • sun.net.inetaddr.negative.ttl:失败DNS记录缓存时长(单位:秒)

3. 验证Docker镜像与Pod的DNS配置

  • 确保Docker镜像未自定义DNS配置,构建时不要添加--dns参数
  • 若需要,可在Kubernetes的Pod Spec中显式指定DNS服务器:
    spec:
      containers:
      - name: 你的应用名称
        image: 你的镜像地址:版本
      dnsPolicy: ClusterFirst
      dnsConfig:
        nameservers:
        - 8.8.8.8
        - 1.1.1.1
    

4. 检查VPC网络与私有DNS配置

如果SMTP服务器是AWS内部服务或企业私有服务:

  • 确认EKS集群所在VPC与SMTP服务器所在VPC已建立对等连接
  • 检查是否配置了正确的私有DNS区域,确保Pod能解析内部主机名

5. 临时规避方案

若以上方法暂时无法解决,可先在配置中使用SMTP服务器IP地址(已验证可行),同时联系运维团队排查DNS根因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:45:13