前言:
本次项目基于springboot 3.x
jdk为17
Maven版本为:3.8.1
IDEA版本为:2023.3.x
1、在qq邮箱进行相关的设置
第一步:我们进入qq邮箱的右上角有一个账号与安全设置:我们点进去
第二步:点进去后来到这个页面:选择安全设置,在最下面有这个服务,我们需要开启这个服务,然后生成一个授权码,生成的授权码记得保存下来,这个很有用处
2、编写java代码
紧接着在我们的项目工程中就可以编写java代码了
2.1、首先我们先引入相关的maven依赖包
首先在我们的pom.xml文件中引入关于email的依赖包
<!-- email邮箱验证-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2.2、随后配置yml文件,进行相关的配置
spring:
mail:
host: smtp.qq.com # 指定邮件服务器的主机名,这里默认是smtp.qq.com,表示使用的是腾讯的SMTP服务器。
port: 587 # 456也行
username: "你的email" # xxxx@qq.com 这里是发送者
password: "授权码" # 这里就是我前面提到的授权码了
properties: # 其他配置
mail:
smtp:
socketFactoryClass: javax.net.ssl.SSLSocketFactory # 指定SSL Socket工厂类,用于创建加密的邮件连接。
auto: true # 设置为true表示启用自动连接。
starttls: # 配置STARTTLS加密连接
enable: true # 设置为true表示启用STARTTLS。
required: true # 设置为true表示STARTTLS是必需的,如果不可用,则会抛出异常。
default-encoding: UTF-8 # 设置邮件内容的默认编码格式为UTF-8 默认就是UTF-8
上面就是配置基本信息了,根据你的需求可以自行更改
2.3、创建Email工具类
我们需要将业务代码整合到一个工具类(EmailSendUtils )中进行编码,我们创建一个专门用于发送email邮箱验证码的类,里面涵盖了发送的步骤,以及随机生成6位字母和数字的验证码。
上代码:
package com.sxy.recordnetwork.Utils;
import com.sxy.recordnetwork.enumeration.Constants;
import org.aspectj.apache.bcel.classfile.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import javax.swing.*;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
/**
* 发送邮箱验证码工具类
* Created by sxy on 2024/3/11.
*/
@Service
public class EmailSendUtils {
// 注入JavaMailSender接口
@Autowired
private JavaMailSender mailSender;
// 集成redis进行验证码的缓存
@Autowired
private RedisTemplate redisTemplate;
// 通过value注解得到配置文件中发送者的邮箱
@Value("${spring.mail.username}")
private String userName;// 用户发送者
// 邮箱验证码 定义为StringBuilder对于增删改操作有优势
private final StringBuilder EMAIL_CODE = new StringBuilder();
// 创建一个发送邮箱验证的方法
public void sendVerificationEmail(String to){
try{
// 定义email信息格式
SimpleMailMessage message = new SimpleMailMessage();
// 调用生成6位数字和字母的方法,生成验证码,该方法在下面定义好了
generateRandomCode();
// 设置发件人
message.setFrom(userName);
// 接收者邮箱,为调用本方法传入的接收者的邮箱xxx@qq.com
message.setTo(to);
// 邮件主题
message.setSubject(Constants.EMAIL_TITLE.getValue());
// 邮件内容 设置的邮件内容,这里我使用了常量类字符串,加上验证码,再加上常量类字符串
message.setText(Constants.EMAIL_MESSAGE.getValue()+EMAIL_CODE+Constants.EMAIL_OUTTIME_TEN.getValue());
// 开始发送
mailSender.send(message);
}catch (Exception e){
e.printStackTrace();
}finally{
// 发送完了之后,将EMAIL_CODE设置为空
EMAIL_CODE.setLength(0);
}
}
/**
* 随机生成6位字母加数字组合的验证码
* @return
*/
public void generateRandomCode(){
// 字母和数字组合
String str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// 拆分每一个字符放到数组中
String[] newStr = str.split("");
// 循环随机生成6为数字和字母组合
for (int i = 0; i < 6; i++){
// 通过循环6次,为stringBuilder追加内容,内容为随机数✖62,取整
EMAIL_CODE.append(newStr[(int)(Math.random() * 62)]);
}
//TODO 这里存储的key如果多个用户同时发送的话会覆盖key,就会导致第一个人的验证码被覆盖
// 存入Redis中并设置时长为2分钟
redisTemplate.opsForValue().set(Constants.EMAIL_CODE.getValue(), EMAIL_CODE,120, TimeUnit.SECONDS);
}
}
这里我声明了一个自定义异常类BaseException去继承RuntimeException这个类
package com.sxy.recordnetwork.Exception;
public class BaseException extends RuntimeException{
public BaseException( String msg) {
super(msg);
}
}
然后我们再创建验证码相关的异常类信息去继承这个就可以了
package com.sxy.recordnetwork.Exception.Son;
import com.sxy.recordnetwork.Exception.BaseException;
/**
* 邮箱验证码异常
*/
public class EmailCodeException extends BaseException {
public EmailCodeException(String msg) {
super(msg);
}
}
注意:这个地方可以看我往期的文章,有写全局异常处理器的使用方法
2.4、在Controller层编写接口调用sendVerificationEmail接口参数为接收者邮箱
package com.sxy.recordnetwork.controller;
import com.sxy.recordnetwork.DTO.USER.UserDtoEmailLogin;
import com.sxy.recordnetwork.DTO.USER.UserDtoPhoneLogin;
import com.sxy.recordnetwork.Exception.Son.EmailCodeException;
import com.sxy.recordnetwork.Utils.EmailSendUtils;
import com.sxy.recordnetwork.enumeration.Constants;
import com.sxy.recordnetwork.common.Result;
import com.sxy.recordnetwork.common.SendCode;
import com.sxy.recordnetwork.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* 第三方短信验证以及其他相关操作
*/
@RequestMapping("/code")
@RestController
@Slf4j
public class CodeController {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private UserService userService;
@Autowired
private EmailSendUtils emailSendUtils;
/**
* 邮箱验证码发送
* @param receiveEmail
* @return
*/
@GetMapping("/email/sendEmail")
public Result sendSimpleMail(@RequestParam(value = "receiveEmail") String receiveEmail) {
emailSendUtils.sendVerificationEmail(receiveEmail);
return Result.success(Constants.EMAIL_SEND_SUCCESS.getValue(),null);
}
/**
* qq邮箱验证登录
* @param emailLogin
* @return
*/
@PostMapping("/emailLogin")
public Result emailLogin(@RequestBody UserDtoEmailLogin emailLogin){
// 查看是否存在这一个qq邮箱
if(!userService.getEmail(emailLogin.getEmail())){
throw new EmailCodeException(Constants.NOT_EXIST_EMAIL.getValue());
}
// 从redis数据库中获取email_code验证码用来做判断
String email_code = (String) redisTemplate.opsForValue().get(Constants.EMAIL_CODE.getValue());
if(!emailLogin.getCode().equals(email_code)){
throw new EmailCodeException(Constants.EMAIL_CODE_ERROR.getValue());
}
// 登陆成功 清楚本地redis邮箱验证码
redisTemplate.delete(Constants.EMAIL_CODE.getValue());
return Result.success(Constants.LOGIN.getValue(),userService.EmailLogin(emailLogin.getEmail()));
}
}
2.5、声明的常量类:
因为项目中用到了大量的字符串,所以我这里就写了常量类,来代替字符串
package com.sxy.recordnetwork.enumeration;
import lombok.Getter;
/**
* 枚举类,常量
*/
@Getter
public enum Constants {
EMAIL_SEND_SUCCESS("皇上,臣妾已为您发送了邮箱哦!"),//邮件发送成功,请查收!
EMAIL_MESSAGE("您的QQ邮箱验证码为:"),
EMAIL_OUTTIME_TEN(",请在2分钟内完成验证"),
EMAIL_TITLE("QQ邮箱验证码"),// 邮箱验证码发送的标题
EMAIL_CODE("email_code"),// 邮箱验证码redis的key
EMAIL_CODE_ERROR("皇上,请核实您的QQ邮箱验证码是否正确!"),// qq邮箱验证码错误
NOT_EXIST_EMAIL("皇上,臣妾没有找到您的QQ邮箱,请确认是否正确!");// 邮箱不存在
private final String Value;
Constants(String value){
this.Value = value;
}
}
好了,到这里就结束了,这样的话一个qq邮箱验证码就通过发送了