文章目录

  • 实体类
  • controller:
  • 前端页面(Vue)
  • 生成校验验证码service:
  • ftl模板:
  • 真正发送邮箱的EmailConfigService

实体类

验证码pojo

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("verification_code")
public class VerificationCode implements Serializable {@TableId//@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String code;/** 使用场景,自己定义  */private String scenes;/** true 为有效,false 为无效,验证时状态+时间+具体的邮箱或者手机号 */private Boolean status = true;/** 类型 :phone 和 email */private String type;/** 具体的phone与email */private String value;/** 创建日期 */@TableField(fill = FieldFill.INSERT)// @Column(name = "create_time")private Timestamp createTime;public VerificationCode(String code, String scenes, @NotBlank String type, @NotBlank String value) {this.code = code;this.scenes = scenes;this.type = type;this.value = value;}
}

邮箱配置pojo:


@Data
@TableName("email_config")
public class EmailConfig implements Serializable {/** ID */@TableId//@GeneratedValue(strategy = GenerationType.IDENTITY)// @Column(name = "id")private Long id;/** 收件人 */// @Column(name = "from_user")private String fromUser;/** 邮件服务器SMTP地址 */// @Column(name = "host")private String host;/** 密码 */// @Column(name = "pass")private String pass;/** 端口 */// @Column(name = "port")private String port;/** 发件者用户名 */// @Column(name = "user")private String user;public void copy(EmailConfig source) {BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));}
}

sql:

DROP TABLE IF EXISTS `verification_code`;
CREATE TABLE `verification_code` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '验证码',`create_time` datetime DEFAULT NULL COMMENT '创建日期',`status` bit(1) DEFAULT NULL COMMENT '状态:1有效、0过期',`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '验证码类型:email或者短信',`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '接收邮箱或者手机号码',`scenes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '业务名称:如重置邮箱、重置密码等',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='验证码';
DROP TABLE IF EXISTS `email_config`;
CREATE TABLE `email_config` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`from_user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '收件人',`host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮件服务器SMTP地址',`pass` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '密码',`port` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '端口',`user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '发件者用户名',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邮箱配置';

邮箱vo

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailVo {/** 收件人,支持多个收件人 */@NotEmptyprivate List<String> tos;@NotBlankprivate String subject;@NotBlankprivate String content;
}

controller:

