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

文章讲述了在将JRE和JDK升级到1.8版本后,遇到javax.mail发送邮件时的SSL/TLS连接问题。通过调整JavaMail配置,指定TLS协议版本(如TLSv1.2),解决了服务器连接问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前一直采用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之类的。

`Authentication failed; nested exception is javax.mail.AuthenticationFailedException` 这个错误通常是由于身份验证失败引起的。可能的原因包括用户名或密码错误,SMTP服务器未开启身份验证,或者安全性设置太高。以下是一些可能的解决方法: 1.检查用户名和密码是否正确,确保它们与您的邮件提供商提供的相同。 2.检查SMTP服务器设置,确保已启用身份验证。如果没有提供身份验证方法,请将 `mail.smtp.auth` 设为 `false`。 3.检查安全设置,确保您的电子邮件客户端已正确配置。如果您使用的是 Gmail,请确保启用了“允许较低安全性应用程序访问您的帐户”选项。 4.如果您使用的是 Outlook.com,请确保已启用“使用与我的传入邮件服务器相同的设置”选项。 以下是一个可能的解决方案: ```java Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.port", "587"); Session session = Session.getInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("yourusername@gmail.com", "yourpassword"); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress("from@example.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@example.com")); message.setSubject("Testing Subject"); message.setText("Dear Mail Crawler," + "\n\n No spam to my email, please!"); Transport.send(message); System.out.println("Done"); } catch (MessagingException e) { throw new RuntimeException(e); } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值