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

springboot实现邮箱验证码功能

引言

邮箱验证码是一个常见的功能,常用于邮箱绑定、修改密码等操作上,这里我演示一下如何使用springboot实现验证码的发送功能;

这里用qq邮箱进行演示,其他都差不多;

准备工作

首先要在设置->账户中开启邮箱POP3/SMTP服务:

image-20230116142701088

开启成功后会获取一个授权码,记住该授权码:

image-20230116142559070

初步准备完成;

代码实现

引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>

application.yml中配置:

spring:mail:host: smtp.qq.comusername: 邮箱号@qq.com # 发件人邮箱password: 授权码 # 邮箱授权码default-encoding: UTF-8

下面就是controller、service了

controller

@PostMapping("/code")
public BaseResponse<String> sendMessageToEmail(@RequestParam("email") String email) {if (StringUtils.isAnyBlank(email)) {throw new BusinessException(StatusCode.NULL_ERROR, "邮箱为空");}// 校验邮箱RegExpUtil.regExpVerify(RegExpUtil.emailRegExp, email, "邮箱格式错误");// 从redis中查看有没有该邮箱的验证码String verifyCode = (String) redisTemplate.opsForValue().get(RedisKey.EMAIL_CODE + email);if (!StringUtils.isAnyBlank(verifyCode)) {throw new BusinessException(StatusCode.SUCCESS, "验证码已发送=>" + verifyCode);}// 如果redis没有该手机号验证码,则获取验证码并发送短信verifyCode = RandomSmsNumUtils.getSixBitRandom(); // 获取六位验证码emailService.sendMessageToEmail(verifyCode, email);// 将该验证码存入redisredisTemplate.opsForValue().set(RedisKey.EMAIL_CODE + email,verifyCode,EMAIL_EXPIRED_TIME,TimeUnit.MINUTES);return ResultUtils.success("发送成功");
}

大致流程就是:校验邮箱->查redis判断邮件是否已发送->未发送则发送验证码->将发送的验证码存入redis

接下来是service,网上有很多发送的就是简单的文本验证码,类似这样的:

image-20230116143909079

就是一个纯文本,不好看,所以接下来直接实现一个html模板email,如图:

image-20230116143828238

html的解析可以用springboot自带的thymeleaf,引入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

然后再resources文件下创建templates文件夹,创建一个html文件作为邮件模板:

image-20230116144125582

该模板内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>邮箱验证码</title><style>table {width: 700px;margin: 0 auto;}#top {width: 700px;border-bottom: 1px solid #ccc;margin: 0 auto 30px;}#top table {font: 12px Tahoma, Arial, 宋体;height: 40px;}#content {width: 680px;padding: 0 10px;margin: 0 auto;}#content_top {line-height: 1.5;font-size: 14px;margin-bottom: 25px;color: #4d4d4d;}#content_top strong {display: block;margin-bottom: 15px;}#content_top strong span {color: #f60;font-size: 16px;}#verificationCode {color: #f60;font-size: 24px;}#content_bottom {margin-bottom: 30px;}#content_bottom small {display: block;margin-bottom: 20px;font-size: 12px;color: #747474;}#bottom {width: 700px;margin: 0 auto;}#bottom div {padding: 10px 10px 0;border-top: 1px solid #ccc;color: #747474;margin-bottom: 20px;line-height: 1.3em;font-size: 12px;}#content_top strong span {font-size: 18px;color: #FE4F70;}#sign {text-align: right;font-size: 18px;color: #FE4F70;font-weight: bold;}#verificationCode {height: 100px;width: 680px;text-align: center;margin: 30px 0;}#verificationCode div {height: 100px;width: 680px;}.button {color: #FE4F70;margin-left: 10px;height: 80px;width: 80px;resize: none;font-size: 42px;border: none;outline: none;padding: 10px 15px;background: #ededed;text-align: center;border-radius: 17px;box-shadow: 6px 6px 12px #cccccc,-6px -6px 12px #ffffff;}.button:hover {box-shadow: inset 6px 6px 4px #d1d1d1,inset -6px -6px 4px #ffffff;}</style>
</head>
<body>
<table><tbody><tr><td><div id="top"><table><tbody><tr><td></td></tr></tbody></table></div><div id="content"><div id="content_top"><strong>尊敬的用户,您好!</strong><strong>您正在使用验证码校验,请在5分钟内填写如下验证码,如非本人操作请忽略该邮件</strong><div id="verificationCode"><button class="button" th:each="a:${verifyCode}">[[${a}]]</button></div></div><div id="content_bottom"><small>注意:此操作可能会修改您的密码、登录邮箱或绑定手机。如非本人操作,请及时登录并修改密码以保证帐户安全<br>(工作人员不会向你索取此验证码,请勿泄漏!)</small></div></div><div id="bottom"><div><p>此为系统邮件,请勿回复<br>请保管好您的邮箱,避免账号被他人盗用</p>
<!--                    <p id="sign">——POLAR官方</p>--></div></div></td></tr></tbody>
</table>
</body>

