
JavaMail API 发送邮件前必须确认的三件事
不配对 SMTP 服务器和认证方式,代码跑得再顺也发不出去。JavaMail 不是“写完就能发”,它本质是把你的邮件内容打包成标准协议数据,扔给 SMTP 服务器——而这个服务器是否接受你、是否要登录、走不走 TLS,全由你填的配置决定。
-
host和port必须匹配:比如用smtp.gmail.com就不能配25端口(默认被禁),得选587(STARTTLS)或465(SSL) - 大多数现代邮箱(Gmail、Outlook、QQ 邮箱)已禁用“密码登录”,必须用
App Password或 OAuth2,直接填邮箱密码会报AuthenticationFailedException - Java 17+ 默认禁用旧版 SSL/TLS 协议,如果还硬配
mail.smtp.ssl.enable=true+465,可能在某些环境静默失败——优先用mail.smtp.starttls.enable=true+587
send() 报 javax.mail.AuthenticationFailedException 怎么快速定位
这个异常不是 JavaMail 的 bug,而是 SMTP 服务器明确拒绝了你的凭据或连接方式。别急着改代码,先查这三点:
- 确认账号已开启“SMTP 服务”:Gmail 要进 Google 账户安全设置 开“两步验证”,再生成
App Password;QQ 邮箱要进“设置 → 账户 → POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”开启 SMTP 并记下授权码 - 检查
Session创建时是否传入了正确的Authenticator实例,且getPasswordAuthentication()返回的username是完整邮箱(如user@gmail.com),不是昵称或用户名 - 抓包或加日志:在
Properties中设mail.debug=true,运行时看控制台输出的真实 SMTP 对话,重点找535-5.7.8或534-5.7.9这类错误码,它们比 Java 异常更准
用 MimeMessage 设置收件人、主题、HTML 正文的常见错法
看似简单的 setXXX 方法,参数类型和编码稍不注意就会导致乱码或收件人解析失败。
-
setRecipients()接收的是Message.RecipientType枚举 +Address[],别直接传字符串数组;正确写法:message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("a@b.com,c@d.com")) - 中文主题必须用
MimeUtility.encodeText()包一层,否则 Outlook 可能显示问号:message.setSubject(MimeUtility.encodeText("订单通知", "UTF-8", "B")) - 发 HTML 邮件必须设
setContent()的 MIME 类型为"text/html; charset=UTF-8",只设setText()会当纯文本处理,<b></b>标签原样显示
JavaMail 在 Spring Boot 里怎么避免手动 new Session
Spring Boot 自带 JavaMailSender,封装了 Session 创建和连接池,不用自己 new Properties 和 Authenticator。但配置项名和原生 JavaMail 不同,容易填错 key。
立即学习“Java免费学习笔记(深入)”;
-
spring.mail.host对应原生的mail.smtp.host,但spring.mail.properties.mail.smtp.auth才对应原生的mail.smtp.auth - 密码字段必须用
spring.mail.password,而不是spring.mail.properties.mail.smtp.password(后者无效) - 如果用 QQ 邮箱,
spring.mail.port=587+spring.mail.properties.mail.smtp.starttls.enable=true是最稳组合;设成465且没关掉starttls,可能握手失败
复杂点在于不同邮箱对 STARTTLS 和 SSL 的容忍度差异很大,同一套配置在 Gmail 成功,换到企业 Exchange 就可能卡在 HELO 阶段——别迷信“通用配置”,每次换服务商都得按它的 SMTP 文档重验一遍端口和加密方式。