@RestController
@RequestMapping("/api/code")
@Api(tags = "工具:验证码管理")
public class VerificationCodeController {@PostMapping(value = "/resetEmail")@ApiOperation("重置邮箱,发送验证码")public ResponseEntity<Object> resetEmail(@RequestBody VerificationCode code) throws Exception {code.setScenes(YshopConstant.RESET_MAIL);EmailVo emailVo = verificationCodeService.sendEmail(code);emailService.send(emailVo, emailService.find());return new ResponseEntity<>(HttpStatus.OK);}

前端页面(Vue)

<template><div style="display: inline-block;"><el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="title" append-to-body width="475px" @close="cancel"><el-form ref="form" :model="form" :rules="rules" size="small" label-width="88px"><el-form-item label="新邮箱" prop="email"><el-input v-model="form.email" auto-complete="on" style="width: 200px;" /><el-button :loading="codeLoading" :disabled="isDisabled" size="small" @click="sendCode">{{ buttonName }}</el-button></el-form-item><el-form-item label="验证码" prop="code"><el-input v-model="form.code" style="width: 320px;" /></el-form-item><el-form-item label="当前密码" prop="pass"><el-input v-model="form.pass" type="password" style="width: 320px;" /></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="text" @click="cancel">取消</el-button><el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button></div></el-dialog></div>
</template><script>
import store from '@/store'
import { validEmail } from '@/utils/validate'
import { updateEmail } from '@/api/system/user'
import { resetEmail } from '@/api/system/code'
export default {props: {email: {type: String,required: true}},data() {const validMail = (rule, value, callback) => {if (value === '' || value === null) {callback(new Error('新邮箱不能为空'))} else if (value === this.email) {callback(new Error('新邮箱不能与旧邮箱相同'))} else if (validEmail(value)) {callback()} else {callback(new Error('邮箱格式错误'))}}return {loading: false, dialog: false, title: '修改邮箱', form: { pass: '', email: '', code: '' },user: { email: '', password: '' }, codeLoading: false,codeData: { type: 'email', value: '' },buttonName: '获取验证码', isDisabled: false, time: 60,rules: {pass: [{ required: true, message: '当前密码不能为空', trigger: 'blur' }],email: [{ required: true, validator: validMail, trigger: 'blur' }],code: [{ required: true, message: '验证码不能为空', trigger: 'blur' }]}}},methods: {cancel() {this.resetForm()},sendCode() {if (this.form.email && this.form.email !== this.email) {this.codeLoading = truethis.buttonName = '验证码发送中'this.codeData.value = this.form.emailconst _this = thisresetEmail(this.codeData).then(res => {this.$message({showClose: true,message: '发送成功,验证码有效期5分钟',type: 'success'})this.codeLoading = falsethis.isDisabled = truethis.buttonName = this.time-- + '秒后重新发送'this.timer = window.setInterval(function() {_this.buttonName = _this.time + '秒后重新发送'--_this.timeif (_this.time < 0) {_this.buttonName = '重新发送'_this.time = 60_this.isDisabled = falsewindow.clearInterval(_this.timer)}}, 1000)}).catch(err => {this.resetForm()this.codeLoading = falseconsole.log(err.response.data.message)})}},doSubmit() {this.$refs['form'].validate((valid) => {if (valid) {this.loading = trueupdateEmail(this.form).then(res => {this.loading = falsethis.resetForm()this.$notify({title: '邮箱修改成功',type: 'success',duration: 1500})store.dispatch('GetInfo').then(() => {})}).catch(err => {this.loading = falseconsole.log(err.response.data.message)})} else {return false}})},resetForm() {this.dialog = falsethis.$refs['form'].resetFields()window.clearInterval(this.timer)this.time = 60this.buttonName = '获取验证码'this.isDisabled = falsethis.form = { pass: '', email: '', code: '' }}}
}
</script><style scoped></style>js:
import request from '@/utils/request'export function resetEmail(data) {return request({url: 'api/code/resetEmail',method: 'post',data})
}export function updatePass(pass) {return request({url: 'api/users/updatePass/' + pass,method: 'get'})
}

生成校验验证码service:


import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.exception.BadRequestException;
import co.yixiang.tools.domain.VerificationCode;
import co.yixiang.tools.domain.vo.EmailVo;
import co.yixiang.tools.service.VerificationCodeService;
import co.yixiang.tools.service.mapper.VerificationCodeMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class VerificationCodeServiceImpl extends BaseServiceImpl<VerificationCodeMapper, VerificationCode> implements VerificationCodeService {@Value("${code.expiration}")private Integer expiration;@Override@Transactional(rollbackFor = Exception.class)public EmailVo sendEmail(VerificationCode code) {EmailVo emailVo;String content;VerificationCode verificationCode = this.getOne(new LambdaQueryWrapper<VerificationCode>().eq(VerificationCode::getScenes, code.getScenes()).eq(VerificationCode::getType, code.getType()).eq(VerificationCode::getValue, code.getValue()));// 如果不存在有效的验证码,就创建一个新的TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));Template template = engine.getTemplate("email/email.ftl");if (verificationCode == null) {code.setCode(RandomUtil.randomNumbers(6));//package cn.hutool.core.util包下的RandomUtil工具content = template.render(Dict.create().set("code", code.getCode()));emailVo = new EmailVo(Collections.singletonList(code.getValue()), "yxiang后台管理系统", content);this.save(code);timedDestruction(code);// 存在就再次发送原来的验证码} else {content = template.render(Dict.create().set("code", verificationCode.getCode()));emailVo = new EmailVo(Collections.singletonList(verificationCode.getValue()), "yshop后台管理系统", content);}return emailVo;}@Overridepublic void validated(VerificationCode code) {VerificationCode verificationCode = this.getOne(new LambdaQueryWrapper<VerificationCode>().eq(VerificationCode::getScenes, code.getScenes()).eq(VerificationCode::getType, code.getType()).eq(VerificationCode::getValue, code.getValue()).eq(VerificationCode::getStatus, true));if (verificationCode == null || !verificationCode.getCode().equals(code.getCode())) {throw new BadRequestException("无效验证码");} else {verificationCode.setStatus(false);this.save(verificationCode);}}/*** 定时任务,指定分钟后改变验证码状态* @param verifyCode 验证码*/private void timedDestruction(VerificationCode verifyCode) {//以下示例为程序调用结束继续运行ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,new BasicThreadFactory.Builder().namingPattern("verifyCode-schedule-pool-%d").daemon(true).build());try {executorService.schedule(() -> {verifyCode.setStatus(false);this.save(verifyCode);}, expiration * 60 * 1000L, TimeUnit.MILLISECONDS);} catch (Exception e) {e.printStackTrace();}}
}

ftl模板:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><style>@page {margin: 0;}</style>
</head>
<body style="margin: 0px;padding: 0px;font: 100% SimSun, Microsoft YaHei, Times New Roman, Verdana, Arial, Helvetica, sans-serif;color: #000;">
<div style="height: auto;width: 820px;min-width: 820px;margin: 0 auto;margin-top: 20px;border: 1px solid #eee;"><div style="padding: 10px;padding-bottom: 0px;"><p style="margin-bottom: 10px;padding-bottom: 0px;">尊敬的用户,您好:</p><p style="text-indent: 2em; margin-bottom: 10px;">您正在申请邮箱验证,您的验证码为:</p><p style="text-align: center;font-family: Times New Roman;font-size: 22px;color: #C60024;padding: 20px 0px;margin-bottom: 10px;font-weight: bold;background: #ebebeb;">${code}</p><div class="foot-hr hr" style="margin: 0 auto;z-index: 111;width: 800px;margin-top: 30px;border-top: 1px solid #DA251D;"></div></div>
</div>
</body>
</html>

真正发送邮箱的EmailConfigService

public interface EmailConfigService extends BaseService<EmailConfig> {/*** 更新邮件配置* @param emailConfig 邮件配置* @param old 旧的配置* @return EmailConfig*/void update(EmailConfig emailConfig, EmailConfig old);/*** 查询配置* @return EmailConfig 邮件配置*/EmailConfig find();/*** 发送邮件* @param emailVo 邮件发送的内容* @param emailConfig 邮件配置* @throws Exception /*/@Asyncvoid send(EmailVo emailVo, EmailConfig emailConfig) throws Exception;
}
import cn.hutool.extra.mail.Mail;
import cn.hutool.extra.mail.MailAccount;
@Service
@AllArgsConstructor
//@CacheConfig(cacheNames = "emailConfig")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class EmailConfigServiceImpl extends BaseServiceImpl<EmailConfigMapper, EmailConfig> implements EmailConfigService {private final IGenerator generator;@Override
//    @CachePut(key = "'1'")@Transactional(rollbackFor = Exception.class)public void update(EmailConfig emailConfig, EmailConfig old) {try {if (!emailConfig.getPass().equals(old.getPass())) {// 对称加密emailConfig.setPass(EncryptUtils.desEncrypt(emailConfig.getPass()));}} catch (Exception e) {e.printStackTrace();}this.save(emailConfig);}@Override
//    @Cacheable(key = "'1'")public EmailConfig find() {EmailConfig emailConfig = this.list().get(0);return emailConfig;}@Override@Transactional(rollbackFor = Exception.class)public void send(EmailVo emailVo, EmailConfig emailConfig) {if (emailConfig == null) {throw new BadRequestException("请先配置,再操作");}// 封装MailAccount account = new MailAccount();account.setHost(emailConfig.getHost());account.setPort(Integer.parseInt(emailConfig.getPort()));account.setAuth(true);try {// 对称解密account.setPass(EncryptUtils.desDecrypt(emailConfig.getPass()));} catch (Exception e) {throw new BadRequestException(e.getMessage());}account.setFrom(emailConfig.getUser() + "<" + emailConfig.getFromUser() + ">");// ssl方式发送account.setSslEnable(true);// 使用STARTTLS安全连接account.setStarttlsEnable(true);String content = emailVo.getContent();// 发送try {int size = emailVo.getTos().size();Mail.create(account).setTos(emailVo.getTos().toArray(new String[size])).setTitle(emailVo.getSubject()).setContent(content).setHtml(true)//关闭session.setUseGlobalSession(false).send();} catch (Exception e) {throw new BadRequestException(e.getMessage());}}
}

springboot使用TemplateEngine修改邮箱后发送验证码示例相关推荐

