解决javax.mail.MessagingException: Could not convert socket to TLS;

之前一直采用jre-1.8和jdk-1.8,基本还顺利。今年升级了服务器硬件,顺便就升级了jre和jdk到版本17,然后就出现了一些问题。其中最棘手的就是这个javax.mail报的错:

Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at util.EmailEncrypt.sendMessageToMe(EmailEncrypt.java:60)
	at util.EmailEncrypt.main(EmailEncrypt.java:17)
Caused by: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
	at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
	at javax.mail.Service.connect(Service.java:317)
	at javax.mail.Service.connect(Service.java:176)
	at javax.mail.Service.connect(Service.java:125)
	at javax.mail.Transport.send0(Transport.java:194)
	at javax.mail.Transport.send(Transport.java:124)
	at util.EmailEncrypt.sendMessageToMe(EmailEncrypt.java:56)
	... 1 more
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:172)
	at java.base/sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:103)
	at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:240)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:448)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
	at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
	at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
	at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
	... 8 more

原代码如下:

    public static void main(String[] args) {
    	EmailEncrypt.sendMessageToMe("toMe", "toMeOnly");    	
    }
    
	public static void sendMessageToMe(String subject, String body) {
		
//    	服务器名称: smtp.office365.com
//    	端口: 587
//    	加密方法: STARTTLS
    	
        final String username = "*****";
        final String password = "*****";

        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "smtp.office365.com");
        props.put("mail.smtp.port", "587");

        Session session = Session.getInstance(props,
          new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
          });

        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("*****"));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("*****"));
            message.setSubject(subject);
            message.setText(body);

            Transport.send(message);
            System.out.println("Done");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }

试过一些方法:

一、在代码中增加props.put("mail.smtp.ssl.trust", "smtp-mail.outlook.com"),没成功。

二、去/jdk-17.jdk/Contents/Home/lib/security调整文件,没找到对应的表述。

三、问过C知道,建议我:“禁用TLS,在代码中设置mail.smtp.starttls.enable为false。”这就是扯淡,毕竟outlook要求采用STARTTLS,我如果不设置,怎么可能连得上服务器呢?

四、问了星火,其中有一条:“检查您的JavaMail代码是否正确设置了TLS选项。确保您已正确指定了TLS端口和协议版本。例如,对于Gmail,TLS端口是587,协议版本是STARTTLS。”好像是有点意思,但我开始没有理解。

最后,直接去了bing国际,看到一位外国友人给出以下方法:

props.put("mail.smtp.ssl.protocols", "TLSv1.2");

成功。

再看星火给的答案是相对靠谱的,Java-17需要显式指定TLS的协议版本,才可以正确运行。

有兴趣的同学,可以再试一下TLSv1.1、TLSv1.3之类的。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值