基于spring boot实现邮箱发送和邮箱验证
目录
- 一、邮箱发送实现
- 1. 开通邮箱服务
- 2. 添加邮箱依赖
- 3.添加配置
- 4.添加邮箱通用类
- 5. 测试类
- 二、邮箱验证实现
- 1.添加依赖
- 2. 添加配置
- 3.添加controller
- 4. 测试
项目地址: https://gitee.com/nssnail/springboot-email
一、邮箱发送实现
1. 开通邮箱服务
使用qq邮箱、163邮箱都行,其他有邮箱服务功能的都可以,这里以163邮箱为例
登录163邮箱,然后在设置那里选择POP3/SMTP/IMAP

开通IMAP/SMTP服务

开通后会有个授权码,记录下来,后面需要用到

2. 添加邮箱依赖
添加pom文件
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>
3.添加配置
host是开通smtp时会有个地址的
username填的是邮箱账号
password填的是刚才上面开通smtp的授权码,请注意不是邮箱密码,是授权码
注:
1.配置里面有个port的配置是默认端口,尽量不要自己去设置,不然可能会无法访问,以下配置是没有port的
2.配置错误可以尝试把注释去掉,因为有可能会因为复制过去的编码问题影响
spring:mail:host: smtp.163.com # smtp地址,开通的时候会显示username: xxxxx@163.com # 你的邮箱账号password: ****** # 你的邮箱授权码properties:mail:smtp:auth: truestarttls:enable: trueprotocol: smtp
4.添加邮箱通用类
这里是用了hutools的工具和lombok的Slf4j日志,视情况而添加
<!-- 工具类 -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.2</version>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version><scope>provided</scope>
</dependency>
@Service
@Slf4j
public class EmailService {@Autowiredprivate JavaMailSender mailSender;@Value("${spring.mail.username}")private String username;/*** 发送文本邮件** @param to 收件人地址* @param subject 邮件主题* @param content 邮件内容* @param cc 抄送地址*/public void sendSimpleMail(String to, String subject, String content, String... cc) {SimpleMailMessage message = new SimpleMailMessage();message.setFrom(username);message.setTo(to);message.setSubject(subject);message.setText(content);if (ArrayUtil.isNotEmpty(cc)) {message.setCc(cc);}mailSender.send(message);}/*** 发送HTML邮件** @param to 收件人地址* @param subject 邮件主题* @param content 邮件内容* @param cc 抄送地址*/public void sendHtmlMail(String to, String subject, String content, String... cc) {try {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message, true,"UTF-8");helper.setFrom(username);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);if (ArrayUtil.isNotEmpty(cc)) {helper.setCc(cc);}mailSender.send(message);} catch (MessagingException e) {log.error("发送邮件失败,收件人:{}", to, e);}}/*** 发送带附件的邮件** @param to 收件人地址* @param subject 邮件主题* @param content 邮件内容* @param filePath 附件地址* @param cc 抄送地址*/public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) {try {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message, true,"UTF-8");helper.setFrom(username);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);if (ArrayUtil.isNotEmpty(cc)) {helper.setCc(cc);}FileSystemResource file = new FileSystemResource(new File(filePath));String fileName = filePath.substring(filePath.lastIndexOf(File.separator));helper.addAttachment(fileName, file);mailSender.send(message);} catch (MessagingException e) {log.error("发送邮件失败,收件人:{}", to, e);}}/*** 发送正文中有静态资源的邮件** @param to 收件人地址* @param subject 邮件主题* @param content 邮件内容* @param rscPath 静态资源地址* @param rscId 静态资源id* @param cc 抄送地址*/public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) {try {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message, true,"UTF-8");helper.setFrom(username);helper.setTo(to);helper.setSubject(subject);helper.setText(content, true);if (ArrayUtil.isNotEmpty(cc)) {helper.setCc(cc);}FileSystemResource res = new FileSystemResource(new File(rscPath));helper.addInline(rscId, res);mailSender.send(message);} catch (MessagingException e) {log.error("发送邮件失败,收件人:{}", to, e);}}
}
5. 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={EmailServiceApplication.class, EmailServiceTest.class})
public class EmailServiceTest {@Resourceprivate EmailService emailService;@Testpublic void test(){emailService.sendSimpleMail("1191986647@qq.com","测试","测试");}
}

