Spring Boot整合JavaMail实现邮件发送
一. 发送邮件原理
发件人【设置授权码】 - SMTP协议【Simple Mail TransferProtocol - 是一种提供可靠且有效的电子邮件传输的协议】 - 收件人
二. 获取授权码
开通POP3/SMTP,获取授权码
授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。适用于登录以下服务:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务。
温馨提醒:为了你的帐户安全,更改QQ密码以及独立密码会触发授权码过期,需要重新获取新的授权码登录
第一步:进入邮箱设置 -> 账户 -> 生成授权码 :【注意】POP3/SMTP ,IMAP/SMTP服务都需要开启
三. SpringBoot发送邮件步骤
1、导入依赖
<!--对邮件的支持jar-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2、配置邮箱
spring:servlet:multipart:#设置单个文件大小max-file-size: 10MB#设置单次请求文件的总大小max-request-size: 50MBmail:host: smtp.qq.com # 设置邮箱主机(服务商),这里使用QQ邮件服务器username: # 设置用户名 - 发送方password: # 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码properties:mail:smtp:auth: true # 必须进行授权认证,它的目的就是阻止他人任意乱发邮件starttls: #SMTP加密方式:连接到一个TLS保护连接enable: truerequired: true
3、发送邮件的时候可以自定义发送的内容,创建工具类
@Component
@Slf4j
public class MailUtil {/*** 1. 来源人名* 2. 来源内容*/public static final String originalText = "<hr style=\"border: 1px dashed #ef859d2e;margin: 20px 0\">\n" +" <div>\n" +" <div style=\"font-size: 18px;font-weight: bold;color: #C5343E\">\n" +" %s\n" +" </div>\n" +" <div style=\"margin-top: 6px;font-size: 16px;color: #000000\">\n" +" <p>\n" +" %s\n" +" </p>\n" +" </div>\n" +" </div>";/*** 发件人*/public static final String replyMail = "你之前的评论收到来自 %s 的回复";public static final String commentMail = "你的文章 %s 收到来自 %s 的评论";public static final String messageMail = "你收到来自 %s 的留言";public static final String loveMail = "你收到来自 %s 的祝福";public static final String imMail = "你收到来自 %s 的消息";public static final String notificationMail = "你收到来自 %s 的订阅";@Autowiredprivate JavaMailSender mailSender;@Value("${spring.mail.username}")private String sendMailer;/*** 1. 网站名称* 2. 邮件类型* 3. 发件人* 4. 发件内容* 5. originalText* 6. 网站名称*/private String mailText;@PostConstructpublic void init() {this.mailText = "<div style=\"font-family: serif;line-height: 22px;padding: 30px\">\n" +" <div style=\"display: flex;justify-content: center;width: 100%%;max-width: 900px;background-size: cover;border-radius: 10px\"></div>\n" +" <div style=\"margin-top: 20px;display: flex;flex-direction: column;align-items: center\">\n" +" <div style=\"margin: 10px auto 20px;text-align: center\">\n" +" <div style=\"line-height: 32px;font-size: 26px;font-weight: bold;color: #000000\">\n" +" 嘿!你在 %s 中收到一条新消息。\n" +" </div>\n" +" <div style=\"font-size: 16px;font-weight: bold;color: rgba(0, 0, 0, 0.19);margin-top: 21px\">\n" +" %s\n" +" </div>\n" +" </div>\n" +" <div style=\"min-width: 250px;max-width: 800px;min-height: 128px;background: #F7F7F7;border-radius: 10px;padding: 32px\">\n" +" <div>\n" +" <div style=\"font-size: 18px;font-weight: bold;color: #C5343E\">\n" +" %s\n" +" </div>\n" +" <div style=\"margin-top: 6px;font-size: 16px;color: #000000\">\n" +" <p>\n" +" %s\n" +" </p>\n" +" </div>\n" +" </div>\n" +" %s\n" +" <a style=\"width: 150px;height: 38px;background: #ef859d38;border-radius: 32px;display: flex;align-items: center;justify-content: center;text-decoration: none;margin: 40px auto 0\"\n" +" href=\"https://poetize.cn\" target=\"_blank\">\n" +" <span style=\"color: #DB214B\">有朋自远方来</span>\n" +" </a>\n" +" </div>\n" +" <div style=\"margin-top: 20px;font-size: 12px;color: #00000045\">\n" +" 此邮件由 %s 自动发出,直接回复无效(一天最多发送 " + CommonConst.COMMENT_IM_MAIL_COUNT + " 条通知邮件和 " + CommonConst.CODE_MAIL_COUNT + " 条验证码邮件),退订请联系站长。\n" +" </div>\n" +" </div>\n" +"</div>";}public String getMailText() {return mailText;}
}
4、实现类。一般来说验证码可以应用在注册、登录、找回密码等功能上。前端需要传递flag标志,后端进行判断发送哪种邮件
public Result getCodeForForgetPassword(String place, Integer flag) {int i = new Random().nextInt(900000) + 100000;if (flag == 1) {// 任务需求} else if (flag == 2) {log.info(place + "---" + "邮箱验证码---" + i);List<String> mail = new ArrayList<>();mail.add(place);String text = getCodeMail(i);WebInfo webInfo = (WebInfo) UtopianCache.get(CommonConst.WEB_INFO);AtomicInteger count = (AtomicInteger) UtopianCache.get(CommonConst.CODE_MAIL + mail.get(0));if (count == null || count.get() < CommonConst.CODE_MAIL_COUNT) {mailUtil.sendMailMessage(mail, "您有一封来自" + (webInfo == null ? "Utopian" : webInfo.getWebName()) + "的回信!", text);if (count == null) {UtopianCache.put(CommonConst.CODE_MAIL + mail.get(0), new AtomicInteger(1), CommonConst.CODE_EXPIRE);} else {count.incrementAndGet();}} else {return Result.fail("验证码发送次数过多,请明天再试!");}}UtopianCache.put(CommonConst.FORGET_PASSWORD + place + "_" + flag, Integer.valueOf(i), 300);return Result.success();}
首先根据标志为flag参数,这里2为注册时候使用的格式。调用getCodeMail方法获取模板内容
private String getCodeMail(int i) {WebInfo webInfo = (WebInfo) UtopianCache.get(CommonConst.WEB_INFO);String webName = (webInfo == null ? "Utopian" : webInfo.getWebName());return String.format(mailUtil.getMailText(),webName,String.format(MailUtil.imMail, PoetryUtil.getAdminUser().getUsername()),UtopianUtil.getAdminUser().getUsername(),String.format(codeFormat, i),"",webName);}
模板内容为:【utopian.cn】%s为本次验证的验证码,请在5分钟内完成验证。为保证账号安全,请勿泄漏此验证码。
对用户点击发送的验证码的次数也需要进行统计,不超过三次,否则进行提示
4、发送邮件
这里采用异步的方式,分别填充邮件主题,邮件内容,发送时间等信息
@Asyncpublic void sendMailMessage(List<String> to, String subject, String text) {log.info("发送邮件===================");log.info("to:{}", JSON.toJSONString(to));log.info("subject:{}", subject);log.info("text:{}", text);try {//true代表支持复杂的类型MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);//邮件发信人mimeMessageHelper.setFrom(sendMailer);//邮件收信人1或多个mimeMessageHelper.setTo(to.toArray(new String[0]));//邮件主题mimeMessageHelper.setSubject(subject);//邮件内容mimeMessageHelper.setText(text, true);//邮件发送时间mimeMessageHelper.setSentDate(new Date());//发送邮件mailSender.send(mimeMessageHelper.getMimeMessage());log.info("发送成功==================");} catch (MessagingException e) {log.info("发送失败==================");log.error(e.getMessage());}}

相关文章:
Spring Boot整合JavaMail实现邮件发送
一. 发送邮件原理 发件人【设置授权码】 - SMTP协议【Simple Mail TransferProtocol - 是一种提供可靠且有效的电子邮件传输的协议】 - 收件人 二. 获取授权码 开通POP3/SMTP,获取授权码 授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。适用…...
字节跳动发布UI-TARS,超越GPT-4o和Claude,能接管电脑完成复杂任务
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
数据的秘密:如何用大数据分析挖掘商业价值
数据的秘密:如何用大数据分析挖掘商业价值 在这个数据爆炸的时代,我们每天都在产生、存储和处理着海量的数据。然而,仅仅拥有数据并不等于拥有价值。就像拥有一座金矿,不开采和提炼,最终只是一堆毫无用处的石头。如何…...
OAuth1和OAuth2授权协议
OAuth 1 授权协议 1. 概述 OAuth1 是 OAuth 标准的第一个正式版本,它通过 签名和令牌 的方式,实现用户授权第三方访问其资源的功能。在 OAuth1 中,安全性依赖于签名机制,无需传递用户密码。 2. 核心特性 使用 签名(…...
AI学习(vscode+deepseek+cline)
1、网页生成不成功时,直接根据提示让模型替你解决问题 2、http://localhost:3000 拒绝链接时,cmd输入命令InetMgr,网站右键新建-配置你的网页代码物理地址,这里我还输入本机登录名及密码了,并把端口地址由默认80修改为…...
04-机器学习-网页数据抓取
网络爬取(Web Scraping)深度指南 1. 网络爬取全流程设计 一个完整的网络爬取项目通常包含以下步骤: 目标分析: 明确需求:需要哪些数据(如商品价格、评论、图片)?网站结构分析&…...
计网week1+2
计网 一.概念 1.什么是Internet 节点:主机及其运行的应用程序、路由器、交换机 边:通信链路,接入网链路主机连接到互联网的链路,光纤、网输电缆 协议:对等层的实体之间通信要遵守的标准,规定了语法、语义…...
重定向与缓冲区
4种重定向 我们有如下的代码: #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h>#define FILE_NAME "log.txt"int main() {close(1)…...
练习题 - Django 4.x File 文件上传使用示例和配置方法
在现代的 web 应用开发中,文件上传是一个常见的功能,无论是用户上传头像、上传文档,还是其他类型的文件,处理文件上传都是开发者必须掌握的技能之一。Django 作为一个流行的 Python web 框架,提供了便捷的文件上传功能和配置方法。学习如何在 Django 中实现文件上传,不仅…...
[VSCode] vscode下载安装及安装中文插件详解(附下载链接)
VSCode 是一款由微软开发且跨平台的免费源代码编辑器;该软件支持语法高亮、代码自动补全、代码重构、查看定义功能,并且内置了命令行工具和Git版本控制系统。 下载链接:https://pan.quark.cn/s/3a90aef4b645 提取码:NFy5 通过上面…...
JVM常见知识点
在《深入理解Java虚拟机》一书中,介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中,对于地址空间进行了分区域的设计,由于JVM是仿照真实的机器进行设计的,那么也进行了分区域的设计。核心区域有四个,…...
深入探索 Vue 3 Markdown 编辑器:高级功能与实现
目录 1. 为什么选择 Markdown 编辑器?2. 选择合适的 Markdown 编辑器3. 安装与基本配置安装 配置 Markdown 编辑器代码说明 4. 高级功能实现4.1 实时预览与双向绑定4.2 插入图片和图像上传安装图像上传插件配置图像上传插件 4.3 数学公式支持安装 KaTeX配置 KaTeX 插…...
vscode无法格式化go代码的问题
CTRLshiftp 点击Go:Install/Update Tools 点击全选,OK!...
《Java程序设计》课程考核试卷
一、单项选择题(本大题共10个小题,每小题2分,共20分) 1.下列用来编译Java源文件为字节码文件的工具是( )。 A.java B.javadoc C.jar D.javac 2…...
one-hot (独热编码)
一、目的 假设我们现在需要对猫、 狗、 人这三个类别进行分类。 若以 0 代表猫, 以 1 代表狗, 以 2 代表人,会发现那么猫和狗之间距离为 1, 狗和人之间距离为 1, 而猫和人之间距离为 2。 假设真实标签是猫࿰…...
寒假1.23
题解 web:[极客大挑战 2019]Secret File(文件包含漏洞) 打开链接是一个普通的文字界面 查看一下源代码 发现一个链接,点进去看看 再点一次看看,没什么用 仔细看,有一个问题,当点击./action.ph…...
unity 粒子系统设置触发
1、勾选Triggers选项 2、将作为触发器的物体拉入队列当中,物体上必须挂载collider 3、将想要触发的方式(Inide、Outside、Enter和Exit)选择为”Callback“,其他默认为”Ignore“ 4、Collider Query Mode 设置为All:…...
【C++】类和对象(五)
1、初始化列表 作用:C提供了初始化列表语法,用来初始化属性。 语法: 构造函数():属性1(值1),属性2(值2)...{}示例: #include<i…...
超分辨率体积重建实现术前前列腺MRI和大病理切片组织病理学图像的3D配准
摘要: 磁共振成像(MRI)在前列腺癌诊断和治疗中的应用正在迅速增加。然而,在MRI上识别癌症的存在和范围仍然具有挑战性,导致即使是专家放射科医生在检测结果上也存在高度变异性。提高MRI上的癌症检测能力对于减少这种变异性并最大化MRI的临床效用至关重要。迄今为止,这种改…...
第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)
1.并发编程的三个重要特性 并发编程有三个至关重要的特性,分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断,要么所有的操作都不执行…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
