Glassfish中JavaMail Session报错:IMAPProvider非jakarta.mail.Provider子类型
解决方案:解决Glassfish 7中JavaMail的ServiceConfigurationError
核心原因
这个错误是API/实现版本冲突导致的:
- Glassfish 7.0.5自带了Jakarta Mail 2.1.x的实现(适配Jakarta EE 10规范)
- 你的项目大概率引入了冲突依赖:要么是Java EE时代的旧
javax.mail包,要么是版本不匹配的jakarta.mail依赖,或是重复引入了邮件实现类(比如com.sun.mail:imap),导致类加载时出现类型不兼容问题。
具体修复步骤
1. 清理项目依赖
检查你的pom.xml(Maven)或build.gradle(Gradle),按以下规则调整:
- 彻底移除所有
javax.mail相关依赖(比如javax.mail:mail) - 仅保留Jakarta Mail API,并设置为
providedscope(因为Glassfish已内置实现)
Maven示例:
Gradle示例:<dependency> <groupId>jakarta.mail</groupId> <artifactId>jakarta.mail-api</artifactId> <version>2.1.2</version> <scope>provided</scope> </dependency>implementation 'jakarta.mail:jakarta.mail-api:2.1.2' providedRuntime 'jakarta.mail:jakarta.mail-api:2.1.2' - 删除任何
com.sun.mail:jakarta.mail、com.sun.mail:imap这类实现类依赖,避免与Glassfish内置实现冲突
2. 检查部署包(WAR)
如果清理依赖后问题仍存在,解压你的WAR包确认:
WEB-INF/lib下没有jakarta.mail-api.jar、jakarta.mail.jar或imap.jar这类文件- 所有邮件相关类都来自Glassfish的内置库,而非项目自带
3. 验证Mail Session配置
确保Glassfish中的Mail Session适配Jakarta EE规范:
- 登录Glassfish管理控制台,进入
Resources > JavaMail Sessions - 确认Session的配置参数(如
mail.imap.host、mail.smtp.port)符合Jakarta Mail 2.1规范 - 代码中通过
@Resource注入Session时,使用jakarta.mail.Session类型,而非旧的javax.mail.Session
4. 清理Glassfish缓存
缓存残留可能导致旧类未更新,执行以下操作:
- 停止Glassfish服务器
- 删除
glassfish/domains/[你的域名]/cache和glassfish/domains/[你的域名]/generated目录下的所有内容 - 重启服务器并重新部署应用
正确的EmailSender类示例
确保你的启动类使用标准Jakarta Mail API:
import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.ejb.Singleton; import jakarta.ejb.Startup; import jakarta.mail.Message; import jakarta.mail.MessagingException; import jakarta.mail.Session; import jakarta.mail.Transport; import jakarta.mail.internet.InternetAddress; import jakarta.mail.internet.MimeMessage; import jakarta.annotation.Resource; @Startup @Singleton public class EmailSender { @Resource(name = "mail/MyMailSession") // 对应Glassfish中配置的Session名称 private Session mailSession; @PostConstruct public void onAppStart() { sendMail("App Started", "Web application has been successfully started."); } @PreDestroy public void onAppStop() { sendMail("App Stopped", "Web application has been stopped."); } private void sendMail(String subject, String content) { try { Message message = new MimeMessage(mailSession); message.setFrom(new InternetAddress("sender@example.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient@example.com")); message.setSubject(subject); message.setText(content); Transport.send(message); } catch (MessagingException e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Mouhamed Ndiaye
相关产品推荐
相关产品推荐

