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

配置Log4j2 SMTPAppender后无法使用Apache Commons Mail发送邮件

问题分析与解决方案

从你的描述和日志来看,问题出在Log4j2的SMTPAppender初始化时修改了JavaMail的默认Session配置(或系统属性),导致后续Apache Commons Email的HtmlEmail不再使用你代码中指定的smtp.gmail.com,而是错误地连接到localhost。这种冲突大概率和你提到的那个不可控本地依赖有关——它可能干扰了JavaMail的Session管理逻辑,使得Log4j2的配置意外覆盖了Commons Email的设置。

核心解决方案:给Commons Email手动配置独立Session

默认情况下,HtmlEmail会使用Session.getDefaultInstance(),这个方法会优先读取系统级的JavaMail属性(而Log4j2的SMTPAppender可能已经修改了这些属性)。我们可以绕过这个默认逻辑,手动创建一个完全独立的Session,确保Commons Email使用我们指定的SMTP参数。

修改你的发送邮件代码如下:

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.util.Properties;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.EmailAttachment;

// ... 其他业务代码 ...

// 1. 手动构建JavaMail配置属性
Properties mailProps = new Properties();
mailProps.put("mail.smtps.host", "smtp.gmail.com");
mailProps.put("mail.smtps.port", "465");
mailProps.put("mail.smtps.auth", "true");
mailProps.put("mail.smtps.ssl.enable", "true");
mailProps.put("mail.smtps.starttls.enable", "true");

// 2. 创建独立的Session,不依赖默认系统配置
Session customSession = Session.getInstance(mailProps, new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("myorigin@gmail.com", "mypasswd");
    }
});
customSession.setDebug(true); // 保留调试日志,方便后续排查

// 3. 初始化HtmlEmail并绑定自定义Session
HtmlEmail email = new HtmlEmail();
email.setSession(customSession); // 关键:用自定义Session替代默认Session

// 注意:不需要再调用setHostName/setAuthentication/setSmtpPort等方法,Session已包含这些配置
email.setFrom("myorigin@gmail.com", "ERROR SISEMAIL");
email.addTo("mydestination@gmail.com");
email.setSubject("My Subject");
email.setHtmlMsg("My message");
email.setCharset("UTF-8");
email.setDebug(true);

// 附件逻辑保持不变
if (attachs != null) {
    for (File attach : attachs) {
        if (attach != null) {
            EmailAttachment attachment = new EmailAttachment();
            attachment.setPath(attach.getAbsolutePath());
            attachment.setName(attach.getName());
            attachment.setDisposition(EmailAttachment.ATTACHMENT);
            email.attach(attachment);
        }
    }
}

email.send();

为什么这个方案有效?

  • Session.getInstance()会创建一个全新的Session实例,完全基于我们传入的Properties,不会读取任何系统级的JavaMail属性(这些属性可能被Log4j2或你的本地依赖修改)。
  • 直接绑定这个自定义Session到HtmlEmail,就能强制它使用我们指定的SMTP服务器信息,彻底避免配置冲突。

额外排查建议(可选)

如果想确认是哪个环节修改了系统属性,可以在发送邮件代码的最开头添加以下代码,打印JavaMail相关的系统属性:

System.out.println("mail.smtps.host: " + System.getProperty("mail.smtps.host"));
System.out.println("mail.smtp.host: " + System.getProperty("mail.smtp.host"));

如果输出是localhost,就说明Log4j2或你的本地依赖确实修改了这些属性,进一步验证我们的解决方案的必要性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:22:49