  1. SpringBoot利用邮箱注册(发送验证码)

    使用邮箱发送验证码功能 提示:本人用的是QQ邮箱,其他邮箱方式类似 文章目录 使用邮箱发送验证码功能 一.开启POP3/SMTP服务 1.进入QQ邮箱,点击设置 2.选中账户 3.然后一直往下划,找到 ...

  2. vb.net——通过邮箱动态发送验证码实现完美注册

    [ 背景] 平时不管我们注册哪个网站,想必大家都注意到必须使用有效的电话号码或邮箱号码,为什么呢?因为他们都要求动态发送 验证码,然后通过验证验证码的真伪,来有效避免胡乱注册的现象. 那么,在高校云平 ...

  3. 【邮箱验证码】springboot 使用邮箱服务发送验证码 ,在阿里云服务器端口的配置

    1.我们需要登录邮箱开通邮箱授权码 2.然后需要pom需要引入spring-boot-starter-mail <dependency><groupId>org.springf ...

  4. Spring Boot 整合163或者qq邮箱发送验证码

    前记 最近做的项目中注册功能要用到验证码,本来想用阿里云的短信服务,但是有点小贵,就另辟捷径,选择了用邮箱来发送验证码.记录一下整合过程,也希望能帮助一些有需要的人. 正文 1.Spring Boot ...

