当前位置: 首页 > 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…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...