1、准备工作
?
- 我们需要前往我们的QQ邮箱开启相关功能,登录QQ邮箱后,点击进入 设置。
?
????????在账户在一栏中,我们可以找到这个界面,然后点击开启?POP3/SMTP服务?,他们会让我们用QQ的密保手机发送一条短信,我们照着即可。
? ? ? ? ?验证成功之后,会获得一个授权码,当我们在第三方客户端登录QQ邮箱时,这个授权码就是我们邮箱的登录密码。
? ? ? ? ?将授权码复制之后,点击确定,我们可以看到 POP3/SMTP服务?已经开启
? ? ? ? 到此,我们的QQ邮箱方面的准备工作就完成了。?
<!--qq邮箱-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.5.6</version>
</dependency>
? ? ? ? 在?application.properties? 配置文件中写入一下代码
# 配置邮箱用户名
spring.mail.username= 你的QQ邮箱号码
# 配置申请到的授权码
spring.mail.password=刚才短信申请到的授权码
# 配置 smtp 服务器地址
spring.mail.host=smtp.qq.com
#
spring.mail.properties.mail.smtp.ssl.enable=true
# 配置邮件编码
spring.mail.default-encoding=UTF-8
- ?话不多说,先测试一波,看我们的准备工作是否准备成功
? ? ? ? ?在spring boot的测试类中,通过 JavaMailSenderImpl?这个对象的 send 方法发送邮件
@SpringBootTest
class SpringbootLoginDemo1ApplicationTests {
@Autowired
JavaMailSenderImpl mailSender; //自动注入对象
@Test
void contextLoads() {
//一个简单的邮件发送
SimpleMailMessage mailMessage = new SimpleMailMessage(); //创建一个邮件信息
System.out.println("当前时间" + new Date());
mailMessage.setSubject("你好啊"); //邮件的主题
mailMessage.setText("我是你新学习的Spring Boot邮件发送的知识");//邮件的内容
mailMessage.setTo("发送者的邮箱"); //发送者的邮箱
mailMessage.setFrom("接受者的邮箱"); //接收者的邮箱
//我这里发送者和接收者都填写的是自己的邮箱
mailSender.send(mailMessage); //发送邮件
}
}
? ? ? ? 点击运行的小按钮,让我们来测试一下吧。
? ? ? ? yes,运行成功,成功收到邮件!!!?
2、编写发送邮件的接口?
? ? ? ? 在接口类上定义一个HashMap,用来存储。
private Map<String, Object> resultMap = new HashMap<>();
?
- 我们正在编写发送邮件的接口,那么首先,我们想通过邮件来发送什么信息呢?肯定是验证码啊,所以我们需要写一个方法,来生产我们的验证码。如下:
private String VerifyCode(int n){ // n的作用就是指定验证码的长度
Random r = new Random(); //创建一个生成随机数的对象
StringBuffer sb =new StringBuffer(); // StringBuffer是一种可变的字符串,长度、内容都可变
for(int i = 0;i < n;i ++){ //一个for循环
int ran1 = r.nextInt(10);//生成一个大于0小于10的随机数
sb.append(String.valueOf(ran1));//调用append方法将我们生成的随机数存放到StringBuffer对象sb中
}
System.out.println(sb);
return sb.toString(); //将sb以String的形式输出
}
? ? ? ? 这样,我们的验证码生成这一功能就完成了,但是大家想一想,验证码肯定是要进行保存,然后可以在注册时将我们后台保存的验证码与用户输入的验证码进行比对,从而判定用户输入的验证码是否正确,并且验证码也需要设置它的过期时间,这样才会更加合理。
//保存验证码和时间
private void saveCode(String code){
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置时间的格式
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, 5);
String currentTime = sf.format(c.getTime());// 生成5分钟后时间,用户校验是否过期
String hash = Md5Util.code(code);//生成MD5值 //对验证码进行md5加密
resultMap.put("hash", hash); //将加密后的验证码发到HashMap中
resultMap.put("tamp", currentTime); //将验证码保存的时间信息发到HashMap中
}
? ? ? ? 相比大家应该已经注意到了,上面代码的?Md5Util 这个md5加密的工具类,我们并没有写,使用我们需要创建一个util包,用以存放我们的工具类,然后将?Md5Util? 编写好。我就讲我们代码放在下面了。
public class Md5Util {
/**
* MD5加密类
*
* @param str 要加密的字符串
* @return 加密后的字符串
*/
public static String code(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte[] byteDigest = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < byteDigest.length; offset++) {
i = byteDigest[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
//32位加密
return buf.toString();
// 16位的加密
//return buf.toString().substring(8, 24);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
@PostMapping("/sendEmail")
@ApiOperation(value = "发送邮件验证码,前端需传email变量,并判断email是否是一个正确的邮箱号码")
public Result<?> sendEmail(@RequestParam("userEmail") @Validated String userEmail) {
SimpleMailMessage message = new SimpleMailMessage();
String code = VerifyCode(6); //随机数生成6位验证码
message.setFrom(sender); //指定发送者的邮箱
message.setTo(userEmail); //接受者的邮箱,由用户输入
message.setSubject("验证码");// 邮件标题
message.setText("【验证码】你的验证码为:"+code+",有效时间为5分钟(若不是本人操作,可忽略该条邮件)");// 内容
try {
javaMailSender.send(message); //发送邮件
logger.info("文本邮件发送成功!");
saveCode(code); //邮件发送成功,将验证码保存
return Result.success();
}catch (MailSendException e){
logger.error("目标邮箱不存在"); //抛出异常,用户邮箱不存在
return Result.error(Constants.CODE_400 , "目标邮箱不存在");
} catch (Exception e) {
logger.error("文本邮件发送异常!", e);
return Result.error(Constants.CODE_500 , "邮件发送异常"); //抛出异常,邮件发送失败
}
}
?
?
? ? ? ? nice,测试成功?
3、注册接口编写
? ? ? ? ?在编写一个接口前,我们先想一想我们需要哪些参数。既然时注册接口,那么我们应该需要注册用户的一些注册信息以及通过邮件发送的验证码。
@PostMapping("/register")
@ApiOperation(value = "用户注册")
public Result<?> register(@RequestBody @Validated User user, @RequestParam String code){
//@Validated验证数据是否合法
user.setUserRole("vip1");//默认创建的都是普通用户
if (StrUtil.isBlank(code)){
return Result.error(Constants.CODE_400, "验证码为空");
}
User res = userService.getUserByUserNum(user.getUserNum());
if (res != null) {
return Result.error("-1", "账号重复");
}
System.out.println(user);
if (StrUtil.isBlank(user.getUserNum())){
return Result.error(Constants.CODE_400, "用户学号为空");
}
String requestHash = resultMap.get("hash").toString();//得到resultMap中的验证码
String tamp = resultMap.get("tamp").toString(); //得到resultMap中的验证码创建时间
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//当前时间对象
Calendar c = Calendar.getInstance();//得到当前时间
System.out.println("当前的时间:::" + c);
String currentTime = sf.format(c.getTime());//调用format方法将日期转换为文本
System.out.println("将当前的时间转换为文本后的时间:currentTime::" + currentTime);
System.out.println( " 时间比较 "+ tamp.compareTo(currentTime));
if (tamp.compareTo(currentTime) > 0) { //调用compareTo方法,比较字符串
String hash = Md5Util.code(code);//生成MD5值
if (hash.equalsIgnoreCase(requestHash)){
//校验成功
User userInfo = User.builder()
.id(user.getId())
.userName(user.getUserName())
.userNum(user.getUserNum())
.userPassword(new BCryptPasswordEncoder().encode(user.getUserPassword()))//加密
.userInfo(user.getUserInfo())
.userEmail(user.getUserEmail())
.userPhone(user.getUserPhone())
.userRole(user.getUserRole())
.build();
userService.insert(userInfo);
return Result.success();
}else {
//验证码不正确,校验失败
return Result.error(Constants.CODE_400, "验证码错误");
}
} else {
// 超时
return Result.error(Constants.CODE_600, "验证码超时");
}
}
- 这样,我们的一个邮件发送跟注册接口就完成了,接下来就是验证环节了。
接受到邮件,获取验证码。?
填写验证码以及用户的注册信息。?
?
?
?结果返回为成功!!!
接下来就让我们去数据库中看看我们刚刚注册的用户是否存在吧。
yes,成功实现。
好了,话不多说,下班了。?
|