模板参考文章:传送门

接下来就是编写service了:

@Service("emailService")
public class EmailServiceImpl implements EmailService {@Resourceprivate JavaMailSender javaMailSender;@Resourceprivate TemplateEngine templateEngine;@Value("${spring.mail.username}")private String username;@Overridepublic void sendMessageToEmail(String verifyCode, String email) {Context context = new Context(); // 引入Template的Context// 设置模板中的变量(分割验证码)context.setVariable("verifyCode", Arrays.asList(verifyCode.split("")));// 第一个参数为模板的名称(html不用写全路径)String process = templateEngine.process("EmailVerificationCode.html", context); // 这里不用写全路径MimeMessage mimeMessage = javaMailSender.createMimeMessage();try {MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);helper.setSubject("【POLAR】验证码"); // 邮件的标题helper.setFrom(username); // 发送者helper.setTo(email); // 接收者helper.setSentDate(new Date()); // 时间helper.setText(process, true); // 第二个参数true表示这是一个html文本} catch (MessagingException e) {throw new BusinessException(StatusCode.SYSTEM_ERROR, "邮件发送异常");}javaMailSender.send(mimeMessage);}
}

这就完成整体逻辑的编写了,接下来测试一下:

image-20230116144830354

接收到的邮件:

image-20230116144908257

查看redis:

image-20230116145007322

至此所有功能完成;

相关文章:

springboot实现邮箱验证码功能

引言 邮箱验证码是一个常见的功能&#xff0c;常用于邮箱绑定、修改密码等操作上&#xff0c;这里我演示一下如何使用springboot实现验证码的发送功能&#xff1b; 这里用qq邮箱进行演示&#xff0c;其他都差不多&#xff1b; 准备工作 首先要在设置->账户中开启邮箱POP…...

Java 进阶(5) Java IO流

⼀、File类 概念&#xff1a;代表物理盘符中的⼀个⽂件或者⽂件夹。 常见方法&#xff1a; 方法名 描述 createNewFile() 创建⼀个新文件。 mkdir() 创建⼀个新⽬录。 delete() 删除⽂件或空⽬录。 exists() 判断File对象所对象所代表的对象是否存在。 getAbsolute…...

“终于我从字节离职了...“一个年薪40W的测试工程师的自白...

”我递上了我的辞职信&#xff0c;不是因为公司给的不多&#xff0c;也不是因为公司待我不好&#xff0c;但是我觉得&#xff0c;我每天看中我憔悴的面容&#xff0c;每天晚上拖着疲惫的身体躺在床上&#xff0c;我都不知道人生的意义&#xff0c;是赚钱吗&#xff1f;是为了更…...

设计模式之策略模式(C++)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 一、策略模式是什么&#xff1f; 策略模式是一种行为型的软件设计模式&#xff0c;针对某个行为&#xff0c;在不同的应用场景下&…...

从工厂普工到Python女程序员,聊聊这一路我是如何逆袭的?

我来聊聊我是如何从一名工厂普工&#xff0c;到国外程序员的过程&#xff0c;这里面充满了坎坷。过去我的工作是在工厂的流水线上&#xff0c;我负责检测电池的正负极。现如今我每天从早上6:20起床&#xff0c;6点四五十分出发到地铁站&#xff0c;7:40到公司。我会给自己准备一…...

全国青少年信息素养大赛2023年python·选做题模拟二卷

目录 打印真题文章进行做题: 全国青少年电子信息智能创新大赛 python选做题模拟二卷 一、单选题 1. numbers = [1, 11, 111, 9], 运行numbers.sort() 后,运行numbers.reverse() numbers会变成?( )...

分布式事务Seata原理

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能与简单易用的分布式事务服务&#xff0c;为用户提供了 AT、TCC、SAGA 和 XA 几种不同的事务模式。Seata AT模式是基于XA事务演进而来&#xff0c;需要数据库支持。AT 模式的特点就是对业务无入侵式&#xff0…...

用ChatGPT怎么赚钱?普通人用这5个方法也能赚到生活费

ChatGPT在互联网火得一塌糊涂&#xff0c;因为它可以帮很多人解决问题。比如&#xff1a;帮编辑人员写文章&#xff0c;还可以替代程序员写代码&#xff0c;帮策划人员写文案策划等等。ChatGPT这么厉害&#xff0c;能否用它来赚钱呢&#xff1f;今天和大家分享用ChatGPT赚钱的5…...

( “树” 之 DFS) 110. 平衡二叉树 ——【Leetcode每日一题】

110. 平衡二叉树 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] …...

