阿里云服务器发送邮件失败 Could not connect to SMTP host: smtp.xxx.com, port: 465;

news2024/11/15 11:26:03

最近做了一个发送邮件的功能, 在本地调试完成后,部署到阿里云服务器就一直报错,
Could not connect to SMTP host: smtp.qiye.aliyun.com, port: 465; 网上也搜索了很多的资料,最后花了好几个小时才解决, 报错日志如下

Send mail failed. Error message : Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: smtp.qiye.aliyun.com, port: 465;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: smtp.qiye.aliyun.com, port: 465;
  nested exception is:
	javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

总结下来,可能的原因如下,我这里遇到的就属于第四种情况

  1. 网络或者端口不通
  2. 邮箱发件服务器地址+端口不正确
  3. jdk版本不支持
  4. 发送邮件代码侧问题

排查定位步骤如下

一、 网络或者端口不通
从提示看就是阿里云邮箱的465端口连接不上,一开始以为是阿里云禁止了465端口,所以在阿里云控制台的安全组里面给465端口都配置了入方向和出方向,但仍旧同样报错。 通过shell命令检查网络和端口,都是ok的。(有人说阿里云服务器默认是开了465的,其实无需特意在安全组规则里面配置465)

在这里插入图片描述
针对465端口检测,显然也是ok的

#不指定TLS版本
openssl s_client -connect smtp.qiye.aliyun.com:465
#指定TLS版本
openssl s_client -connect smtp.qiye.aliyun.com:465 -tls1_2

在这里插入图片描述

二、邮箱发件服务器地址+端口不正确
关于端口方面,早期的邮件端口是25,但目前大多服务商因为垃圾邮件的原因禁止了25端口(所以我这边一开始就用的是465)。阿里云服务器也不例外,但可以在阿里云控制台申请解封25端口,然而是小微服务器一般不给解封的,所以即使本地25端口也调试ok,也不考虑换25端口作为解决方向。

阿里云的stmp地址除了smtp.qiye.aliyun.com外,还有以下两个

smtp.mxhichina.com +465
smtphk.qiye.aliyun.com +80/465

但是经过部署阿里云服务器测试,报错是同样的。于是怀疑是阿里云企业邮箱有啥问题或者阿里云的企业邮箱哪里设置的不对头,所以另外申请了腾讯企业邮箱 smtp.exmail.qq.com+465/587端口进行部署阿里云测试,问题依旧。这波操作下来, 本地ok上阿里云行不通,还是环境的问题需要继续排查。

三、jdk版本不支持
网上有说法,高版本的jdk的http安全限制导致发不去邮件。我这里阿里云服务器jdk版本是1.8.0_372, 本地是 1.8.0_91,都是1.8的jdk,小版本不同应该问题不大,但也进行了尝试。关于jdk主要是两个方面,java.security文件的配置和替换jre目录下的jar包
3.1更改 java.security配置
java.security文件位于jdk安装目录的/jdk1.8.0_372/jre/lib目录下面,服务器上忘记或者不知道jdk的安装路径的,可以参考如下

which java
ls -lrt /usr/bin/java  #其中 /usr/bin/java是第一步的输出结果
ls -lrt /etc/alternatives/java    #其中 /etc/alternatives/java是第二步输出的结果
# 如下图,可知安装目录是 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.372.b07-4.0.2.al8.x86_64

在这里插入图片描述
编辑 java.security文件,搜索关键词jdk.tls.disabledAlgorithms=找到如下位置
在这里插入图片描述

注释原来的3行或者删除其中的 SSLv3、TLSv1、TLSv1.1协议(即不禁用这三个加密协议),并保存。效果如下
在这里插入图片描述

3.2 用低版本jdk的jar替换高版本jdk的jre目录下的jar包
需要替换的jar文件分别是 local_policy.jarUS_export_policy.jar。可以从网上下载低版本的jar或者用本地jdk相同目录下的jar(因为本地能发送成功)去服务器上进行覆盖。这两个jar包的路径位于jdk安装目录下

