代码触发STARTTLS错误,已导入相关Jar包仍未解决,求排查方案
解决STARTTLS要求但主机不支持的邮件发送问题
看你遇到的javax.mail.MessagingException: STARTTLS is required but host does not support STARTTLS错误,结合你的代码配置,问题核心出在端口选择和STARTTLS配置的冲突上,咱们一步步调整就能解决:
问题根源分析
你当前的配置同时做了两件矛盾的事:
- 配置了
mail.smtp.socketFactory.class用SSL直接连接,还指定了465端口(这是SMTP over SSL的标准端口,连接建立时就已经是加密状态,不需要再通过STARTTLS升级连接) - 又强制开启了
mail.smtp.starttls.enable=true和mail.smtp.starttls.required=true,要求必须使用STARTTLS,但你的邮件服务器在465端口上根本不支持这个流程(因为没必要),所以触发了冲突报错
两种可行解决方案
方案一:用SMTP over SSL(465端口),关闭STARTTLS强制要求
如果你的邮件服务器支持465端口的SSL连接,直接调整配置,去掉STARTTLS相关的强制规则:
boolean sessionDebug=false; Properties props=System.getProperties(); // 保留SSL Socket Factory配置,适配465端口的加密连接 props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.host", host); props.put("mail.smtp.port", "465"); props.put("mail.smtp.auth", "true"); // 去掉STARTTLS相关配置,因为465端口不需要 // props.put("mail.smtp.starttls.enable", "true"); // props.put("mail.smtp.starttls.required", "true"); final javax.mail.Session mailSession = javax.mail.Session.getInstance(props); java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); props.put("mail.smtp.debug", "true"); mailSession.setDebug(sessionDebug); Message msg = new MimeMessage(mailSession); msg.setFrom(new InternetAddress(from)); InternetAddress[] address={new InternetAddress(to)}; msg.setRecipients(Message.RecipientType.TO,address); msg.setSubject(subject); msg.setSentDate(new Date()); msg.setText(msgText); Transport transport =mailSession.getTransport("smtp"); System.out.println("smtp"); transport.connect(host,user,pass); System.out.println("smtp connection"); transport.sendMessage(msg,msg.getAllRecipients()); System.out.println("smtp message"); transport.close();
方案二:用STARTTLS(587端口),去掉SSL Socket Factory配置
如果你的邮件服务器支持587端口的STARTTLS流程,就切换到这个标准端口,适配STARTTLS的配置逻辑:
boolean sessionDebug=false; Properties props=System.getProperties(); // 去掉SSL Socket Factory,因为STARTTLS是先建立明文连接再升级为加密状态 // props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.host", host); // 改用STARTTLS的标准端口587 props.put("mail.smtp.port", "587"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.required", "true"); final javax.mail.Session mailSession = javax.mail.Session.getInstance(props); java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); props.put("mail.smtp.debug", "true"); mailSession.setDebug(sessionDebug); Message msg = new MimeMessage(mailSession); msg.setFrom(new InternetAddress(from)); InternetAddress[] address={new InternetAddress(to)}; msg.setRecipients(Message.RecipientType.TO,address); msg.setSubject(subject); msg.setSentDate(new Date()); msg.setText(msgText); Transport transport =mailSession.getTransport("smtp"); System.out.println("smtp"); transport.connect(host,user,pass); System.out.println("smtp connection"); transport.sendMessage(msg,msg.getAllRecipients()); System.out.println("smtp message"); transport.close();
额外排查建议
- 先确认你的邮件服务器支持哪种加密方式:可以用
openssl s_client -connect 你的主机:465测试465端口的SSL连接;或者用telnet 你的主机:587后输入EHLO localhost,看返回内容里有没有STARTTLS字样,以此判断是否支持该流程 - 开启
mail.smtp.debug=true,能看到详细的邮件服务器交互日志,方便进一步定位问题
内容的提问来源于stack exchange,提问作者Hanin Qaddoura
相关产品推荐
相关产品推荐

