Java应用用Authenticator发邮件仍报未授权发匿名邮件异常原因
嘿,这个问题我之前帮同事排查过好几次,大概率是你的Authenticator配置没真正生效,或者没满足邮件服务器的硬性要求,咱们一步步拆解原因和解决办法:
Authenticator没和Session正确绑定
很多人会犯的低级错误:创建了Authenticator实例,但调用Session.getInstance()的时候没把它传进去!这样Session根本不知道要用这个认证器,自然会以匿名身份发送邮件。错误示例:
Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", "smtp.example.com"); // 这里只传了props,没传Authenticator Session session = Session.getInstance(props);正确示例:
Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", "smtp.example.com"); // 实现自定义认证器 Authenticator auth = new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("your-email@domain.com", "your-auth-code"); } }; // 必须把auth作为第二个参数传给Session Session session = Session.getInstance(props, auth);未开启SSL/TLS加密连接
现在几乎所有主流邮件服务商(Gmail、Outlook、QQ邮箱等)都强制要求加密连接,如果你的Session没配置加密,即使传了Authenticator,服务器也会拒绝你的认证请求,直接判定为匿名邮件。针对TLS(端口通常是587)的配置:
props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.port", "587");针对SSL(端口通常是465)的配置:
props.put("mail.smtp.ssl.enable", "true"); props.put("mail.smtp.port", "465");用了登录密码而非应用授权码
现在很多邮箱(比如QQ邮箱、Gmail)已经禁止直接使用账号登录密码进行SMTP认证,必须生成应用授权码。如果你还在填普通登录密码,服务器会直接拒绝认证,表现出来就是“未认证”的错误。解决办法:去邮箱的设置页面开启POP3/SMTP服务,然后生成对应的应用授权码,用这个授权码替换
PasswordAuthentication里的密码参数。忘记开启SMTP认证开关
别笑,真的有人会漏!必须确保mail.smtp.auth属性被设置为字符串"true"(注意是字符串,不是布尔值true,因为Properties存储的是键值对字符串):props.put("mail.smtp.auth", "true");如果这个属性没开,Authenticator根本不会被Session调用,等于白写。
邮箱账号的安全限制
有些服务商(比如Gmail)会对陌生设备/IP的登录进行拦截,即使你用了正确的授权码,也可能需要去账号后台手动允许这次登录,或者开启对应权限(Gmail现在更推荐使用App Password)。可以去邮箱的安全日志里看看有没有相关的拦截记录。
总结一下:先检查Session和Authenticator的绑定是否正确,再确认加密配置和mail.smtp.auth开关,最后核对授权码是否正确以及账号的安全设置,基本就能解决问题了。
内容的提问来源于stack exchange,提问作者eeadev

