如何捕获Playframework中MailerClient抛出的异常?
如何捕获Play-Mailer的所有异常
我来帮你梳理下Play-Mailer异常捕获的问题,结合实际使用经验,分几种场景来解决:
1. 同步发送的异常捕获
如果你用的是同步版的mailerClient.send(email)方法,理论上底层的异常应该能被捕获,但你说没抓到,大概率是没正确包裹try-catch,或者没覆盖到异常类型。试试这样写:
@Inject MailerClient mailerClient; public void sendTestEmail() { Email email = new Email() .setSubject("测试邮件") .setFrom("your@example.com") .addTo("invalid-user@non-existent-domain.com") .setBodyText("测试内容"); try { mailerClient.send(email); } catch (MailerException me) { // 优先捕获Play-Mailer封装的专属异常 System.err.println("邮件发送失败(Play-Mailer异常):" + me.getMessage()); me.printStackTrace(); } catch (Exception e) { // 兜底捕获所有其他异常,包括底层commons mail的EmailException System.err.println("邮件发送失败(通用异常):" + e.getMessage()); e.printStackTrace(); } }
有些Play-Mailer版本会把Apache Commons Mail的EmailException包装成自己的MailerException,所以分两层捕获会更稳妥。
2. 异步发送的异常捕获
如果用的是异步API(返回CompletionStage<Void>的sendAsync方法),异常不会直接抛出,而是藏在CompletionStage的失败回调里,这时候得用回调来处理:
@Inject MailerClient mailerClient; public CompletionStage<Void> sendEmailAsync() { Email email = new Email() .setSubject("异步测试邮件") .setFrom("your@example.com") .addTo("invalid-user@non-existent-domain.com") .setBodyText("异步测试内容"); return mailerClient.sendAsync(email) .whenComplete((unused, ex) -> { if (ex != null) { // 处理异步发送的异常 System.err.println("异步邮件发送失败:" + ex.getMessage()); ex.printStackTrace(); } }); }
这种场景下,try-catch是抓不到异常的,必须通过whenComplete或者exceptionally来处理失败分支。
3. 排查异常的辅助手段
如果还是抓不到异常,建议开启Play-Mailer的DEBUG日志,看看底层到底发生了什么。在application.conf里添加:
logger.play.mailer=DEBUG logger.org.apache.commons.mail=DEBUG
这样就能看到邮件发送全流程的详细日志,包括异常的完整堆栈,帮你定位问题。
特殊情况提醒
还有一种情况:有些邮件服务器会先接收邮件,之后再退回(比如生成退信),这种情况下Play-Mailer的send方法不会抛出异常,因为请求已经被服务器接受了。这种场景下,你需要监听退信邮箱,或者配置邮件服务器的回调通知来处理。
内容的提问来源于stack exchange,提问作者Jörg Bergner
相关产品推荐
相关产品推荐

