当前位置: 首页 > news >正文

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

最近做了一个发送邮件的功能, 在本地调试完成后,部署到阿里云服务器就一直报错,
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());}}
}

相关文章:

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

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

Socket编程权威指南(二)完美掌握TCP流式协议及Socket编程的recv()和send()

在上一篇文章中&#xff0c;我们学习了Socket编程的基础知识&#xff0c;包括创建Socket、绑定地址、监听连接、接收连接等操作。然而&#xff0c;真正的套接字编程远不止于此。本文将重点介绍TCP 流式协议&#xff0c;什么是粘包问题&#xff1f;如何解决粘包问题 &#xff1f…...

当C++的static遇上了继承

比如我们想要统计下当前类被实例化了多少次&#xff0c;我们通常会这么写 class A { public:A() { Count_; }~A() { Count_--; }int GetCount() { return Count_; }private:static int Count_; };class B { public:B() { Count_; }~B() { Count_--; }int GetCount() { return …...

Three.js中的Raycasting技术:实现3D场景交互事件的Raycaster详解

前言 在Web开发中&#xff0c;Three.js是一个极为强大的库&#xff0c;它让开发者能够轻松地在浏览器中创建和展示3D图形。随着3D技术在网页设计、游戏开发、数据可视化等领域的广泛应用&#xff0c;用户与3D场景的交互变得日益重要。而要实现这种交互&#xff0c;一个核心的技…...

5 分钟内构建一个简单的基于 Python 的 GAN

文章目录 一、说明二、代码三、训练四、后记 一、说明 生成对抗网络&#xff08;GAN&#xff09;因其能力而在学术界引起轩然大波。机器能够创作出新颖、富有灵感的作品&#xff0c;这让每个人都感到敬畏和恐惧。因此&#xff0c;人们开始好奇&#xff0c;如何构建一个这样的网…...

智能硬件产品中常用的参数存储和管理方案

一、有哪些参数需要管理? 在智能硬件产品中,一般有三类数据需要存储并管理: 1. 系统设置数据 系统设置数据是指产品自身正常工作所依赖的一些参数。 这类数据的特点:只能在生产过程中修改,出厂后用户无权限修改。 比如:产品SN、产品密钥/token/license、传感器校准值…...

SwiftUI中Mask修饰符的理解与使用

Mask是一种用于控制图形元素可见性的图形技术&#xff0c;使用给定视图的alpha通道掩码该视图。在SwiftUI中&#xff0c;它类似于创建一个只显示视图的特定部分的模板。 Mask修饰符的定义&#xff1a; func mask<Mask>(alignment: Alignment .center,ViewBuilder _ ma…...

全光网络与传统网络架构的对比分析

随着信息技术的飞速发展&#xff0c;网络已经成为我们日常生活中不可或缺的一部分。在这个信息爆炸的时代&#xff0c;全光网络和传统网络架构作为两种主流的网络技术&#xff0c;各有其特点和适用范围。本文将对这两种网络架构进行详细的对比分析&#xff0c;帮助读者更好地了…...

stack overflow复现

当你在内存的栈中&#xff0c;存放了太多元素&#xff0c;就有可能在造成 stack overflow这个问题。 今天看看如何复现这个问题。 下图&#xff0c;是我写的程序&#xff0c;不断的创造1KB的栈&#xff0c;来看看执行了多少次&#xff0c;无限循环。 最后结果是7929kB时, 发…...

mybatis使用笔记

文章目录 打印sql日志mybatis-config.xml方式application.yml里面配置配置类配置方式 其他扫描方式官网文档 mybatis用了那么久&#xff0c;实际一直不明白&#xff0c;做个笔记吧。 打印sql日志 实测&#xff0c;mybatis-config.xml方式好用(记得注掉yml里的相关配置) mybat…...

学习笔记——路由网络基础——路由概述

一、路由概述 1、路由定义与作用 路由(routing)是指导报文转发路径信息&#xff0c;通过路由可以确认转发IP报文的路径。 路由&#xff1a;是指路由器从一个接口上收到数据包&#xff0c;根据数据包的目的地址进行定向并转发到另一个接口的过程。 路由(routing)的定义是指分…...

在量子计算时代,大数据技术将面临哪些挑战和机遇?

在量子计算时代&#xff0c;大数据技术将面临以下挑战和机遇&#xff1a; 挑战&#xff1a; 处理速度&#xff1a;量子计算机具有极高的计算速度&#xff0c;大数据技术需要适应和充分利用这种速度。现有的大数据算法和架构可能需要重新设计和优化&#xff0c;以充分发挥量子计…...

怎么换自己手机的ip地址

在互联网时代&#xff0c;IP地址已经成为了我们数字身份的一部分。无论是浏览网页、下载文件还是进行在线交流&#xff0c;我们的IP地址都在默默发挥着作用。然而&#xff0c;有时出于安全或隐私保护的考虑&#xff0c;我们可能需要更换手机的IP地址。那么&#xff0c;如何轻松…...

搭建 Langchain-Chatchat 详细过程

前言 本文参考官网和其他多方教程&#xff0c;将搭建 Langchain-Chatchat 的详细步骤进行了整理&#xff0c;供大家参考。 我的硬件 4090 显卡win10 专业版本 搭建环境使用 chatglm2-6b 模型 1. 创建虚拟环境 chatchat &#xff0c;python 3.9 以上 conda create -n chat…...

C++期末复习

目录 1.基本函数 2.浅拷贝和深拷贝 3.初始化列表 4.const关键字的使用 5.静态成员变量和成员函数 6.C对象模型 7.友元 8.自动类型转换 9.继承 1.基本函数 &#xff08;1&#xff09;构造函数&#xff0c;这个需要注意的就是我们如果使用类名加括号&#xff0c;括号里面…...

2005-2022年各省居民人均消费支出数据(无缺失)

2005-2022年各省居民人均消费支出数据&#xff08;无缺失&#xff09; 1、时间&#xff1a;2005-2022年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;全体居民人均消费支出 4、范围&#xff1a;31省 5、缺失情况&#xff1a;无缺失 6、指标解释 居民人…...

swaggerHole:针对swaggerHub的公共API安全扫描工具

关于swaggerHole swaggerHole是一款针对swaggerHub的API安全扫描工具&#xff0c;该工具基于纯Python 3开发&#xff0c;可以帮助广大研究人员检索swaggerHub上公共API的相关敏感信息&#xff0c;整个任务过程均以自动化形式实现&#xff0c;且具备多线程特性和管道模式。 工具…...

【Rust】——面向对象设计模式的实现

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…...

C#朗读语音

最近有个需求&#xff0c;需要在C#程序发生异常时候&#xff0c;朗读文字&#xff0c;C#提供了.net framework可以提供简单的语音朗读功能。 引入依赖 using System.Media; using System.Speech.Synthesis; using System.Runtime.InteropServices; //报警音量 SystemSounds.…...

c++ 简单的日志类 CCLog

此日志类&#xff0c;简单地实现了向标准输出控制台和文件输出日志信息的功能&#xff0c;并能在这两者之间进行切换输出&#xff0c;满足输出日志的不同需求。 代码如下&#xff1a; /** CCLog.h* c_common_codes** Created by xichen on 12-1-12.* Copyright 2012 cc_te…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...