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

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());}}

image-20231228122738660

相关文章:

Spring Boot整合JavaMail实现邮件发送

一. 发送邮件原理 发件人【设置授权码】 - SMTP协议【Simple Mail TransferProtocol - 是一种提供可靠且有效的电子邮件传输的协议】 - 收件人 二. 获取授权码 开通POP3/SMTP&#xff0c;获取授权码 授权码是QQ邮箱推出的&#xff0c;用于登录第三方客户端的专用密码。适用…...

字节跳动发布UI-TARS,超越GPT-4o和Claude,能接管电脑完成复杂任务

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

数据的秘密:如何用大数据分析挖掘商业价值

数据的秘密&#xff1a;如何用大数据分析挖掘商业价值 在这个数据爆炸的时代&#xff0c;我们每天都在产生、存储和处理着海量的数据。然而&#xff0c;仅仅拥有数据并不等于拥有价值。就像拥有一座金矿&#xff0c;不开采和提炼&#xff0c;最终只是一堆毫无用处的石头。如何…...

OAuth1和OAuth2授权协议

OAuth 1 授权协议 1. 概述 OAuth1 是 OAuth 标准的第一个正式版本&#xff0c;它通过 签名和令牌 的方式&#xff0c;实现用户授权第三方访问其资源的功能。在 OAuth1 中&#xff0c;安全性依赖于签名机制&#xff0c;无需传递用户密码。 2. 核心特性 使用 签名&#xff08…...

AI学习(vscode+deepseek+cline)

1、网页生成不成功时&#xff0c;直接根据提示让模型替你解决问题 2、http://localhost:3000 拒绝链接时&#xff0c;cmd输入命令InetMgr&#xff0c;网站右键新建-配置你的网页代码物理地址&#xff0c;这里我还输入本机登录名及密码了&#xff0c;并把端口地址由默认80修改为…...

04-机器学习-网页数据抓取

网络爬取&#xff08;Web Scraping&#xff09;深度指南 1. 网络爬取全流程设计 一个完整的网络爬取项目通常包含以下步骤&#xff1a; 目标分析&#xff1a; 明确需求&#xff1a;需要哪些数据&#xff08;如商品价格、评论、图片&#xff09;&#xff1f;网站结构分析&…...

计网week1+2

计网 一.概念 1.什么是Internet 节点&#xff1a;主机及其运行的应用程序、路由器、交换机 边&#xff1a;通信链路&#xff0c;接入网链路主机连接到互联网的链路&#xff0c;光纤、网输电缆 协议&#xff1a;对等层的实体之间通信要遵守的标准&#xff0c;规定了语法、语义…...

重定向与缓冲区

4种重定向 我们有如下的代码&#xff1a; #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 是一款由微软开发且跨平台的免费源代码编辑器&#xff1b;该软件支持语法高亮、代码自动补全、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和Git版本控制系统。 下载链接&#xff1a;https://pan.quark.cn/s/3a90aef4b645 提取码&#xff1a;NFy5 通过上面…...

JVM常见知识点

在《深入理解Java虚拟机》一书中&#xff0c;介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中&#xff0c;对于地址空间进行了分区域的设计&#xff0c;由于JVM是仿照真实的机器进行设计的&#xff0c;那么也进行了分区域的设计。核心区域有四个&#xff0c;…...

深入探索 Vue 3 Markdown 编辑器:高级功能与实现

目录 1. 为什么选择 Markdown 编辑器&#xff1f;2. 选择合适的 Markdown 编辑器3. 安装与基本配置安装 配置 Markdown 编辑器代码说明 4. 高级功能实现4.1 实时预览与双向绑定4.2 插入图片和图像上传安装图像上传插件配置图像上传插件 4.3 数学公式支持安装 KaTeX配置 KaTeX 插…...

vscode无法格式化go代码的问题

CTRLshiftp 点击Go:Install/Update Tools 点击全选&#xff0c;OK&#xff01;...

《Java程序设计》课程考核试卷

一、单项选择题&#xff08;本大题共10个小题&#xff0c;每小题2分&#xff0c;共20分&#xff09; 1.下列用来编译Java源文件为字节码文件的工具是&#xff08; &#xff09;。 A.java B.javadoc C.jar D.javac 2…...

one-hot (独热编码)

一、目的 假设我们现在需要对猫、 狗、 人这三个类别进行分类。 若以 0 代表猫&#xff0c; 以 1 代表狗&#xff0c; 以 2 代表人&#xff0c;会发现那么猫和狗之间距离为 1&#xff0c; 狗和人之间距离为 1&#xff0c; 而猫和人之间距离为 2。 假设真实标签是猫&#xff0…...

寒假1.23

题解 web&#xff1a;[极客大挑战 2019]Secret File&#xff08;文件包含漏洞&#xff09; 打开链接是一个普通的文字界面 查看一下源代码 发现一个链接&#xff0c;点进去看看 再点一次看看&#xff0c;没什么用 仔细看&#xff0c;有一个问题&#xff0c;当点击./action.ph…...

unity 粒子系统设置触发

1、勾选Triggers选项 2、将作为触发器的物体拉入队列当中&#xff0c;物体上必须挂载collider 3、将想要触发的方式&#xff08;Inide、Outside、Enter和Exit&#xff09;选择为”Callback“&#xff0c;其他默认为”Ignore“ 4、Collider Query Mode 设置为All&#xff1a…...

【C++】类和对象(五)

1、初始化列表 作用&#xff1a;C提供了初始化列表语法&#xff0c;用来初始化属性。 语法&#xff1a; 构造函数&#xff08;&#xff09;&#xff1a;属性1&#xff08;值1&#xff09;&#xff0c;属性2&#xff08;值2&#xff09;...{}示例&#xff1a; #include<i…...

超分辨率体积重建实现术前前列腺MRI和大病理切片组织病理学图像的3D配准

摘要: 磁共振成像(MRI)在前列腺癌诊断和治疗中的应用正在迅速增加。然而,在MRI上识别癌症的存在和范围仍然具有挑战性,导致即使是专家放射科医生在检测结果上也存在高度变异性。提高MRI上的癌症检测能力对于减少这种变异性并最大化MRI的临床效用至关重要。迄今为止,这种改…...

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)

1.并发编程的三个重要特性 并发编程有三个至关重要的特性&#xff0c;分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中&#xff0c;要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断&#xff0c;要么所有的操作都不执行…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...