邮件系统重构,重置密码加入验证码验证

This commit is contained in:
Himit_ZH 2021-01-15 14:50:56 +08:00
parent 1aaf5968ac
commit 6e666b948a
53 changed files with 725 additions and 281 deletions

View File

@ -128,6 +128,17 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--模板引擎,主要用于发送邮件模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--生成验证码-->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -95,7 +95,7 @@ public class AccountController {
return CommonResult.errorResponse("对不起!该邮箱已被注册,请更换新的邮箱!");
}
String numbers = RandomUtil.randomNumbers(6); // 随机生成6位数字的组合
redisUtils.set(email, numbers, 5 * 60);//默认验证码有效5分钟
redisUtils.set(Constants.Email.REGISTER_KEY_PREFIX.getValue()+email, numbers, 5 * 60);//默认验证码有效5分钟
emailService.sendCode(email, numbers);
return CommonResult.successResponse(MapUtil.builder()
.put("email", email)
@ -153,20 +153,26 @@ public class AccountController {
* @Since 2020/11/6
*/
@PostMapping("/apply-reset-password")
public CommonResult applyResetPassword(@RequestBody Map<String, Object> data) throws MessagingException {
public CommonResult applyResetPassword(@RequestBody Map<String, Object> data) {
String captcha = (String) data.get("captcha");
String captchaKey = (String) data.get("captchaKey");
String email = (String) data.get("email");
String username = (String) data.get("username");
if (StringUtils.isEmpty(email) || StringUtils.isEmpty(username)) {
return CommonResult.errorResponse("用户名或邮箱不能为空");
if (StringUtils.isEmpty(captcha) || StringUtils.isEmpty(email) || StringUtils.isEmpty(captchaKey)) {
return CommonResult.errorResponse("邮箱或验证码不能为空");
}
QueryWrapper<UserInfo> wrapper = new QueryWrapper<UserInfo>().eq("email", email).eq("username", username);
UserInfo user = userInfoDao.getOne(wrapper);
if (user == null) {
return CommonResult.errorResponse("用户名和该邮箱不匹配");
// 获取redis中的验证码
String redisCode = (String) redisUtils.get(captchaKey);
// 判断验证码
if (!redisCode.equals(captcha.trim().toLowerCase())) {
return CommonResult.errorResponse("验证码不正确");
}
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
userInfoQueryWrapper.eq("email", email.trim());
UserInfo userInfo = userInfoDao.getOne(userInfoQueryWrapper);
String code = IdUtil.simpleUUID().substring(0, 21); // 随机生成20位数字与字母的组合
redisUtils.set(username, code, 10 * 60);//默认链接有效10分钟
emailService.sendResetPassword(username, code, email);
redisUtils.set(Constants.Email.RESET_PASSWORD_KEY_PREFIX.getValue()+userInfo.getUsername(), code, 10 * 60);//默认链接有效10分钟
// 发送邮件
emailService.sendResetPassword(userInfo.getUsername(), code, email.trim());
return CommonResult.successResponse(null, "重置密码邮件已发送至指定邮箱,请稍稍等待一会。");
}
@ -187,10 +193,12 @@ public class AccountController {
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(username) || StringUtils.isEmpty(code)) {
return CommonResult.errorResponse("用户名,新密码或验证码不能为空");
}
if (!redisUtils.hasKey(username)) {
String codeKey = Constants.Email.RESET_PASSWORD_KEY_PREFIX.getValue()+username;
if (!redisUtils.hasKey(codeKey)) {
return CommonResult.errorResponse("重置密码链接不存在或已过期,请重新发送重置邮件");
}
if (!redisUtils.get(username).equals(code)) { //验证码判断
if (!redisUtils.get(codeKey).equals(code)) { //验证码判断
return CommonResult.errorResponse("重置密码的链接验证码不正确,请重新发送重置邮件");
}
@ -218,11 +226,11 @@ public class AccountController {
if (!configVo.getRegister()) { // 需要判断一下网站是否开启注册
return CommonResult.errorResponse("对不起!本站暂未开启注册功能!", CommonResult.STATUS_ACCESS_DENIED);
}
if (!redisUtils.hasKey(registerDto.getEmail())) {
String codeKey = Constants.Email.REGISTER_KEY_PREFIX.getValue()+registerDto.getEmail();
if (!redisUtils.hasKey(codeKey)) {
return CommonResult.errorResponse("验证码不存在或已过期");
}
if (!redisUtils.get(registerDto.getEmail()).equals(registerDto.getCode())) { //验证码判断
if (!redisUtils.get(codeKey).equals(registerDto.getCode())) { //验证码判断
return CommonResult.errorResponse("验证码不正确");
}
String uuid = IdUtil.simpleUUID();

View File

@ -1,6 +1,10 @@
package top.hcode.hoj.controller.oj;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -9,6 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
import top.hcode.hoj.common.result.CommonResult;
import top.hcode.hoj.pojo.entity.*;
import top.hcode.hoj.service.impl.*;
import top.hcode.hoj.utils.RedisUtils;
import javax.validation.Valid;
import java.util.HashMap;
@ -19,7 +24,7 @@ import java.util.stream.Collectors;
/**
* @Author: Himit_ZH
* @Date: 2020/12/12 23:25
* @Description:
* @Description: 通用的请求控制处理类
*/
@RestController
@RequestMapping("/api")
@ -37,52 +42,69 @@ public class CommonController {
@Autowired
private ProblemLanguageServiceImpl problemLanguageService;
@Autowired
private RedisUtils redisUtil;
@GetMapping("/captcha")
public CommonResult getCaptcha() {
SpecCaptcha specCaptcha = new SpecCaptcha(90, 30, 4);
specCaptcha.setCharType(Captcha.TYPE_DEFAULT);
String verCode = specCaptcha.text().toLowerCase();
String key = IdUtil.simpleUUID();
// 存入redis并设置过期时间为30分钟
redisUtil.set(key, verCode, 1800);
// 将key和base64返回给前端
return CommonResult.successResponse(MapUtil.builder().put("img", specCaptcha.toBase64())
.put("captchaKey", key).map(), "获取成功");
}
@GetMapping("/get-all-problem-tags")
public CommonResult getAllProblemTagsList(){
public CommonResult getAllProblemTagsList() {
List<Tag> list = tagService.list();
if (list!=null){
return CommonResult.successResponse(list,"获取题目标签列表成功!");
}else{
if (list != null) {
return CommonResult.successResponse(list, "获取题目标签列表成功!");
} else {
return CommonResult.errorResponse("获取题目标签列表失败!");
}
}
@GetMapping("/get-problem-tags")
public CommonResult getProblemTags(@Valid @RequestParam("pid") Long pid){
public CommonResult getProblemTags(@Valid @RequestParam("pid") Long pid) {
Map<String, Object> map = new HashMap<>();
map.put("pid", pid);
List<Long> tidList = problemTagService.listByMap(map).stream().map(ProblemTag::getTid).collect(Collectors.toList());
List<Tag> tags = (List<Tag>) tagService.listByIds(tidList);
if (tags!=null){
return CommonResult.successResponse(tags,"获取该题目的标签列表成功!");
}else{
if (tags != null) {
return CommonResult.successResponse(tags, "获取该题目的标签列表成功!");
} else {
return CommonResult.errorResponse("获取该题目的标签列表失败!");
}
}
@GetMapping("/languages")
public CommonResult getLanguages(){
public CommonResult getLanguages() {
List<Language> list = languageService.list();
if (list!=null){
return CommonResult.successResponse(list,"获取编程语言列表成功!");
}else{
if (list != null) {
return CommonResult.successResponse(list, "获取编程语言列表成功!");
} else {
return CommonResult.errorResponse("获取编程语言列表失败!");
}
}
@GetMapping("/get-Problem-languages")
public CommonResult getProblemLanguages(@Valid @RequestParam("pid") Long pid){
public CommonResult getProblemLanguages(@Valid @RequestParam("pid") Long pid) {
QueryWrapper<ProblemLanguage> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("pid", pid).select("lid");
List<Long> idList = problemLanguageService.list(queryWrapper)
.stream().map(ProblemLanguage::getLid).collect(Collectors.toList());
List<Language> languages = (List<Language>) languageService.listByIds(idList);
if (languages!=null){
return CommonResult.successResponse(languages,"获取该题目的编程语言列表成功!");
}else{
if (languages != null) {
return CommonResult.successResponse(languages, "获取该题目的编程语言列表成功!");
} else {
return CommonResult.errorResponse("获取该题目的编程语言列表失败!");
}
}

View File

@ -1,9 +1,8 @@
package top.hcode.hoj.service;
import javax.mail.MessagingException;
public interface EmailService {
public void sendCode(String email,String code) throws MessagingException;
public void sendResetPassword(String username,String code,String email) throws MessagingException;
public void testEmail(String email) throws MessagingException;
public void sendCode(String email,String code);
public void sendResetPassword(String username,String code,String email);
public void testEmail(String email) ;
}

View File

@ -2,13 +2,17 @@ package top.hcode.hoj.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import top.hcode.hoj.service.EmailService;
import top.hcode.hoj.utils.Constants;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
@ -18,234 +22,135 @@ import java.util.Date;
/**
* @Author: Himit_ZH
* @Date: 2020/10/24 13:21
* @Description:
* @Description: 异步发送邮件的任务
*/
@Service
@Async
@Slf4j
public class EmailServiceImpl implements EmailService {
@Autowired
JavaMailSender mailSender;
private JavaMailSender mailSender;
@Autowired
private TemplateEngine templateEngine;
/**
* @param email 用户邮箱
* @param code 生成的六位随机数字验证码
* @MethodName sendCode
* @Description 为正在注册的用户发送一份注册验证码
* @Return
* @Since 2021/1/14
*/
@Override
public void sendCode(String email, String code) throws MessagingException {
DateTime dateTime = DateUtil.offsetMinute(new Date(), 5);
public void sendCode(String email, String code) {
DateTime expireTime = DateUtil.offsetMinute(new Date(), 10);
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
mimeMessageHelper.setSubject("HOJ的注册邮件");
mimeMessageHelper.setText("<div style=\"background: white;\n" +
"\t\t width: 100%;\n" +
"\t\t max-width: 800px;\n" +
"\t\t margin: auto auto;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t border:#1bc3fb 1px solid;\n" +
"\t\t overflow: hidden;\n" +
"\t\t -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);\n" +
"\t\t box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);\">\n" +
"\t\t\t\t<header style=\"overflow: hidden;\">\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<img style=\"width:100%;HEz-index: 666;\" src=\"https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png\">\n" +
"\t\t\t\t\t</center>\n" +
"\t\t\t\t</header>\n" +
"\t\t\t\t<div style=\"padding: 5px 20px;\">\n" +
"\t\t\t\t\t<p style=\"position: relative;\n" +
"\t\t color: white;\n" +
"\t\t float: left;\n" +
"\t\t z-index: 999;\n" +
"\t\t background: #1bc3fb;\n" +
"\t\t padding: 5px 30px;\n" +
"\t\t margin: -25px auto 0 ;\n" +
"\t\t box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30)\">\n" +
"\t\t\t\t\t\tDear New HOJer\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<h3>\n" +
"\t\t\t\t\t\t\t来自 <span style=\"text-decoration: none;color: #FF779A; \">HOJ</span> 邮件提醒\n" +
"\t\t\t\t\t\t</h3>\n" +
"\t\t\t\t\t<p style=\"text-indent:2em; \">\n" +
"\t\t\t\t\t\t您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=\"text-decoration: none;color: #1bc3fb \" target=\"_blank\" href=\"${POST_URL}\" rel=\"noopener\">&nbsp;HOJ&nbsp;</a>上进行注册。假如这不是您本人所申请, 请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<div style=\"background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center;\">\n" +
"\t\t\t\t\t\t请使用以下验证码完成后续注册流程<br>\n" +
"\t\t\t\t\t\t <span style=\"color: #FF779A;font-weight: bolder;font-size: 25px;\">"+code+"</span><br>\n" +
"\t\t\t\t\t\t 注意:请您在收到邮件5分钟内("+dateTime.toString()+"前)使用,否则该验证码将会失效。\n" +
"\t\t\t\t\t\t</div>\n" +
"\t\t\t\t\t&nbsp; &nbsp;\n" +
"\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<div style=\"text-align: center;\">\n" +
"\t\t\t\t\t\t<a style=\"text-transform: uppercase;\n" +
"\t\t text-decoration: none;\n" +
"\t\t font-size: 14px;\n" +
"\t\t background: #FF779A;\n" +
"\t\t color: #FFFFFF;\n" +
"\t\t padding: 10px;\n" +
"\t\t display: inline-block;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t margin: 10px auto 0; \"\n" +
"\t\t\t\t\t\t target=\"_blank\" href=\"oj.hcode.top\" rel=\"noopener\">HOJ传送门\uD83D\uDEAA</a>\n" +
"\t\t\t\t\t</div>\n" +
"\t\t\t\t\t<p style=\"font-size: 12px;text-align: center;color: #999;\">\n" +
"\t\t\t\t\t\t欢迎常来访问<br>\n" +
"\t\t\t\t\t\t© 2020 <a style=\"text-decoration:none; color:#1bc3fb\" href=\"${SITE_URL}\" rel=\"noopener\" target=\"_blank\">\n" +
"\t\t\t\t\t\t\tHODE-OJ </a>\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<p></p>\n" +
"\t\t\t\t</div>\n" +
"\t\t\t</div>",true);
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
// 设置渲染到html页面对应的值
Context context = new Context();
context.setVariable(Constants.Email.OJ_NAME.name(), Constants.Email.OJ_NAME.getValue());
context.setVariable(Constants.Email.OJ_SHORT_NAME.name(), Constants.Email.OJ_SHORT_NAME.getValue());
context.setVariable(Constants.Email.OJ_URL.name(), Constants.Email.OJ_URL.getValue());
context.setVariable(Constants.Email.EMAIL_BACKGROUND_IMG.name(), Constants.Email.EMAIL_BACKGROUND_IMG.getValue());
context.setVariable("CODE", code);
context.setVariable("EXPIRE_TIME", expireTime.toString());
mimeMessageHelper.setTo(email);
mimeMessageHelper.setFrom("oj.hcode@qq.com");
mailSender.send(mimeMessage);
//利用模板引擎加载html文件进行渲染并生成对应的字符串
String emailContent = templateEngine.process("emailTemplate_registerCode", context);
// 设置邮件标题
mimeMessageHelper.setSubject("HOJ的注册邮件");
mimeMessageHelper.setText(emailContent, true);
// 收件人
mimeMessageHelper.setTo(email);
// 发送人
mimeMessageHelper.setFrom(Constants.Email.EMAIL_FROM.getValue());
mailSender.send(mimeMessage);
} catch (MessagingException e) {
log.error("用户注册的邮件任务发生异常------------>{}", e.getMessage());
}
}
/**
* @param username 需要重置密码的用户名
* @param email 用户邮箱
* @param code 随机生成20位数字与字母的组合
* @MethodName sendResetPassword
* @Description 给指定的邮箱的用户发送重置密码链接的邮件
* @Return
* @Since 2021/1/14
*/
@Override
public void sendResetPassword(String username, String code, String email) throws MessagingException {
DateTime dateTime = DateUtil.offsetMinute(new Date(), 10);
public void sendResetPassword(String username, String code, String email) {
DateTime expireTime = DateUtil.offsetMinute(new Date(), 10);
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
mimeMessageHelper.setSubject("HOJ的重置密码邮件");
mimeMessageHelper.setText("<div style=\"background: white;\n" +
"\t\t width: 100%;\n" +
"\t\t max-width: 800px;\n" +
"\t\t margin: auto auto;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t border:#1bc3fb 1px solid;\n" +
"\t\t overflow: hidden;\n" +
"\t\t -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);\n" +
"\t\t box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);\">\n" +
"\t\t\t\t<header style=\"overflow: hidden;\">\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<img style=\"width:100%;HEz-index: 666;\" src=\"https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png\">\n" +
"\t\t\t\t\t</center>\n" +
"\t\t\t\t</header>\n" +
"\t\t\t\t<div style=\"padding: 5px 20px;\">\n" +
"\t\t\t\t\t<p style=\"position: relative;\n" +
"\t\t color: white;\n" +
"\t\t float: left;\n" +
"\t\t z-index: 999;\n" +
"\t\t background: #1bc3fb;\n" +
"\t\t padding: 5px 30px;\n" +
"\t\t margin: -25px auto 0 ;\n" +
"\t\t box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30)\">\n" +
"\t\t\t\t\t\tDear "+username+"\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<h3>\n" +
"\t\t\t\t\t\t\t来自 <span style=\"text-decoration: none;color: #FF779A; \">HOJ</span> 邮件提醒\n" +
"\t\t\t\t\t\t</h3>\n" +
"\t\t\t\t\t<p style=\"text-indent:2em; \">\n" +
"\t\t\t\t\t\t您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=\"text-decoration: none;color: #1bc3fb \" target=\"_blank\" href=\"${POST_URL}\" rel=\"noopener\">&nbsp;HOJ&nbsp;</a>上进行密码重置操作。假如这不是您本人所申请, 请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<div style=\"background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center;\">\n" +
"\t\t\t\t\t\t请点击下面的链接完成后续重置密码的流程<br>\n" +
"\t\t\t\t\t\t <a href=\"http://localhost:8080/reset-password?username="+username+"&code="+code+"\" style=\"color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;\">CLICK HERE</a><br>\n" +
"\t\t\t\t\t\t 注意:请您在收到邮件10分钟内("+dateTime.toString()+"前)使用,否则该链接将会失效。\n" +
"\t\t\t\t\t\t</div>\n" +
"\t\t\t\t\t&nbsp; &nbsp;\n" +
"\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<div style=\"text-align: center;\">\n" +
"\t\t\t\t\t\t<a style=\"text-transform: uppercase;\n" +
"\t\t text-decoration: none;\n" +
"\t\t font-size: 14px;\n" +
"\t\t background: #FF779A;\n" +
"\t\t color: #FFFFFF;\n" +
"\t\t padding: 10px;\n" +
"\t\t display: inline-block;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t margin: 10px auto 0; \"\n" +
"\t\t\t\t\t\t target=\"_blank\" href=\"oj.hcode.top\" rel=\"noopener\">HOJ传送门\uD83D\uDEAA</a>\n" +
"\t\t\t\t\t</div>\n" +
"\t\t\t\t\t<p style=\"font-size: 12px;text-align: center;color: #999;\">\n" +
"\t\t\t\t\t\t欢迎常来访问<br>\n" +
"\t\t\t\t\t\t© 2020 <a style=\"text-decoration:none; color:#1bc3fb\" href=\"${SITE_URL}\" rel=\"noopener\" target=\"_blank\">\n" +
"\t\t\t\t\t\t\tHODE-OJ </a>\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<p></p>\n" +
"\t\t\t\t</div>\n" +
"\t\t\t</div>",true);
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
// 设置渲染到html页面对应的值
Context context = new Context();
context.setVariable(Constants.Email.OJ_NAME.name(), Constants.Email.OJ_NAME.getValue());
context.setVariable(Constants.Email.OJ_SHORT_NAME.name(), Constants.Email.OJ_SHORT_NAME.getValue());
context.setVariable(Constants.Email.OJ_URL.name(), Constants.Email.OJ_URL.getValue());
context.setVariable(Constants.Email.EMAIL_BACKGROUND_IMG.name(), Constants.Email.EMAIL_BACKGROUND_IMG.getValue());
context.setVariable("RESET_URL", Constants.Email.OJ_URL.getValue() + "/reset-password?username=" + username + "&code=" + code);
context.setVariable("EXPIRE_TIME", expireTime.toString());
context.setVariable("USERNAME", username);
//利用模板引擎加载html文件进行渲染并生成对应的字符串
String emailContent = templateEngine.process("emailTemplate_resetPassword", context);
mimeMessageHelper.setTo(email);
mimeMessageHelper.setFrom("oj.hcode@qq.com");
mailSender.send(mimeMessage);
mimeMessageHelper.setSubject("HOJ的重置密码邮件");
mimeMessageHelper.setText(emailContent, true);
// 收件人
mimeMessageHelper.setTo(email);
// 发送人
mimeMessageHelper.setFrom(Constants.Email.EMAIL_FROM.getValue());
mailSender.send(mimeMessage);
} catch (MessagingException e) {
log.error("用户重置密码的邮件任务发生异常------------>{}", e.getMessage());
}
}
@Override
public void testEmail(String email) throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
mimeMessageHelper.setSubject("HOJ的测试邮件");
mimeMessageHelper.setText("<div style=\"background: white;\n" +
"\t\t width: 100%;\n" +
"\t\t max-width: 800px;\n" +
"\t\t margin: auto auto;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t border:#1bc3fb 1px solid;\n" +
"\t\t overflow: hidden;\n" +
"\t\t -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);\n" +
"\t\t box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);\">\n" +
"\t\t\t\t<header style=\"overflow: hidden;\">\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<img style=\"width:100%;HEz-index: 666;\" src=\"https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png\">\n" +
"\t\t\t\t\t</center>\n" +
"\t\t\t\t</header>\n" +
"\t\t\t\t<div style=\"padding: 5px 20px;\">\n" +
"\t\t\t\t\t<p style=\"position: relative;\n" +
"\t\t color: white;\n" +
"\t\t float: left;\n" +
"\t\t z-index: 999;\n" +
"\t\t background: #1bc3fb;\n" +
"\t\t padding: 5px 30px;\n" +
"\t\t margin: -25px auto 0 ;\n" +
"\t\t box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30)\">\n" +
"\t\t\t\t\t\tDear 超级管理员\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<center>\n" +
"\t\t\t\t\t\t<h3>\n" +
"\t\t\t\t\t\t\t来自 <span style=\"text-decoration: none;color: #FF779A; \">HOJ</span> 邮件提醒\n" +
"\t\t\t\t\t\t</h3>\n" +
"\t\t\t\t\t<p style=\"text-indent:2em; \">\n" +
"\t\t\t\t\t\t您收到这封电子邮件是因为您在<a style=\"text-decoration: none;color: #1bc3fb \" target=\"_blank\" href=\"${POST_URL}\" rel=\"noopener\">&nbsp;HOJ&nbsp;</a>上进行邮箱配置更新,然后进行邮箱可行性的测试。\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<div style=\"background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center;\">\n" +
"\t\t\t\t\t\t经过本邮件的接收可证实<br>\n" +
"\t\t\t\t\t\t <span style=\"color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;\">测试成功</span><br>\n" +
"\t\t\t\t\t\t</div>\n" +
"\t\t\t\t\t&nbsp; &nbsp;\n" +
"\n" +
"\t\t\t\t\t<br>\n" +
"\t\t\t\t\t<div style=\"text-align: center;\">\n" +
"\t\t\t\t\t\t<a style=\"text-transform: uppercase;\n" +
"\t\t text-decoration: none;\n" +
"\t\t font-size: 14px;\n" +
"\t\t background: #FF779A;\n" +
"\t\t color: #FFFFFF;\n" +
"\t\t padding: 10px;\n" +
"\t\t display: inline-block;\n" +
"\t\t border-radius: 5px;\n" +
"\t\t margin: 10px auto 0; \"\n" +
"\t\t\t\t\t\t target=\"_blank\" href=\"oj.hcode.top\" rel=\"noopener\">HOJ传送门\uD83D\uDEAA</a>\n" +
"\t\t\t\t\t</div>\n" +
"\t\t\t\t\t<p style=\"font-size: 12px;text-align: center;color: #999;\">\n" +
"\t\t\t\t\t\t欢迎常来访问<br>\n" +
"\t\t\t\t\t\t© 2020 <a style=\"text-decoration:none; color:#1bc3fb\" href=\"${SITE_URL}\" rel=\"noopener\" target=\"_blank\">\n" +
"\t\t\t\t\t\t\tHODE-OJ </a>\n" +
"\t\t\t\t\t</p>\n" +
"\t\t\t\t\t<p></p>\n" +
"\t\t\t\t</div>\n" +
"\t\t\t</div>",true);
mimeMessageHelper.setTo(email);
mimeMessageHelper.setFrom("oj.hcode@qq.com");
mailSender.send(mimeMessage);
/**
* @param email 用户邮箱
* @MethodName testEmail
* @Description 超级管理员后台修改邮件系统配置后发送的测试邮箱可用性的测试邮件
* @Return
* @Since 2021/1/14
*/
@Override
public void testEmail(String email) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,
true);
// 设置渲染到html页面对应的值
Context context = new Context();
context.setVariable(Constants.Email.OJ_NAME.name(), Constants.Email.OJ_NAME.getValue());
context.setVariable(Constants.Email.OJ_SHORT_NAME.name(), Constants.Email.OJ_SHORT_NAME.getValue());
context.setVariable(Constants.Email.OJ_URL.name(), Constants.Email.OJ_URL.getValue());
context.setVariable(Constants.Email.EMAIL_BACKGROUND_IMG.name(), Constants.Email.EMAIL_BACKGROUND_IMG.getValue());
//利用模板引擎加载html文件进行渲染并生成对应的字符串
String emailContent = templateEngine.process("emailTemplate_testEmail", context);
mimeMessageHelper.setSubject("HOJ的测试邮件");
mimeMessageHelper.setText(emailContent, true);
// 收件人
mimeMessageHelper.setTo(email);
// 发送人
mimeMessageHelper.setFrom(Constants.Email.EMAIL_FROM.getValue());
mailSender.send(mimeMessage);
} catch (MessagingException e) {
log.error("超级管理员重置邮件系统配置的测试邮箱可用性的任务发生异常------------>{}", e.getMessage());
}
}
}

View File

@ -21,7 +21,8 @@ public class ScheduleServiceImpl implements ScheduleService {
@Autowired
private FileServiceImpl fileService;
@Scheduled(cron = "0/5 * * * * *")
// 每天300执行一次
@Scheduled(cron = "0 0 3 * * *")
@Override
public void deleteAvatar() {
List<File> files = fileService.queryDeleteAvatarList();

View File

@ -127,4 +127,28 @@ public class Constants {
return path;
}
}
/**
* @Description 邮件任务的一些常量
* @Since 2021/1/14
*/
public enum Email{
OJ_URL("http://localhost:8080"),
OJ_NAME("Hcode Online Judge"),
OJ_SHORT_NAME("HOJ"),
EMAIL_FROM("oj.hcode@qq.com"),
EMAIL_BACKGROUND_IMG("https://cdn.jsdelivr.net/gh/HimitZH/CDN/images/HCODE.png"),
REGISTER_KEY_PREFIX("register-user:"),
RESET_PASSWORD_KEY_PREFIX("reset-password:");
private String value;
Email(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
}

View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset=UTF-8>
<title>用户注册验证码</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) ">
Dear New HOJer
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行注册。假如这不是您本人所申请,
请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
请使用以下验证码完成后续注册流程:<br>
<span style=" color: #FF779A;font-weight: bolder;font-size: 25px;" th:text="${CODE}"></span><br>
注意:请您在收到邮件10分钟内([[${EXPIRE_TIME}]]前)使用,否则该验证码将会失效。
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset="UTF-8">
<title>HOJ的重置密码邮件</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) " th:text="'Dear '+${USERNAME}">
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行密码重置操作。假如这不是您本人所申请, 请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
请点击下面的链接完成后续重置密码的流程:<br>
<a th:href="${RESET_URL}" style="color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;">CLICK HERE</a><br>
注意:请您在收到邮件10分钟内([[${EXPIRE_TIME}]]前)使用,否则该重置密码链接将会失效。
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset="UTF-8">
<title>超级管理员测试邮箱可用性邮件</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) ">
Dear Super Admin
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行邮箱配置更新,然后进行邮箱可行性的测试。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
经过本邮件的接收,可证实:<br>
<a style="color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;">Test Success</a><br>
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset=UTF-8>
<title>用户注册验证码</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) ">
Dear New HOJer
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行注册。假如这不是您本人所申请,
请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
请使用以下验证码完成后续注册流程:<br>
<span style=" color: #FF779A;font-weight: bolder;font-size: 25px;" th:text="${CODE}"></span><br>
注意:请您在收到邮件10分钟内([[${EXPIRE_TIME}]]前)使用,否则该验证码将会失效。
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset="UTF-8">
<title>HOJ的重置密码邮件</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) " th:text="'Dear '+${USERNAME}">
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您 (也可能是某人冒充您的名义) 在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行密码重置操作。假如这不是您本人所申请, 请不用理会这封电子邮件, 但是如果您持续收到这类的信件骚扰, 请您尽快联络管理员。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
请点击下面的链接完成后续重置密码的流程:<br>
<a th:href="${RESET_URL}" style="color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;">CLICK HERE</a><br>
注意:请您在收到邮件10分钟内([[${EXPIRE_TIME}]]前)使用,否则该重置密码链接将会失效。
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th=http://www.thymeleaf.org>
<head>
<meta charset="UTF-8">
<title>超级管理员测试邮箱可用性邮件</title>
</head>
<body>
<div style="background: white;
width: 100%;
max-width: 800px;
margin: auto auto;
border-radius: 5px;
border:#1bc3fb 1px solid;
overflow: hidden;
-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
<header style="overflow: hidden;">
<center>
<img style="width:100%;z-index: 666;"
th:src="${EMAIL_BACKGROUND_IMG}">
</center>
</header>
<div style="padding: 5px 20px; ">
<p style=" position: relative;
color: white;
float: left;
z-index: 999;
background: #1bc3fb;
padding: 5px 30px;
margin: -25px auto 0 ;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30) ">
Dear Super Admin
</p>
<br>
<center>
<h3>
来自 <span style=" text-decoration: none;color: #FF779A;" th:text="${OJ_SHORT_NAME}"></span> 邮件提醒
</h3>
<p style="text-indent:2em;">
您收到这封电子邮件是因为您在<a style=" text-decoration: none;color: #1bc3fb "
target="_blank" th:href="${OJ_URL}" rel="noopener">&nbsp;HOJ&nbsp;</a>上进行邮箱配置更新,然后进行邮箱可行性的测试。
</p>
<div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;text-align: center; ">
经过本邮件的接收,可证实:<br>
<a style="color: #FF779A;font-weight: bolder;font-size: 25px;text-decoration: none;">Test Success</a><br>
</div>
&nbsp; &nbsp;
<br>
<div style=" text-align: center; ">
<a style="text-transform: uppercase;
text-decoration: none;
font-size: 14px;
background: #FF779A;
color: #FFFFFF;
padding: 10px;
display: inline-block;
border-radius: 5px;
margin: 10px auto 0;"
target="_blank" th:href="${OJ_URL}" rel="noopener" th:text="${OJ_SHORT_NAME}+'|传送门🚪'"></a>
</div>
<p style="font-size: 12px;text-align: center;color: #999; ">
欢迎常来访问!<br>
© 2021 <a style="text-decoration:none; color:#1bc3fb " th:href="${OJ_URL}" rel="noopener"
target="_blank" th:text="${OJ_NAME}"></a>
</p>
<p></p>
</center>
</div>
</div>
</body>
</html>

View File

@ -153,6 +153,10 @@ const ojApi = {
}
})
},
// 获取验证码
getCaptcha(){
return ajax('/api/captcha', 'get')
},
// 注册
register(data) {
return ajax('/api/register', 'post', {

View File

@ -1,28 +1,37 @@
<template>
<div>
<el-form :model="formResetPassword" :rules="rules" ref="formResetPassword">
<el-form-item prop="username">
<el-input
v-model="formResetPassword.username"
prefix-icon="el-icon-user-solid"
placeholder="Please Enter Your Username"
width="100%"
></el-input>
</el-form-item>
<el-form-item prop="email">
<el-input
v-model="formResetPassword.email"
prefix-icon="el-icon-s-promotion"
prefix-icon="el-icon-message"
placeholder="Please Enter Your Email"
>
</el-input>
</el-form-item>
<el-form-item prop="captcha">
<div id="captcha">
<div id="captchaCode">
<el-input
v-model="formResetPassword.captcha"
prefix-icon="el-icon-s-check"
placeholder="Please Enter the captcha"
></el-input>
</div>
<div id="captchaImg">
<el-tooltip content="Click to refresh" placement="top">
<img :src="captchaSrc" @click="getCaptcha" />
</el-tooltip>
</div>
</div>
</el-form-item>
</el-form>
<div class="footer">
<el-button
type="primary"
@click="handleResetPwd"
:loading="btnResetPwdLoading"
:disabled="btnResetPwdDisabled"
>
{{ resetText }}
</el-button>
@ -38,18 +47,6 @@ import api from '@/common/api';
import mMessage from '@/common/message';
export default {
data() {
const CheckUsernameNotExist = (rule, value, callback) => {
api.checkUsernameOrEmail(value, undefined).then(
(res) => {
if (res.data.data.username === false) {
callback(new Error('The username does not exist'));
} else {
callback();
}
},
(_) => callback()
);
};
const CheckEmailNotExist = (rule, value, callback) => {
api.checkUsernameOrEmail(undefined, value).then(
(res) => {
@ -65,18 +62,22 @@ export default {
return {
resetText: '发送重置密码的邮件',
btnResetPwdLoading: false,
btnResetPwdDisabled: false,
captchaSrc: '',
formResetPassword: {
username: '',
captcha: '',
email: '',
captchaKey: '',
},
rules: {
username: [
captcha: [
{
required: true,
message: 'The username is required',
message: 'The captcha is required',
trigger: 'blur',
min: 1,
max: 8,
},
{ validator: CheckUsernameNotExist, trigger: 'blur' },
],
email: [
{
@ -90,8 +91,17 @@ export default {
},
};
},
mounted() {
this.getCaptcha();
},
methods: {
...mapActions(['changeModalStatus', 'changeResetTimeOut', 'startTimeOut']),
getCaptcha() {
api.getCaptcha().then((res) => {
this.captchaSrc = res.data.data.img;
this.formResetPassword.captchaKey = res.data.data.captchaKey;
});
},
switchMode(mode) {
this.changeModalStatus({
mode,
@ -102,7 +112,7 @@ export default {
let i = this.time;
this.resetText = i + '秒后,可重新发送重置密码的邮件...';
if (i == 0) {
this.btnResetPwdLoading = false;
this.btnResetPwdDisabled = false;
this.resetText = '发送重置密码的邮件';
return;
}
@ -113,19 +123,27 @@ export default {
handleResetPwd() {
this.$refs['formResetPassword'].validate((valid) => {
if (valid) {
this.resetText = '正在发送...';
mMessage.info('请稍后...系统正在向您的邮箱发送重置确认邮件');
this.resetText = '正在处理...';
mMessage.info('请稍后...系统正在处理中...');
this.btnResetPwdLoading = true;
this.btnResetPwdDisabled = true;
api.applyResetPassword(this.formResetPassword).then(
(res) => {
mMessage.success(res.data.msg);
this.successApply = true;
this.countDown();
this.startTimeOut({ name: 'resetTimeOut' });
},
(_) => {
this.btnResetPwdLoading = false;
this.formResetPassword.captcha = '';
this.formResetPassword.captchaKey = '';
this.getCaptcha();
},
(err) => {
this.formResetPassword.captcha = '';
this.formResetPassword.captchaKey = '';
this.btnResetPwdLoading = false;
this.btnResetPwdDisabled = false;
this.resetText = '重新发送';
this.getCaptcha();
}
);
}
@ -145,13 +163,29 @@ export default {
},
created() {
if (this.time != 90 && this.time != 0) {
this.btnResetPwdLoading = true;
this.btnResetPwdDisabled = true;
this.countDown();
}
},
};
</script>
<style scoped>
#captcha {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
width: 100%;
height: 36px;
}
#captchaCode {
flex: auto;
}
#captchaImg {
margin-left: 10px;
padding: 3px;
flex: initial;
}
.footer {
overflow: auto;
margin-top: 20px;