二、邮箱验证实现
实现验证需要使用redis,本章节不介绍如何使用redis,请自行搭建
1.添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- jedis连接 -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>
2. 添加配置
yaml配置
spring:redis:host: localhost # redis地址port: 6379database: 0 password: 123456 # 密码,无密码可不填
序列化配置,新建一个config包,并添加RedisConfig类
@Configuration
public class RedisConfig {@Beanpublic StringRedisTemplate redisTemplate(RedisConnectionFactory factory) {StringRedisTemplate template = new StringRedisTemplate(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());return template;}
}
3.添加controller
@RestController
@RequestMapping("/api")
public class VerificationController {@Autowiredprivate EmailService emailService;@Autowiredprivate StringRedisTemplate redisTemplate;@PostMapping("/sendCode")public String sendCode(@RequestParam String email) {// 生成验证码String code = String.valueOf((int)((Math.random() * 9 + 1) * 100000));emailService.sendHtmlMail(email, "【邮箱验证码】欢迎使用xxx系统", "<p>您的邮箱验证码是:<p><p style=\" font-weight: bold;text-align: center;color: red;\">"+code+"</p>" );// 存储验证码到 Redis,设置过期时间为 5 分钟ValueOperations<String, String> ops = redisTemplate.opsForValue();redisTemplate.delete(email);ops.set(email, code, 5, TimeUnit.MINUTES);return "验证码已发送";}@PostMapping("/verifyCode")public String verifyCode(@RequestParam String email, @RequestParam String code) {// 从 Redis 获取验证码ValueOperations<String, String> ops = redisTemplate.opsForValue();String storedCode = ops.get(email);if (storedCode != null && storedCode.equals(code)) {redisTemplate.delete(email);return "邮箱验证成功";} else {return "验证码错误或者已失效";}}
}
4. 测试
发送


验证


相关文章:
基于spring boot实现邮箱发送和邮箱验证
目录 一、邮箱发送实现1. 开通邮箱服务2. 添加邮箱依赖3.添加配置4.添加邮箱通用类5. 测试类 二、邮箱验证实现1.添加依赖2. 添加配置3.添加controller4. 测试 项目地址: https://gitee.com/nssnail/springboot-email 一、邮箱发送实现 1. 开通邮箱服务 使用qq邮箱、163邮箱都…...
华清作业day56
SQLite特性: 零配置一无需安装和管理配置;储存在单一磁盘文件中的一个完整的数据库;数据库文件可以在不同字节顺序的机器间自由共享;支持数据库大小至2TB;足够小,全部源码大致3万行c代码,250KB…...
【FPGA】VHDL:八段码到8421BCD码转换电路
目录 EDA设计基础练习题 : 实验要求如下: 代码 八段码到8421BCD码转换电路 8421BCD码到八段码转换电路 八段码到8421BCD~运行结果展示 8421BCD转八段码~运行结果展示 特别注意 软件:Quartus II 13.0 (64-bit) 语言:VHDL E…...
docker安装、运行
1、安装 之前有docker的话,需要先卸载旧版本: sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装之前需要安装yum工具: sud…...
新型RedAlert勒索病毒针对VMWare ESXi服务器
前言 RedAlert勒索病毒又称为N13V勒索病毒,是一款2022年新型的勒索病毒,最早于2022年7月被首次曝光,主要针对Windows和Linux VMWare ESXi服务器进行加密攻击,到目前为止该勒索病毒黑客组织在其暗网网站上公布了一名受害者&#x…...
qt-C++笔记之判断一个QLabel上有没有load图片
qt-C笔记之判断一个QLabel上有没有load图片 code review! 在Qt框架中,QLabel是用来显示文本或者图片的一个控件。如果你想判断一个QLabel控件上是否加载了图片,你可以检查它的pixmap属性。pixmap属性会返回一个QPixmap对象,如果没有图片被加…...
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Menu组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Menu组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Menu组件 以垂直列表形式显示的菜单。 子组件 包含MenuItem、MenuItemGroup子组…...
vue三种路由守卫详解
在 Vue 中,可以通过路由守卫来实现路由鉴权。Vue 提供了三种路由守卫:全局前置守卫、全局解析守卫和组件内的守卫。 全局前置守卫 通过 router.beforeEach() 方法实现,可以在路由跳转之前进行权限判断。在这个守卫中,可以根据用…...
【Linux】线程概念和线程控制
线程概念 一、理解线程1. Linux中的线程2. 重新定义线程和进程3. 进程地址空间之页表4. 线程和进程切换5. 线程的优点6. 线程的缺点7. 线程异常8. 线程用途9. 线程和进程 二、线程控制1. pthread 线程库(1)pthread_create()(2)pth…...
maven创建webapp+Freemarker组件的实现
下载安装配置maven Maven官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘123云盘为您提供Maven最新版正式版官方版绿色版下载,Maven安卓版手机版apk免费下载安装到手机,支持电脑端一键快捷安装https://www.123pan.com/s/9QRqVv-TcUY.html链接为3.6.2-3.6.3的版本 下载解…...
Stable Diffusion 模型下载:Samaritan 3d Cartoon SDXL(撒玛利亚人 3d 卡通 SDXL)
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十...
Oracle系列之十:Oracle正则表达式
Oracle正则表达式 1. 基本语法2. POSIX字符类3. 正则表达式函数4. 常用正则表达式 正则表达式 (Regular expression) 是一种强大的文本处理工具,Oracle数据库自9i版本开始引入了正则表达式支持,可帮助开发者快速而准确地匹配、查找和替换字符串ÿ…...
php基础学习之运算符(重点在连接符和错误抑制符)
运算符总结 在各种编程语言中,常用的运算符号有这三大类: 算术运算符:,-,*,/,%位运算符:&,|,^,<<,>>赋值运算符&…...
【CC工具箱1.2.0】更新_免费无套路,60+个工具,原码放出
CC工具箱目前已经更新到1.2.0版本,完全免费无套路。 适用版本ArcGIS Pro 3.0及以上。 欢迎大家使用,反馈bug,以及提出需求和意见,时间和能力允许的话我会尽量满足要求。 如有关于工具的使用问题和需求建议,可以加下…...
Java 将TXT文本文件转换为PDF文件
与TXT文本文件,PDF文件更加专业也更适合传输,常用于正式报告、简历、合同等场合。项目中如果有使用Java将TXT文本文件转为PDF文件的需求,可以查看本文中介绍的免费实现方法。 免费Java PDF库 本文介绍的方法需要用到Free Spire.PDF for Java…...
Sketch 99.1 for macOS
Sketch 99.1 for macOS 概述 这个程序是对矢量绘图的创新性和焕然一新的看法。它特意采用了极简主义的设计,基于一个大小无限、图层自由的绘图空间,没有调色板、面板、菜单、窗口和控件。 此外,它提供了强大的矢量绘图和文本工具,…...
Apache 神禹(shenyu)源码阅读(一)——Admin向Gateway的数据同步(Admin端)
源码版本:2.6.1 单机源码启动项目 启动教程:社区新人开发者启动及开发防踩坑指南 源码阅读 前言 开了个新坑,也是第一次阅读大型项目源码,写文章记录。 在写文章前,已经跑了 Divide 插件体验了一下(体…...
Prompt Tuning:深度解读一种新的微调范式
阅读该博客,您将系统地掌握如下知识点: 什么是预训练语言模型? 什么是prompt?为什么要引入prompt?相比传统fine-tuning有什么优势? 自20年底开始,prompt的发展历程,哪些经典的代表…...
Unity3d Shader篇(五)— Phong片元高光反射着色器
文章目录 前言一、Phong片元高光反射着色器是什么?1. Phong片元高光反射着色器的工作原理2. Phong片元高光反射着色器的优缺点优点缺点 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数 三、效果四、总…...
sql求解连续两个以上的空座位
Q:查找电影院所有连续可用的座位。 返回按 seat_id 升序排序 的结果表。 测试用例的生成使得两个以上的座位连续可用。 结果表格式如下所示。 A:我们首先找出所有的空座位:1,3,4,5 按照seat_id排序(上面已…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