/jdk1.8.0_372/jre/lib
或者
/jdk1.8.0_372/jre/lib/jre/lib/security/policy/limited
/jdk1.8.0_372/jre/lib/jre/lib/security/policy/unlimited

jdk1.7版本替换包网上下载地址: 点击下载,下载后解压后覆盖到上面的路径下

以上两个步骤操作后,通过阿里云控制台重启了实例和重启应用服务器,报错却依旧。

四、 发送邮件代码侧问题
先看发送邮件核心代码

Properties properties = new Properties();
properties.put("mail.smtp.auth", true);
properties.put("mail.smtp.connectiontimeout", String.valueOf(3 * 1000));
properties.put("mail.smtp.timeout", String.valueOf(3 * 1000));
//启用SSL与指定465端口
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.socketFactory.port", "465");
properties.put("mail.smtp.port", "465"); 
// SSL来建立连接,失败则回退兼容。如果出于某种原因无法使用SSL来建立连接(比如服务器不支持),则不会回退到非加密的连接方式,而是让连接尝试失败。
properties.put("mail.smtp.ssl.socketFactory", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.socketFactory.fallback", "false");

这段代码本地ok,上阿里云服务器就连不通stmp+465,故而又从网上找了几个别人写的发送邮件的工具类代码,都是大同小异,结果也是本地ok阿里云服务器不行,着实让人有点蒙圈。后来添加下面这行指定了ssl的加密协议才解决问题

// 握手阶段加密算法不匹配,jre高版本把加密算法禁止了 SSLv3, TLSv1, TLSv1.1等,尝试指定jdk版本或删除相关禁用配置项
 props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2"); 

下面附录一个发送邮件的工具类,以供参考和测试

package com.yulisao.utils.email;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.Security;
import java.util.Date;
import java.util.Properties;

public class EmailUtils{
	// 此方法调试ok后自行整理成工具类应用到项目中
    public static void sendmail() {
        try{
            //设置SSL连接、邮件环境
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            Properties props = System.getProperties();
            //协议
            //props.setProperty("mail.transport.protocol", "smtp");

            props.setProperty("mail.smtp.host", "smtp.qiye.aliyun.com");//smtp服务器地址
            //props.setProperty("mail.smtp.port", "25");//非加密端口
            // 使用ssl加密方式,进行如下配置:
            props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            props.setProperty("mail.smtp.socketFactory.fallback", "false");
            props.setProperty("mail.smtp.socketFactory.port", "465");

            // 不指定则是25端口了!注意阿里云禁用此端口
            props.setProperty("mail.smtp.port", "465");
            props.setProperty("mail.smtp.ssl.enable", "true");
            props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

            props.setProperty("mail.smtp.auth", "true");//表示SMTP发送邮件,需要进行身份验证
            props.setProperty("mail.smtp.from", "你的发件邮箱");//mailfrom 参数
            props.setProperty("mail.user","你的发件邮箱");//发件人的账号
            props.setProperty("mail.password","你的发件邮箱的授权码");// 发件人的账号的密码,如果开启三方客户端安全密码请使用新生产的密码
            System.setProperty("mail.mime.splitlongparameters", "false"); //用于解决附件名过长导致的显示异常
            
            //建立邮件会话
            Session session = Session.getDefaultInstance(props, new Authenticator() {
                //身份认证
                protected PasswordAuthentication getPasswordAuthentication() {
                    //发件人的账号、密码
                    String userName = props.getProperty("mail.user");
                    String password = props.getProperty("mail.password");
                    return new PasswordAuthentication(userName, password);
                }
            });
            //建立邮件对象
            MimeMessage message = new MimeMessage(session);
            //设置邮件的发件人
            InternetAddress from = new InternetAddress("你的发件邮箱","你的邮件主题"); //from 参数,可实现代发,注意:代发容易被收信方拒信或进入垃圾箱。
            message.setFrom(from);
            //设置邮件的收件人
            String[] to = {"abc@163.com","123456789@qq.com"};//收件人列表
            InternetAddress[] sendTo = new InternetAddress[to.length];
            for (int i=0;i<to.length;i++){
                System.out.println("正在执行发送到:" + to[i]);
                sendTo[i] = new InternetAddress(to[i]);
            }

            //传入收件人
            message.setRecipients(Message.RecipientType.TO,sendTo);
            //设置邮件的主题
            message.setSubject("邮件主题");
            //设置邮件的文本
            String content="邮件内容";
            message.setContent(content,"text/html;charset=UTF-8");
            //设置时间
            message.setSentDate(new Date());
            message.saveChanges();
            //发送邮件
            Transport.send(message);
            System.out.println("发送成功!");
        }catch(Exception e){
            System.out.println("发送邮件异常:"+e.toString());
        }
    }

	// 自测main方法
    public static void main(String[] args) {
        try{
            //设置SSL连接、邮件环境
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            Properties props = System.getProperties();
            //协议
            //props.setProperty("mail.transport.protocol", "smtp");

            props.setProperty("mail.smtp.host", "smtp.qiye.aliyun.com");//smtp服务器地址
            //props.setProperty("mail.smtp.port", "25");//非加密端口
            // 使用ssl加密方式,进行如下配置:
            props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            props.setProperty("mail.smtp.socketFactory.fallback", "false");
            props.setProperty("mail.smtp.socketFactory.port", "465");
            props.setProperty("mail.smtp.ssl.enable", "true");
            props.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

            props.setProperty("mail.smtp.auth", "true");//表示SMTP发送邮件,需要进行身份验证
            props.setProperty("mail.smtp.from", "你的发件邮箱");//mailfrom 参数
            props.setProperty("mail.user","你的发件邮箱");//发件人的账号
            props.setProperty("mail.password","你的发件邮箱的授权码");// 发件人的账号的密码,如果开启三方客户端安全密码请使用新生产的密码
			System.setProperty("mail.mime.splitlongparameters", "false"); // 用于解决附件名过长导致的显示异常
			
            //建立邮件会话
            Session session = Session.getDefaultInstance(props, new Authenticator() {
                //身份认证
                protected PasswordAuthentication getPasswordAuthentication() {
                    //发件人的账号、密码
                    String userName = props.getProperty("mail.user");
                    String password = props.getProperty("mail.password");
                    return new PasswordAuthentication(userName, password);
                }
            });
            //建立邮件对象
            MimeMessage message = new MimeMessage(session);
            //设置邮件的发件人
            InternetAddress from = new InternetAddress("你的发件邮箱","你的邮件主题"); //from 参数,可实现代发,注意:代发容易被收信方拒信或进入垃圾箱。
            message.setFrom(from);
            //设置邮件的收件人
            String[] to = {"abc@163.com","123456789@qq.com"};//收件人列表
            InternetAddress[] sendTo = new InternetAddress[to.length];
            for (int i=0;i<to.length;i++){
                System.out.println("正在执行发送到:" + to[i]);
                sendTo[i] = new InternetAddress(to[i]);
            }

            //传入收件人
            message.setRecipients(Message.RecipientType.TO,sendTo);
            //设置邮件的主题
            message.setSubject("邮件主题");
            //设置邮件的文本
            String content="邮件内容";
            message.setContent(content,"text/html;charset=UTF-8");
            //设置时间
            message.setSentDate(new Date());
            message.saveChanges();
            //发送邮件
            Transport.send(message);
            System.out.println("发送成功!");
        }catch(Exception e){
            System.out.println("发送邮件异常:"+e.toString());
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1800685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全新抖音快手小红书视频解析去水印系统网站源码

这个系统支持几十种平台&#xff0c;包括抖音、快手小红书以及其他热门社交媒体平台。它可以帮助轻松地下载这些平台上的任何视频&#xff0c;并去除其中的水印&#xff0c;让你可以自由地保存和分享这些视频。 使用方法&#xff1a; 上传压缩包解压&#xff0c;网站信息在inc…

数据脱敏技术方案选择(word)

1 概述 1.1 数据脱敏定义 1.2 数据脱敏原则 1.2.1基本原则 1.2.2技术原则 1.2.3管理原则 1.3 数据脱敏常用方法 3.1.1泛化技术 3.1.2抑制技术 3.1.3扰乱技术 3.1.4有损技术 1.4 数据脱敏全生命周期 2 制定数据脱敏规程 3 发现敏感数据 4 定义脱敏规则 5 执…

读取文件

自学python如何成为大佬(目录):自学python如何成为大佬(目录)_利用python语言智能手机的默认语言实战一-CSDN博客 在Python中打开文件后&#xff0c;除了可以向其写入或追加内容&#xff0c;还可以读取文件中的内容。读取文件内容主要分为以下几种情况&#xff1a; 1 读取指…

python爬虫入门教程(二):requests库的高级用法

requests库除了基本的GET和POST请求外&#xff0c;requests库还提供了许多高级功能&#xff0c;本文将介绍其中一些常用的用法。包括&#xff1a; 会话保持&#xff08;Session&#xff09;SSL证书验证文件上传代理设置自定义HTTP适配器超时设置 请求参数 文章最开始&#x…

github将默认分支main改为master

github将默认分支main改为master 1.进入github&#xff0c;点击setting 2.在setting中&#xff0c;选择Respositories&#xff0c;更新默认分支为master 3.选择要更新的项目&#xff0c;在项目中选择setting->general->切换默认分支

Elastic Search(ES)Java 入门实操(3)数据同步

基本概念和数据查询代码&#xff1a; Elastic Search &#xff08;ES&#xff09;Java 入门实操&#xff08;1&#xff09;下载安装、概念-CSDN博客 Elastic Search&#xff08;ES&#xff09;Java 入门实操&#xff08;2&#xff09;搜索代码-CSDN博客 想要使用 ES 来查询数…

MAVEN:自定义模板Archetype的创建

目录 一、简介 二、具体步骤 三、 vscode通过模板创建项目 四、通过IDEA创建 一、简介 有时候MAVEN自带的模板库并不能满足我们创建项目的需求&#xff0c;为了能够快速创建项目&#xff0c;免去每次复杂的配置&#xff0c;所以我们需要自定义模板库&#xff0c;本次操作基于…

控制台输入javac命令输出的结果中的中文乱码解决方式

默认字符编码UTF-8无法解析中文。设置环境变量中 “JAVA_TOOL_OPTIONS” 的值为"UTF-8" 即可。 具体配置步骤&#xff1a; 桌面右键"我的电脑" --> 属性 高级系统设置 环境变量 用户变量中添加 JAVA_TOOL_OPTIONS 然后确定&#xff0c;保存即可。

Windows 更新根文件夹的修改时间

简介&#xff1a; Win10 系统不会根据深层目录文件更新主目录的修改时间. 一般解决办法是关闭 Winodws 搜索引擎。 win10文件夹不能自动更新了怎么办&#xff1f;_百度知道 本脚本通过递归遍历子目录和子文件&#xff0c;来更新根目录的时间。 使用内层目录和当前目录下的最新…

(杂交版)植物大战僵尸

1.为什么我老是闪退&#xff1f; 答&#xff1a;主页控制台把“后台运行”点开&#xff0c;尽量避免全屏就会好很多。 2.哪里下载&#xff1f; 答&#xff1a;夸克https://pan.quark.cn/s/973efb326f81 3.为啥我没有14个卡槽&#xff1f; 答&#xff1a;冒险没打&#xff0c;怪…

课时149:项目发布_基础知识_项目交付

1.1.1 项目交付 学习目标 这一节&#xff0c;我们从 基础知识、代码发布、小结 三个方面来学习 基础知识 简介 项目交付是一个涉及到多团队共同协作的事情&#xff0c;它包括 产品团队设计产品、研发团队开发产品、测试团队测试代码、运维团队发布代码和维护站点等工作。项…

运维 之 DNS域名解析

前言 我们每天打开的网站&#xff0c;他是如何来解析&#xff0c;并且我们怎么能得到网站的内容反馈的界面呢&#xff1f;那什么是DNS呢&#xff08;DNS&#xff08;DomainNameservice&#xff0c;域名服务&#xff0c;主要用于因特网上作为域名和IP地址相互映射&#xff09;那…

【Python】读取文件夹中所有excel文件拼接成一个excel表格 的方法

我们平常会遇到下载了一些Excel文件放在一个文件夹下&#xff0c;而这些Excel文件的格式都一样&#xff0c;这时候需要批量这些文件合并成一个excel 文件里。 在Python中&#xff0c;我们可以使用pandas库来读取文件夹中的所有Excel文件&#xff0c;并将它们拼接成一个Excel表…

【UE5 刺客信条动态地面复刻】实现无界地面01:动态生成

2024.6.4更新 昨天半夜意识到生成Cube的方案不合适&#xff0c;又开始到处找动态地面的方法&#xff0c;发现了我想要的效果直接可以用nigara实现&#xff01;&#xff01;&#xff01;&#xff01; 于是这个部分就暂时告一段落&#xff0c;今季开始新的方向的学习。 为了快速…

Flink⼤状态作业调优实践指南:状态报错与启停慢篇

摘要&#xff1a;本文整理自俞航翔、陈婧敏、黄鹏程老师所撰写的大状态作业调优实践指南。由于内容丰富&#xff0c;本文分享终篇状态报错与启停慢篇&#xff0c;主要分为以下四个部分&#xff1a; 检查点和快照超时的诊断与调优 作业快速启动和扩缩容方案 总结 阿里云企业级…

1.vue2.x-初识及环境搭建

目录 1.下载nodejs v16.x 2.设置淘宝镜像源 3.安装脚手架 4.创建一个项目 5.项目修改 代码地址&#xff1a;source-code: 源码笔记 1.下载nodejs v16.x 下载地址&#xff1a;Node.js — Download Node.js 2.设置淘宝镜像源 npm config set registry https://registry.…

如何删除电脑端口映射?

在使用电脑进行网络连接时&#xff0c;有时需要进行端口映射以实现不同设备之间的信息远程通信。当这些端口映射不再需要时&#xff0c;我们需要及时删除它们以确保网络的安全和稳定。本文将介绍如何删除电脑端口映射的方法。 操作系统自带的工具 大多数操作系统都提供了自带…

【docker】centos7配置docker镜像阿里云加速

国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;由于网络原因&#xff0c;下载一个Docker官方镜像可能会需要很长的时间&#xff0c;甚至下载失败。此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务。 测试了几次阿里云的加速是最快的。 …

OpenCV学习(4.6) 图像梯度

1.目标 在本教程中&#xff1a; 你会学到如何找到图像的梯度&#xff0c;边缘等。你会学到如下函数&#xff1a;**cv.Sobel()&#xff0c;cv.Scharr()&#xff0c;cv.Laplacian()** 等。 图像梯度是图像处理中的一个基本概念&#xff0c;它用于测量图像亮度变化的强度和方向…

springCloud中将redis共用到common模块

一、 springCloud作为公共模块搭建框架 springCloud 微服务模块中将redis作为公共模块进行的搭建结构图&#xff0c;如下&#xff1a; 二、redis 公共模块的搭建框架 如上架构&#xff0c;代码如下pom.xml 关键代码&#xff1a; <dependencies><!-- SpringBoot Boo…