无法通过公司服务器发送SSL邮件,遇SSL异常寻求技术协助
解决Java邮件发送的SSL异常:Unrecognized SSL message, plaintext connection?
嘿,我来帮你搞定这个邮件发送的SSL问题~这个错误的核心原因很明确:你正在尝试用SSL直接连接一个初始是明文的端口,导致SSL握手时无法识别服务器返回的明文响应,所以抛出了这个异常。
问题出在你的配置冲突
看你的代码,你用了smtps协议(直接SSL连接),但指定的端口是587——而587是标准的STARTTLS端口,这个端口一开始是明文连接,需要先建立普通连接,再通过STARTTLS命令升级为SSL加密。你直接用SSL握手去连它,服务器返回的是明文的SMTP问候,SSL层自然认不出来。
另外你还同时配置了mail.smtps.socketFactory.class,强制使用SSL Socket连接,这就和587端口的工作方式彻底冲突了。
两种修复方案,选适合你的一种
方案一:使用STARTTLS(推荐,符合587端口的标准用法)
把代码改成普通SMTP协议+STARTTLS升级的模式,具体修改点如下:
public static void Send(final String username, final String password, String recipientEmail, String ccEmail, String title, String message) throws AddressException, MessagingException { System.setProperty("java.net.useSystemProxies", "true"); // Java 8及以上无需手动添加SSL Provider,默认已包含,注释掉这行 // Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); Properties props = System.getProperties(); // 切换为smtp协议,启用STARTTLS props.setProperty("mail.smtp.starttls.enable", "true"); props.setProperty("mail.smtp.host", "mail.company.au"); props.setProperty("mail.smtp.user", username); props.setProperty("mail.smtp.password", password); props.setProperty("mail.smtp.port", "587"); props.setProperty("mail.smtp.auth", "true"); // 移除强制SSL Socket的配置,STARTTLS会自动升级连接 props.setProperty("mail.smtp.timeout", "5000"); props.setProperty("mail.smtp.connectiontimeout", "5000"); props.setProperty("mail.smtp.writetimeout", "5000"); Session session = Session.getInstance(props, null); session.setDebug(true); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(username)); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientEmail, false)); // 增加null判断,避免空指针异常 if (ccEmail != null && ccEmail.length() > 0) { msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccEmail, false)); } msg.setSubject(title); msg.setText(message, "utf-8"); msg.setSentDate(new Date()); // 使用smtp协议获取Transport SMTPTransport t = (SMTPTransport) session.getTransport("smtp"); t.connect("mail.company.au", username, password); t.sendMessage(msg, msg.getAllRecipients()); t.close(); }
修改说明:
- 把所有
mail.smtps.*属性改成mail.smtp.*,协议也从smtps切换为smtp - 删除了
mail.smtps.socketFactory.class配置,STARTTLS会自动完成从明文到SSL的升级 - 增加了
ccEmail的null判断,防止空指针异常 - 注释掉了手动添加SSL Provider的代码,Java 8及以上版本默认已经包含该Provider,无需手动添加
方案二:使用直接SSL连接(465端口)
如果你的公司邮件服务器支持465端口的直接SSL连接,可以这样修改:
public static void Send(final String username, final String password, String recipientEmail, String ccEmail, String title, String message) throws AddressException, MessagingException { System.setProperty("java.net.useSystemProxies", "true"); // Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); Properties props = System.getProperties(); // smtps协议默认是直接SSL连接,无需STARTTLS props.setProperty("mail.smtps.host", "mail.company.au"); props.setProperty("mail.smtps.user", username); props.setProperty("mail.smtps.password", password); // 切换为465端口 props.setProperty("mail.smtps.port", "465"); props.setProperty("mail.smtps.auth", "true"); props.setProperty("mail.smtps.timeout", "5000"); props.setProperty("mail.smtps.connectiontimeout", "5000"); props.setProperty("mail.smtps.writetimeout", "5000"); Session session = Session.getInstance(props, null); session.setDebug(true); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(username)); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientEmail, false)); if (ccEmail != null && ccEmail.length() > 0) { msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccEmail, false)); } msg.setSubject(title); msg.setText(message, "utf-8"); msg.setSentDate(new Date()); SMTPTransport t = (SMTPTransport) session.getTransport("smtps"); t.connect("mail.company.au", username, password); t.sendMessage(msg, msg.getAllRecipients()); t.close(); }
修改说明:
- 保留
smtps协议和属性前缀 - 把端口改成465
- 移除了
mail.smtps.starttls.enable和mail.smtps.socketFactory.class配置(smtps协议默认已经使用SSL连接,无需额外配置)
额外验证步骤
可以先用命令行测试一下服务器端口的支持情况:
- 测试587端口:
telnet mail.company.au 587,输入EHLO localhost,看返回内容里有没有STARTTLS字样,有就说明支持STARTTLS - 测试465端口:
openssl s_client -connect mail.company.au:465,如果能建立SSL连接,说明支持直接SSL
内容的提问来源于stack exchange,提问作者user9130545
相关产品推荐
相关产品推荐

