发送邮箱验证码【spring boot】

news2024/12/28 18:42:55

⭐前言⭐

※※※大家好!我是同学〖森〗,一名计算机爱好者,今天让我们进入学习模式。若有错误,请多多指教。更多有趣的代码请移步Gitee
👍 点赞 ⭐ 收藏 📝留言 都是我创作的最大的动力!

1. 思维导图

发送邮箱验证码的思维导图

2. 获取邮箱授权码

2.1 1. 开启POP3/SMTP服务

  • 登录QQ邮箱 --> 设置 --> 账户

在这里插入图片描述

  • 向下滑动滚动条,找到账户页面下方的 POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务一栏,点击管理服务
    在这里插入图片描述
  • 第一次会让你绑定手机后再进行操作 按要求进行操作就好;
  • 进入安全模式,点击生成授权码;

在这里插入图片描述

  • 短信验证
    在这里插入图片描述
  • 验证成功会生成授权码
    在这里插入图片描述

一定要复制授权码,并保存到一个地方;别问我怎么知道的;

3. 创建 Spring Boot 项目

3.1 引入依赖

<!--   发送邮件     -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

添加依赖后一定要重新 ReLoad 一下;

在这里插入图片描述

3.2 配置application.yml文件

Spring:
  # 邮箱基本配置
  mail:
    # 配置 smtp 服务主机地址
    # qq 邮箱     smtp.qq.com    端口号 465 或 587
    # sina       smtp.sina.com
    # aliyun     smtp.aliyun.com
    # 163        smtp.163.com   端口号 465 或 994
    host: smtp.qq.com
    # 发送者邮箱
    username: xxxxxxxx@qq.com
    # 在邮箱内申请的授权码
    password: xttfwlhoyguxbacg
    # 端口号
    port: 587
    # 默认的邮件编码为UTF-8
    default-encoding: UTF-8
    # 其他参数
    properties:
      mail:
          # 配置SSL 加密工厂
        smtp:
          ssl:
            # 本地测试, 先放开ssl
            enable: false
            required: false
          #开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误
        debug: true
  • 这里注意一下port 465有时会报错,换一个就好;
  • 把username 改成自己的QQ邮箱号,把password 换成刚刚我们申请的授权码(不是QQ密码哟)

3.3 实体类ToEmail

package com.example.sendemail.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

/**
 * @version IntelliJ IDEA || java version 11.
 * @Author: Oliver
 * @Description: 邮箱验证码实体类
 * @Date: 2023-07-02
 * @Time: 14:21
 */
@Data
@AllArgsConstructor //生成一个包含所有类字段的构造函数
public class ToEmail implements Serializable {
    /**
     *  邮件接受方
     */
    private String tos;
    /**
     *      邮件主题
     */
    private String subject;

    /**
     * 邮件内容
     */
    private String content;
}

3.4 生成6位验证码

package com.example.sendemail.utils;

import java.security.SecureRandom;
import java.util.Random;

/**
 * @version IntelliJ IDEA || java version 11.
 * @Author: Oliver
 * @Description: 生成验证码工具类
 * @Date: 2023-07-02
 * @Time: 14:35
 */
public class VerCodeGenerateUtil {
    /**
     * 验证码包含的字段
     */
    private static final String SYMBOLS = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ";
    private static final Random RAND = new SecureRandom();

    /**
     * 生成 6 位数的随机数字
     * @return {@link String 验证码}
     */
    public static String generateVerCode(){
        char[] code = new char[6];
        for(int i = 0; i < code.length; i++) {
            code[i] = SYMBOLS.charAt(RAND.nextInt(SYMBOLS.length()));
            //  RAND.nextInt(SYMBOLS.length()) 生成一个随机的索引值;
            //  RAND.nextInt(n) 生成一个0到n-1之间的随机整数;
        }
        return new String(code);
    }
}

