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

SpringBoot发送OTP邮件调用sendOtp时出现NullPointerException异常

问题根因

抛出空指针的直接原因是执行this.emailService.sendMail()时,emailService变量为null,由两个常见错误导致:

  • OtpEmailController中的emailService字段没有添加依赖注入注解,Spring容器不会自动为该字段装配EmailSenderService实例
  • 从错误堆栈可见,sendOtp()方法是在SessionHandlingController.loginUser()中被调用的,如果你是通过new OtpEmailController()手动创建实例后调用方法,该实例不受Spring容器管理,即使加了注入注解,所有依赖字段也会是null

另外你的现有代码还存在几个会影响功能正常运行的隐患:

  • Random random = new Random(1000)使用固定种子初始化随机数生成器,生成的OTP序列完全可预测,没有安全校验价值
  • SimpleMailMessage仅支持纯文本内容,你拼接的<h1>HTML标签会作为明文展示给用户,不会被渲染为标题格式
  • 发件人邮箱拼写错误(gamil.com应为gmail.com),且第三方邮箱SMTP发件需要提前开启服务、配置应用专用密码,直接使用账号密码会发件失败
修复方案
  1. 修正OtpEmailController的依赖注入,替换不安全的随机数生成器,推荐使用构造器注入(Spring 4.3+单构造器无需额外添加@Autowired):
@Controller
public class OtpEmailController {
    
    private final EmailSenderService emailService;
    private final SecureRandom secureRandom = new SecureRandom();

    // 构造器注入,Spring会自动传入装配完成的EmailSenderService Bean
    public OtpEmailController(EmailSenderService emailService) {
        this.emailService = emailService;
    }
    
    @PostMapping("/send-otp")
    public String sendOtp(@RequestParam("email") String email) {
        // 生成固定6位长度的OTP,不足位数补前导零
        int otp = secureRandom.nextInt(1000000);
        String formattedOtp = String.format("%06d", otp);
        
        String subject = "OTP from session-handling-proj By Harshit";
        String body = String.format("<h1>OTP = %s</h1>", formattedOtp);
        
        emailService.sendMail(email, subject, body);
        return "success";
    }
}
  1. 禁止手动new Spring管理的Bean(包括Controller、Service),如果需要在SessionHandlingController中触发OTP发送逻辑,直接注入Spring管理的EmailSenderService或OtpEmailController实例使用。

最佳实践:不要跨Controller调用业务方法,将发OTP的逻辑下沉到Service层,所有Web层Controller只做请求参数接收和响应返回,避免出现对象脱离容器管理的问题。

  1. 修正EmailSenderService支持HTML邮件发送,补全异常处理:
@Service
public class EmailSenderService {

    private final JavaMailSender mailSender;

    public EmailSenderService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }
    
    public void sendMail(String toEmail, String subject, String htmlContent) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            // 替换为正确的发件人邮箱,确保已开启SMTP服务、配置应用专用密码
            helper.setFrom("growthgreek@gmail.com");
            helper.setTo(toEmail);
            helper.setSubject(subject);
            // 第二个参数传true标识内容为HTML格式
            helper.setText(htmlContent, true);
            mailSender.send(message);
            System.out.println("OTP邮件发送完成");
        } catch (MessagingException e) {
            throw new RuntimeException("邮件发送失败", e);
        }
    }
}
  1. 在application.properties中补全正确的邮箱SMTP配置,以Gmail为例:
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=你的Gmail邮箱地址
spring.mail.password=Google账号后台生成的应用专用密码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

内容的提问来源于stack exchange,提问作者Harshit Toxia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:06:24