nvm软件使用-同一个环境下控制多个不同node版本

1.使用场景 nvm是一个用于管理Node.js版本的工具&#xff0c;它可以让你在同一台机器上安装和切换不同的Node.js版本。使用nvm的好处有以下几点&#xff1a; 1.1.nvm可以让你轻松地测试你的代码在不同的Node.js版本下的兼容性和性能&#xff0c;避免因为版本差异导致的问题。…...

连续两个南航的研究生面试出了从来没出现过的问题,本科和研究生都是计算机专业的,竟然说static是不可更改的。

最近面试人数有点多&#xff0c;面试有点频繁&#xff0c;因此发现了一些学生普遍会发生的错误&#xff0c;可以说是很离谱。 因为做了十多年的面试官&#xff0c;无论是大中小厂的面试&#xff0c;还是社招、校招。 从来没有遇到过这样的情况&#xff0c;而且发生在两个南航…...

How to install nacos/nacos-server:v2.1.2-slim with docker

今天给大家介绍一下如何基于Docker的nacos/nacos-server:v2.1.2-slim镜像安装nacos 1、Data Source 我们需要从nacos的github官网下载nacos 2.12发布包 nacos-server-2.1.2.tar.gznacos-server-2.1.2.zip 这里以nacos-server-2.1.2.tar.gz为例来介绍&#xff0c;解压后我们…...

Rust社区引发舆论危机,问题到底出在哪儿?

围绕开源的法律问题&#xff0c;讨论焦点往往集中在开源许可证、软件著作权等方面&#xff0c;商标的讨论却极少引人关注。事实上&#xff0c;关于开源软件以及开源软件的衍生产品的商标使用情况往往处于某种灰色地带。 最近&#xff0c;Rust基金会正在就更新的商标政策征求反馈…...

C++算法恢复训练之归并排序

归并排序&#xff08;Merge Sort&#xff09;是一种基于分治思想的排序算法&#xff0c;它将待排序数组分成两个子数组&#xff0c;然后对这两个子数组分别进行排序&#xff0c;最后将两个已排序的子数组合并成一个有序数组。归并排序是一种稳定的排序算法&#xff0c;具体体现…...

使用Process Explorer和Clumsy工具定位软件高CPU占用问题

目录 1、问题描述 2、使用Process Explorer初步找到CPU占用高的原因 3、使用Clumsy工具在公司内网环境复现了问题...

为何巴菲特和马斯克站在了一起?

股神巴菲特虽然非常传奇&#xff0c;但是马斯克对其并不感冒。马斯克曾经在一档电视节目中表示&#xff0c;实业才是王道&#xff0c;埋怨金融业抢走太多人才和精英&#xff0c;暗指巴菲特为年轻人做了错误示范。当然&#xff0c;巴菲特的投资非常厉害&#xff0c;但也有失手的…...

企业数字化转型全是坑?这几篇数字化转型成功案例,减少70%损失

这篇给大家整理了200企业数字化转型案例合集&#xff0c;涵盖了制造、建筑、教育、零售、互联网等10行业的大中小型企业数字化转型思路&#xff0c;希望对大家有所帮助。 案例全部整合在这篇文章中&#xff0c;点击即可查看>>数字化干货资料合集&#xff01; 01 首先&…...

13.Java面向对象----嵌套类

Java面向对象—嵌套类、内部类、匿名类 一、static静态 在《Java编程思想》有这样一段话&#xff1a;   “static方法就是没有this的方法。在static方法内部不能调用非静态方法&#xff0c;反过来是可以的。而且可以在没有创建任何对象的前提下&#xff0c;仅仅通过类本身来…...

Redis数据迁移过程,使用jedis客户端发送命令,需要注意string和byte类型的命令,如果使用的转换字符编码不一致,会导致丢数据

1.了解String与byte之间存在的字符编码映射规则&#xff08;java为例&#xff09; string与byte来回转换&#xff0c;需要指定一样字符编码规则 详细原因请参考&#xff1a;关于Java中bytes到String的转换-阿里云开发者社区 简单来说 &#xff08;1&#xff09;string和by…...

第六章 IA-32指令类型

