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

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ł

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:12:34