Spring Boot starter-mail发送邮件时接口无限挂起无响应问题
问题根因
- 超时配置未生效:你在Controller中手动实例化
JavaMailSenderImpl时,仅注入了host、port、账号、密码四个基础参数,application.properties中配置的三类超时参数、SMTP认证、加密传输等配置完全没有被加载到新建的邮件发送实例中。一旦SMTP握手、指令交互阶段出现网络异常,程序没有超时中断机制,就会无限阻塞。 - 参数校验逻辑失效:
BindingResult仅能捕获紧邻的、被@Valid注解标记的参数的校验错误,你的代码中既没有给ConfirmationEmail参数加@Valid注解触发校验,参数校验规则本身就不会运行。 - 发件人地址不符合SMTP服务规则:你使用的Mailtrap是测试类邮件服务,要求发件人地址必须是当前账号下已完成验证的地址,你直接将请求传入的第三方gmail地址设为发件人,会被SMTP服务直接拒绝连接,部分场景下会导致请求挂起。
- 重复造轮子导致配置遗漏:引入
spring-boot-starter-mail后,Spring Boot会自动读取spring.mail.*前缀的所有配置,构建好可用的JavaMailSenderBean,你自定义EmailConfig类、手动new发送实例的写法,完全绕开了框架的自动配置逻辑,漏掉了大量必要的底层参数。
修复步骤
- 删除自定义的
EmailConfig类,不需要自己读取邮件配置,直接注入Spring自动生成的JavaMailSender实例即可。 - 修正Controller层代码:给请求体参数加
@Valid注解,保证BindingResult紧跟在被校验参数之后,不要手动创建JavaMailSenderImpl实例,修正发件人地址为Mailtrap账号下已验证的邮箱。 - 补全SMTP必要配置,开启认证和传输加密,保证超时规则正常加载。
- 本地验证SMTP端口连通性,排除网络层拦截问题。
修正后代码
EmailController.java
@RestController @RequestMapping(path = "api/v1/email") public class EmailController { private final JavaMailSender javaMailSender; // 直接注入Spring自动配置好的邮件发送实例 public EmailController(JavaMailSender javaMailSender) { this.javaMailSender = javaMailSender; } @PostMapping public ResponseEntity<String> sendEmail(@Valid @RequestBody ConfirmationEmail confirmationEmail, BindingResult bindingResult) throws ValidationException { if (bindingResult.hasErrors()) { throw new ValidationException("请求参数不合法"); } SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); // 此处替换为你在Mailtrap后台验证过的发件人邮箱,不要使用请求传入的外部地址 simpleMailMessage.setFrom("your-authorized-sender@example.com"); simpleMailMessage.setTo("mail@gmail.com"); simpleMailMessage.setSubject("Test Subject from " + confirmationEmail.getSenderName()); simpleMailMessage.setText(confirmationEmail.getConfirmationBody()); javaMailSender.send(simpleMailMessage); return ResponseEntity.ok("邮件发送成功"); } }
application.properties
spring.mail.host=smtp.mailtrap.io spring.mail.port=2525 spring.mail.username=替换为你的Mailtrap账号SMTP用户名 spring.mail.password=替换为你的Mailtrap账号SMTP密码 # 开启SMTP认证 spring.mail.properties.mail.smtp.auth=true # 开启TLS加密传输 spring.mail.properties.mail.smtp.starttls.enable=true # 超时配置,Spring自动配置会自动加载以下参数 spring.mail.properties.mail.smtp.connectiontimeout=5000 spring.mail.properties.mail.smtp.timeout=3000 spring.mail.properties.mail.smtp.writetimeout=5000
ConfirmationEmail.java
原有代码逻辑不需要调整,保留现有getter、setter和校验注解即可。
额外排查项
如果完成以上修改后请求仍然阻塞,先在部署服务的机器上执行telnet smtp.mailtrap.io 2525测试端口连通性:
- 如果连接失败,说明本地网络或防火墙拦截了对应SMTP端口,可以换成Mailtrap提供的587、465等其他SMTP端口重试。
- 如果连接正常,检查填写的SMTP用户名、密码是否和Mailtrap后台提供的测试账号一致,账号信息错误也可能导致握手阶段挂起。
内容的提问来源于stack exchange,提问作者Radwan Afiouni
相关产品推荐
相关产品推荐