IA-32指令类型1、传送指令1.1、常用传送指令1.1.1、通用数据传送指令1.2、传送指令执行过程2、定点算术运算指令2.1、常用定点运算指令2.2、加法运算的底层实现举例2.3、加法指令和乘法指令举例3、按位运算指令3.1、逻辑运算和移位运算3.2、按位运算指令举例4、控制转移指令4.1…...

如何在3分钟内为Axure RP配置中文界面:终极汉化指南

如何在3分钟内为Axure RP配置中文界面&#xff1a;终极汉化指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包&#xff0c;不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 你是…...

树莓派4b(armv8) 64位系统源码编译onnx实战指南

1. 环境准备&#xff1a;从零搭建树莓派4B开发环境 在树莓派4B上编译ONNX源码之前&#xff0c;我们需要先确保系统环境配置正确。我用的是一台4GB内存版本的树莓派4B&#xff0c;系统是最新的Raspberry Pi OS 64位版本。这里有个小细节要注意&#xff1a;很多教程还在用32位系统…...

Maven阿里云镜像配置详解:提升依赖下载速度的终极方案

Maven阿里云镜像配置实战&#xff1a;突破国内依赖下载瓶颈的完整指南 每次打开IDE准备大干一场时&#xff0c;最扫兴的莫过于看着Maven依赖下载进度条像蜗牛一样缓慢爬行。作为Java开发者&#xff0c;我们都经历过中央仓库下载速度只有几十KB/s的煎熬时刻——特别是当团队新成…...

大疆L1点云数据导出后,用CloudCompare做可视化与简单分析的完整流程

大疆L1点云数据从导出到分析&#xff1a;CloudCompare实战全流程指南 当你从DJI Terra中导出L1激光雷达的LAS文件时&#xff0c;真正的数据价值挖掘才刚刚开始。作为测绘工程师或三维建模从业者&#xff0c;如何将这些原始点云转化为可操作的洞察&#xff1f;本文将带你用开源神…...

高效批处理:一键复制文件/文件夹至当前目录所有子文件夹

1. 为什么需要批量复制文件到子文件夹&#xff1f; 在日常工作中&#xff0c;我经常遇到这样的场景&#xff1a;需要把一个重要文件快速分发到几十甚至上百个子文件夹中。比如给每个项目文件夹添加一份新的规范文档&#xff0c;或者为所有客户目录更新同一份合同模板。手动操作…...

如何快速搭建Kafka Docker集群:broker-list.sh工作原理与实用指南

如何快速搭建Kafka Docker集群&#xff1a;broker-list.sh工作原理与实用指南 【免费下载链接】kafka-docker Dockerfile for Apache Kafka 项目地址: https://gitcode.com/gh_mirrors/ka/kafka-docker GitHub 加速计划 / ka / kafka-docker 项目提供了基于 Docker 的 A…...

暴力检测新思路:如何用HL-Net和弱监督技术提升多模态识别准确率?

多模态暴力检测技术革新&#xff1a;HL-Net与弱监督学习的实战解析 暴力行为检测一直是计算机视觉和音频分析领域的重要挑战。传统的暴力检测方法往往受限于单一模态输入、高昂的标注成本以及有限的场景适应性。本文将深入探讨如何通过HL-Net架构和弱监督学习技术&#xff0c;构…...

保姆级避坑指南:用Python预测波士顿房价,你的MSE为什么降不下来?

Python实战&#xff1a;波士顿房价预测模型MSE居高不下的7个关键排查点 当你第一次尝试用线性回归预测波士顿房价时&#xff0c;最令人沮丧的莫过于看着训练损失曲线反复横跳&#xff0c;而测试集的MSE&#xff08;均方误差&#xff09;却像被钉在墙上的蝴蝶标本一样纹丝不动。…...

前后端分离毕设架构指南:从技术选型到生产级落地

前后端分离架构如今已成为现代Web开发的标配&#xff0c;但对于即将进行毕业设计的同学来说&#xff0c;如何从零开始搭建一个结构清晰、易于维护的毕设项目&#xff0c;却是一个不小的挑战。很多同学在项目初期雄心勃勃&#xff0c;但在开发过程中却常常陷入接口文档缺失、前后…...

开源项目版本冲突解决指南:从现象到实践的深度解析

开源项目版本冲突解决指南&#xff1a;从现象到实践的深度解析 【免费下载链接】ComfyUI-Impact-Pack 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Impact-Pack 问题现象&#xff1a;版本不匹配的警告信号 在开源项目开发中&#xff0c;你是否遇到过这样的情…...