JavaMailSender异常处理咨询:邮件服务异常如何处理
邮件发送场景的异常处理方案
首先得指出你现有代码的核心问题:你的MailService把所有发送邮件时的异常都“吞”掉了——catch块里只打了日志,没有把异常向上抛出,所以上层Controller根本拿不到邮件发送失败的信号,只能捕获模板引擎处理时的IOException。要实现你想要的“在HTML视图显示错误信息或重定向到404”,得先调整异常的传递逻辑,再做上层处理。
下面给你两种实用的处理方案,按需选择:
方案一:局部try-catch + 自定义业务异常(适合单个Controller处理邮件的场景)
第一步:重构MailService,抛出自定义异常
不要在Service层把异常吞掉,而是定义一个业务异常类,把邮件发送失败的异常包装后抛给上层:
// 自定义邮件发送异常类 public class MailSendException extends RuntimeException { public MailSendException(String message, Throwable cause) { super(message, cause); } } // 修改后的MailService public class MailService { public final JavaMailSender emailSender; // 方法声明抛出自定义异常 public void sendMail(String content, String to, Boolean isHtml, String subject, String path) throws MailSendException { log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}", true, isHtml, to, subject, content); MimeMessage mimeMessage = emailSender.createMimeMessage(); try { MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, CharEncoding.UTF_8); message.setTo(to); message.setFrom("applica@applica.ai"); message.setSubject(subject); message.setText(content, isHtml); FileSystemResource file = new FileSystemResource(path); message.addAttachment(file.getFilename(), file); emailSender.send(mimeMessage); log.debug("Sent e-mail to User '{}'", to); } catch (Exception e) { log.warn("E-mail could not be sent to user '{}'", to, e); // 抛出自定义异常,把根源异常传进去 throw new MailSendException("Failed to send email to " + to, e); } } }
第二步:在Controller里捕获异常并处理
现在Controller能拿到邮件发送失败的异常了,就可以根据不同异常类型返回对应的视图或重定向:
@GetMapping("/send-mail") // 假设这是你的请求映射 public String sendMail(UserInfo userInfo, Model model) { try { // 先处理模板渲染,这里可能抛出IOException String mailContent = templateEngine.process("summary/mailTemplate", ctx); // 调用邮件服务,可能抛出MailSendException mailService.sendMail(mailContent, userInfo.getEmail(), true, "Mail title", "attachment title"); // 发送成功:返回成功页面并传递提示信息 model.addAttribute("successMsg", "邮件已成功发送至你的邮箱!"); return "mail/success"; } catch (IOException e) { log.error("Failed to render mail template", e); // 模板处理失败:返回错误页面或重定向到404 model.addAttribute("errorMsg", "邮件模板加载失败,请联系管理员"); return "error/404"; // 或者用重定向:return "redirect:/404"; } catch (MailSendException e) { log.error("Failed to send email", e); // 邮件发送失败:返回错误页面提示用户 model.addAttribute("errorMsg", "邮件发送失败,请稍后重试"); return "error/mail-fail"; // 如果想直接跳404也可以:return "redirect:/404"; } }
方案二:全局异常处理器(适合多Controller或统一异常处理的场景)
如果你的项目里有多个地方需要处理异常,用@ControllerAdvice做全局异常处理会更简洁,不用每个Controller都写重复的try-catch代码。
第一步:定义全局异常处理器
@ControllerAdvice public class GlobalExceptionHandler { // 处理邮件发送异常 @ExceptionHandler(MailSendException.class) public String handleMailSendException(MailSendException e, Model model) { log.error("Email sending failed", e); model.addAttribute("errorMsg", "邮件发送失败:" + e.getMessage()); return "error/mail-fail"; // 自定义错误页面 // 重定向到404的话:return "redirect:/404"; } // 处理模板渲染的IOException @ExceptionHandler(IOException.class) public String handleTemplateIOException(IOException e, Model model) { log.error("Mail template processing failed", e); model.addAttribute("errorMsg", "邮件模板加载失败"); return "error/template-error"; } // 处理其他通用运行时异常 @ExceptionHandler(RuntimeException.class) public String handleGeneralRuntimeException(RuntimeException e, Model model) { log.error("Unexpected system error", e); model.addAttribute("errorMsg", "系统出现异常,请稍后重试"); return "error/general-error"; } }
第二步:简化Controller代码
现在Controller里不需要写try-catch,直接抛出异常即可,全局处理器会自动捕获并处理:
@GetMapping("/send-mail") public String sendMail(UserInfo userInfo, Model model) throws IOException, MailSendException { String mailContent = templateEngine.process("summary/mailTemplate", ctx); mailService.sendMail(mailContent, userInfo.getEmail(), true, "Mail title", "attachment title"); model.addAttribute("successMsg", "邮件已成功发送!"); return "mail/success"; }
额外说明
- 关于重定向到404:404通常是“资源不存在”的场景,邮件发送失败更适合用5xx(服务器错误)或自定义错误页面提示用户,不过如果你业务上需要跳404,直接在异常处理里返回
"redirect:/404"就行。 - 日志记录:不管哪种方案,一定要把异常的根源信息(即
e)传入日志,方便后续排查问题(比如你的原代码里log.warn已经传入了e,这点做得很好)。
内容的提问来源于stack exchange,提问作者Michał
相关产品推荐
相关产品推荐