  5. SpringBoot——邮箱发送验证码进行密码修改

    使用邮箱发送验证码进行改密验证,验证码需要分别发送到:(1)用户邮箱(2)缓存服务器 注:验证码发送到缓存服务器后,验证码保存一段时间,时间到期后,证明验证失败 1.设计前端页面 计划是:输入用户名( ...

  6. SpringBoot实现邮箱发送验证码(QQ,163等同理)

    SpringBoot实现邮箱发送验证码 准备工作(依赖和yml文件的配置) 邮件的发送代码 补充 准备工作(依赖和yml文件的配置) 我们要远程操纵邮箱就需要获得每个邮箱的密钥: 1.先进入你的qq邮 ...

  7. SpringBoot通过qq邮箱发送验证码

    SpringBoot通过qq邮箱发送验证码 1.开启qq授权码 2.编写配置文件 spring:#邮箱验证mail:##163 smtp.163.com(反垃圾系统发送不了了)##qq smtp.qq ...

  8. react-hooks + node 使用qq邮箱发送验证码,验证修改密码

    在平常,我们写登录注册react项目时,我们可能会考虑使用QQ邮箱发送验证码登录注册,或者使用QQ邮箱验证来修改密码,下面,我们就来使用QQ邮箱来简单发送个邮件. 1.当我们想在react项目中使用Q ...

  9. Java实现QQ邮箱登录,实现邮箱验证码三分钟失效,代码实现发送验证码和登录全过程思路。内附完整项目。

    温馨提示: 如果感觉本文章困难,请移步简单的邮箱验证,不涉及数据库和Redis,点击我进行跳转 使用技术: 1. MySQL数据库 2. Redis缓存(极其简单)点击此处学习 功能介绍: 发送验证码 ...

最新文章

  1. 玩转Mixly – 2、Arduino AVR编程 之 输入输出
  2. 【H3C交换机】cpu各个进程的详细说明
  3. 01-spring配置详解
  4. Nodejs 博客系统遇到的问题及解决
  5. 在vSphere 6.x vSAN数据存储上使用Oracle RAC(2121181)
  6. Linux终端的概念
  7. Access手工注入
  8. linux sendemail,在linux下使用sendEmail发送邮件
  9. 孙鑫VC学习笔记:第十一讲 (五) 如何使窗口具有滚动条
  10. uni-app 小程序分享到朋友和朋友圈
  11. 图像处理与计算机视觉:基础,经典以及最近发展
  12. 又拍云叶靖:OpenResty 在又拍云存储中的应用
  13. LightOJ-1090-数论
  14. windows 10修改host,有效解决权限问题,请惠存
  15. sdnu1385.Problem A: XOR(连续异或规律)
  16. 用inception_v3提取图片的特征向量
  17. 撑不下去的时候,请看看这19张照片
  18. Request Method: OPTIONS
  19. 电脑正在更新计算机一直是,win10电脑一直不停更新怎么办啊
  20. [错题]Mocha and Railgun

热门文章

  1. dataset中的数据批量导入oracle数据库,c#如何将dataset中的数据批量导入oracle数据库...
  2. 如何在圆柱表面滚花纹_更多地了解圆柱形铣刀
  3. Java ist reverse_charist.js响应
  4. 四个变量的图表怎么做_年终总结必备:Excel双色图表怎么做?数据表达更直观...
  5. 软工专硕考研_分析|华北电力(北京)大学20计算机考研报录分析!电子信息复试狂刷114人,软工专硕复试录取高达1:4.7!...
  6. 分布式内存数据库---Redis的持久化
  7. pycharm导入自定义模块问题
  8. 【推荐系统】基于模型的协同过滤算法
  9. 推翻Hinton NeurIPS论文结论!审稿人评价:该文章在标签平滑和知识蒸馏的关系上取得了重大突破!...
  10. 想快速发表CV/NLP论文?试试这几个方向!