SecureRandom() 和 Random()

  • java.util.Random是一个伪随机数生成器,它使用线性同余算法生成随机数。
    • 这种算法虽然能够快速生成随机数,但是它的随机性并不够强,因此不适用于安全相关的场景。在Java中,使用java.util.Random生成的随机数只能用于一些非安全性的场景,例如模拟数据或游戏等。
  • java.security.SecureRandom是一个强随机数生成器,它使用安全的随机数生成算法生成随机数。
    • 这种算法的随机性更加强大和安全,可以用于安全相关的场景,例如密码学或安全通信等。在Java中,使用java.security.SecureRandom生成的随机数可以用于安全性要求更高的场景。

3.5 邮件服务器类MailService

package com.example.sendemail.service;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;


import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.File;
import java.util.Date;

@Service
public class MailService {
    /**
     * 注入邮件工具类
     */
    @Resource
    private JavaMailSenderImpl javaMailSender;

    @Value("${spring.mail.username}")
    private String sendMailer;

    /**
     * 检测邮件信息类
     * @param receiveEmail 接收者
     * @param subject  主题
     * @param emailMsg 内容
     */
    private void checkMail(String receiveEmail, String subject, String emailMsg){
        //  StringUtils 需要引入  commons-lang3 依赖
        //  可以用 receiveEmail == null || receiveEmail.isEmpty() 来代替
        if(StringUtils.isEmpty(receiveEmail)) {
            throw new RuntimeException("邮件收件人不能为空");
        }
        if(StringUtils.isEmpty(subject)) {
            throw new RuntimeException("邮件主题不能为空");
        }
        if(StringUtils.isEmpty(emailMsg)) {
            throw new RuntimeException("邮件内容不能为空");
        }
    }
    
    /**
     * 发送纯文本邮件
     * @param receiveEmail 接收者
     * @param subject  主题
     * @param emailMsg 内容
     */
    public Boolean sendTextMail(String receiveEmail, String subject, String emailMsg) {
        // 参数检查
        checkMail(receiveEmail, subject, emailMsg);
        try {
            // true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(), true);
            // 邮件发件人
            mimeMessageHelper.setFrom(sendMailer);
            // 邮件收件人
            mimeMessageHelper.setTo(receiveEmail.split(","));
            // 邮件主题
            mimeMessageHelper.setSubject(subject);
            // 邮件内容
            mimeMessageHelper.setText(emailMsg);
            // 邮件发送时间
            mimeMessageHelper.setSentDate(new Date());
    
            // 发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            System.out.println("发送邮件成功: " + sendMailer + "-->" + receiveEmail);
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
            System.out.println("发送邮件失败: " + e.getMessage());
            return false;
        }
    }
}

3.6 EmailController

package com.example.sendemail.controller;

import com.example.sendemail.common.AjaxResult;
import com.example.sendemail.entity.ToEmail;
import com.example.sendemail.service.MailService;
import com.example.sendemail.utils.VerCodeGenerateUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @version IntelliJ IDEA || java version 11.
 * @Author: Oliver
 * @Description: 邮箱验证码
 * @Date: 2023-07-02
 * @Time: 15:06
 */
@RestController
@RequestMapping("/email")
public class EmailController {

    @Resource
    private MailService mailService;

    @RequestMapping("/sendEmail")
    public AjaxResult sendEmail(ToEmail toEmail, HttpServletRequest request) {
        if(toEmail == null || toEmail.getTos() == null ) {
            return AjaxResult.fail(-1, "参数错误!");
        }
        toEmail.setSubject("你本次的验证码是");
        // 获取验证码
        String verCode = VerCodeGenerateUtil.generateVerCode();
        String content = "尊敬的xxx,您好:\n"
                + "\n本次请求的邮件验证码为:" + verCode + ",本验证码 5 分钟内效,请及时输入。(请勿泄露此验证码)\n"
                + "\n如非本人操作,请忽略该邮件。\n(这是一封通过自动发送的邮件,请不要直接回复)";
        toEmail.setContent(content);

        Boolean check = mailService.sendTextMail(toEmail.getTos(), toEmail.getSubject(), toEmail.getContent());
        if(check) {
            return AjaxResult.success(200, "发送成功");
        } else {
            return AjaxResult.fail(-2, "发送失败");
        }

    }
}
  • AjaxResult 统一格式返回类,包含 状态码 code , 状态码描述信息 msg, 返回的数据 data;

