Java1.7遗留Web应用Office365 SMTP邮件发送SSL握手异常求助
错误信息
javax.mail.MessagingException: Can't send command to SMTP host;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:1420)
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:1408)
at com.sun.mail.smtp.SMTPTransport.ehlo(SMTPTransport.java:847)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:384)
at javax.mail.Service.connect(Service.java:297)
环境与核心代码
我们有一个基于Java 1.7、mail1.4.jar构建并部署在Tomcat 7上的遗留Web应用,向Office365的SMTP发送带附件邮件时触发上述错误。配置从属性文件读取,核心代码片段如下:
final String username = ConfReader.getPropertyValue("mail.username"); final String passwd = ConfReader.getPropertyValue("mail.password"); from = ConfReader.getPropertyValue("mail.from"); String port = ConfReader.getPropertyValue("mail.port"); Properties props = new Properties(); props.put("mail.smtp.host", ConfReader.getPropertyValue("mail.smtp.host")); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", port); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.debug", "true"); Session session = Session.getInstance(props, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { LogWriter.logErrorMessage("username :: " + username + "passwd :: "+passwd); return new PasswordAuthentication(username, passwd); } }); Message message = new MimeMessage(session); try { message.setFrom(new InternetAddress(from)); final InternetAddress[] toAddress = InternetAddress.parse(toEmails); final InternetAddress[] ccAddress = InternetAddress.parse(ccEmails); message.setRecipients(Message.RecipientType.TO, toAddress); message.setRecipients(Message.RecipientType.CC, ccAddress); message.setSubject(subject); /* * Multipart to create the mail content. */ final Multipart multipart = new MimeMultipart(); /* * html body part to set in multipart */ final MimeBodyPart htmlBodyPart = new MimeBodyPart(); htmlBodyPart.setContent(htmlBody, "text/html"); multipart.addBodyPart(htmlBodyPart); /* * source to read attachment content */ DataSource source = new ByteArrayDataSource(bytes, "application/excel"); /* * MimeBodyPart to hold the attachment content. */ MimeBodyPart attachmentBodyPart = new MimeBodyPart(); DataHandler handler = new DataHandler(source); attachmentBodyPart.setHeader("Content-Disposition", "attachment;filename=" + attachmentName); attachmentBodyPart.setDataHandler(handler); attachmentBodyPart.setFileName(attachmentName); multipart.addBodyPart(attachmentBodyPart); message.setContent(multipart); /* * following line to send email, if it fails, corresponding catch * block executes, which is logged to let know user if any error */ Transport.send(message); } catch (AddressException e) { /* * email sending failed, logging the information */ LogWriter .logErrorMessage("Address Exception : " + e.getMessage()); } catch (MessagingException e) { /* * email sending failed, logging the information */ LogWriter.logErrorMessage("Messaging Exception : " + e.getMessage()); }
已尝试的方案
- 更新mail.jar至1.4.7版本
- 代码中添加
mail.smtp.starttls.enable=true和mail.debug=true属性 - 删除部署服务器JRE的
java.security文件中jdk.tls.disabledAlgorithms配置项 - 切换SMTP端口至25并保持
mail.smtp.starttls.enable=true - 代码中添加
mail.smtp.ssl.protocols=TLSv1.2和mail.smtps.ssl.protocols=TLSv1.2属性
可行解决方案
1. 强制JVM启用TLSv1.2协议
Java 1.7默认不优先启用TLSv1.2,可通过JVM启动参数强制指定:
-Dhttps.protocols=TLSv1.2 -Djdk.tls.client.protocols=TLSv1.2
在Tomcat的catalina.sh(Linux)或catalina.bat(Windows)中添加上述参数,确保JVM在SSL握手时只使用TLSv1.2。
2. 升级JavaMail至兼容版本
建议直接升级到JavaMail 1.5.6及以上版本,这些版本对TLSv1.2的支持更完善,修复了老版本中的协议协商问题。替换时需移除旧的mail.jar,避免依赖冲突。
3. 解除JRE加密强度限制
Java 1.7默认存在加密强度限制,无法使用Office365要求的强加密套件。需下载对应JRE版本的无限强度策略文件,替换JRE/lib/security目录下的local_policy.jar和US_export_policy.jar。
4. 补充SMTP连接属性
在现有Properties配置中添加以下属性,明确指定SSL套接字工厂和协议:
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); props.put("mail.smtp.ssl.enable", "true");
同时确认mail.smtp.host配置为正确的Office365地址:smtp.office365.com。
5. 验证服务器网络连通性
确保部署Tomcat的服务器能访问Office365的SMTP端口(587或25),可通过命令测试:
telnet smtp.office365.com 587
若网络不通,需检查防火墙或安全组规则,放行对应端口的出站流量。
内容的提问来源于stack exchange,提问作者Nageswara Rao P

