配置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
相关产品推荐
相关产品推荐