4 功能测试

使用 PostMan测试

在这里插入图片描述

其中 tos 的 val 值是要收件人的邮箱;

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/710208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis6之穿透、击穿、雪崩

大量的高并发的请求打在Redis上&#xff0c;但是发现Redis中并没有请求的数据&#xff0c;redis的命令率降低&#xff0c;所以这些请求就只能直接打在DB&#xff08;数据库服务器&#xff09;上&#xff0c;在大量的高并发的请求下就会导致DB直接卡死、宕机。 缓存穿透 当客户端…

一例Phorpiex僵尸网络样本分析

本文主要分析Phorpiex僵尸网络的一个变种&#xff0c;该样本通常NSIS打包&#xff0c;能够检测虚拟机和沙箱。病毒本体伪装为一个文件夹&#xff0c;通过U盘来传播&#xff0c;会隐藏系统中各盘符根目录下的文件夹&#xff0c;创建同名的lnk文件&#xff0c;诱导用户点击。 病…

TF卡/U盘系统备份

Jetson nano使用TF卡/U盘来装载系统&#xff0c;如果TF卡/U盘丢失或者损坏&#xff0c;那么Jetson nano上的数据都会丢失&#xff0c;所以一定要备份好TF卡/U盘。这篇文章可以帮你备份你的Jetson nano系统。主要内容为备份TF卡/U盘&#xff0c;制作Jetson nano系统镜像以及在需…

Java——《面试题——ElasticSearch篇》

目录 1、谈谈分词与倒排索引的原理 2、说说分段存储的思想 3、谈谈你对段合并的策略思想的认识 4、了解文本相似度 TF-IDF吗 5、能说说ElasticSearch 写索引的逻辑吗&#xff1f; 6、熟悉ElasticSearch 集群中搜索数据的过程吗&#xff1f; 7、了解ElasticSearch 深翻页的…

vsCode 创建新java项目(创建一个新java项目测试方法)

VSCODE环境配置-java之项目建立&#xff0c;非常适合刚准备使用VSCODE开发JAVA的人_vscode创建java项目_rainmenzhao的博客-CSDN博客 1 按 ctrl shift p 2 输入 create Java project 3 选 no build tools 4 选择 一个文件夹 存放 之后要 新建的文件 5 选完之后 自动返回主页…

获得Jolt 大奖的《持续交付》作者David Farley又一新作《现代软件工程》

戴维 法利 (David Farley) 是持续交付的先驱、思想领袖&#xff0c; 也是持续交付、 DevOps、 测试驱动开发和软件开发领域的专家。 从现代计算的早期开始&#xff0c;戴维曾担任过程序员、软件工程师、系统架构师和成功团 队的领导者&#xff0c;他掌握了计算机和软件开发的基…

ES基本操作(postman篇)

关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。 需要注意的是&#xff1a;type的概念在es7.0之后已经删除了。 以下仅做刚入门学习…

矩阵对角线元素的和:揭秘数学之美,解密矩阵的隐秘密码

本篇博客会讲解力扣“1572. 矩阵对角线元素的和”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a;主对角线的下标满足i j&#xff0c;副对角线的下标满足i j size - 1&#xff0c;故只需要使用i遍历每一行&#xff0c;把(i, i)和(i, size - i - 1)的元素求和…

探索 Spring Boot 项目全过程

文章目录 &#x1f387;前言1.Spring Boot 所需环境2.Spring Boot 项目创建2.1 安装插件2.2 创建新项目2.3 项目属性配置2.4添加依赖2.4 修改项目名称2.5 添加框架支持2.6 目录介绍 3.判断Spring Boot 创建项目是否成功&#x1f386;总结 &#x1f387;前言 在 Java 这个圈子&…

1. Except

文章目录 Except前言Except 语法Except 使用举例结合其他关键字使用EXCEPT with BETWEEN operatorExcept with IN operatorEXCEPT with LIKE operator 文章参考 Except 前言 SQL中&#xff0c;EXCEPT 操作用于检索存在于第一个表中的唯一记录&#xff0c;而不是两个表中共有的…

python3GUI--网速内存小工具By:PyQt5(附源码)

文章目录 一&#xff0e;前言二&#xff0e;预览1.主界面2.动图演示3.内存详细信息查看4.自定义界面 三&#xff0e;源代码1.tool_god_GUI.py2.tool_god_ui.py3.engine.py4.CWidgets.py 四&#xff0e;总结五&#xff0e;参考 一&#xff0e;前言 本次使用PyQt5进行开发一款网…

(并查集) 685. 冗余连接 II ——【Leetcode每日一题】

并查集基础 并查集&#xff08;Union-find Sets&#xff09;是一种非常精巧而实用的数据结构&#xff0c;它主要用于处理一些不相交集合的合并问题。一些常见的用途有求连通子图、求最小生成树的Kruskal算法和求最近公共祖先&#xff08;LCA&#xff09;等。 并查集的基本操作主…

MySQL 分库分表实战之ShardingSpare

文章目录 概要一、安装二、配置2.1、 通用配置2.2、 分片配置2.3、读写分离 三、演练3.1、读写分离3.2、分库分表3.3、分库分表读写分离 4、总结 概要 市面上MySQL分库分表中间件还是很多的&#xff0c;主要分为两大类&#xff1a;应用层依赖类中间件&#xff08;比如sharding…

【学习周报】

最近看过的几篇论文里&#xff0c;VALOR和InstructBLIP模型使用了cross-attention机制&#xff0c;以这两篇论文为基础着重学习cross-attention相关的代码和思路。 学习内容&#xff1a; cross-attention机制学习lstm与transformer 学习时间&#xff1a; 6.26 ~ 7.1 学习笔记…

Linux--重定向:> >> <

输出重定向&#xff1a;> a.如果目标文件不存在&#xff0c;则创建文件。反之 b.本来应该显示到显示器的内容&#xff0c;被写入到了文件中 示例&#xff1a; 追加重定向: >> 示例&#xff1a; 输入重定向&#xff1a;< 本来应该从键盘中读取的内容&#xff0c;变…

分布式锁的实现方案(免费gpt4分享)

1.1基于数据库 有两个方案&#xff1a;依赖数据库排他锁以及表主键的唯一。 依赖数据库排他锁&#xff1a; 在查询语句后面增加for update&#xff0c;数据库会在查询过程中给数据库表增加排他锁 (注意&#xff1a; InnoDB 引擎在加锁的时候&#xff0c;只有通过索引进行检索…

SpringBoot扩展机制

启动生命周期 一.Spring boot初始化器扩展 package com.lx.conmon.extend.intializer;import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext;/*** Spring boot初始化器扩展* author liu we…

AIPRM for ChatGPT 提示词模板扩展工具实践

&#xff08;1&#xff09;基本介绍 AIPRM for ChatGPT是一个Chrome浏览器扩展程序&#xff0c;基于Chromium内核开发的浏览器都可以使用该扩展&#xff0c;比如微软的Edge浏览器等。 在AIPRM的帮助下&#xff0c;我们可以在ChatGPT中一键使用各种专门为网站SEO、SaaS、营销、…

超详细,Python自动化测试 Allure报告参数化动态生成标题(实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 默认 allure 报告…

ubuntu安装openssh

Ubuntu安装openssh之后&#xff0c;然后在客户端安装winscp,然后就可以很方便的传输文件了 sudo apt install openssh-server sudo service ssh status sudo service ssh start sudo service ssh restart