邮件系统重构,重置密码加入验证码验证
This commit is contained in:
parent
1aaf5968ac
commit
6e666b948a
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,6 +42,24 @@ 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() {
|
||||
|
@ -62,7 +85,6 @@ public class CommonController {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/languages")
|
||||
public CommonResult getLanguages() {
|
||||
List<Language> list = languageService.list();
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
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());
|
||||
|
||||
//利用模板引擎加载html文件进行渲染并生成对应的字符串
|
||||
String emailContent = templateEngine.process("emailTemplate_registerCode", context);
|
||||
// 设置邮件标题
|
||||
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\"> HOJ </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 \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.setText(emailContent, true);
|
||||
// 收件人
|
||||
mimeMessageHelper.setTo(email);
|
||||
mimeMessageHelper.setFrom("oj.hcode@qq.com");
|
||||
// 发送人
|
||||
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();
|
||||
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.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\"> HOJ </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 \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.setText(emailContent, true);
|
||||
// 收件人
|
||||
mimeMessageHelper.setTo(email);
|
||||
mimeMessageHelper.setFrom("oj.hcode@qq.com");
|
||||
// 发送人
|
||||
mimeMessageHelper.setFrom(Constants.Email.EMAIL_FROM.getValue());
|
||||
mailSender.send(mimeMessage);
|
||||
} catch (MessagingException e) {
|
||||
log.error("用户重置密码的邮件任务发生异常------------>{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param email 用户邮箱
|
||||
* @MethodName testEmail
|
||||
* @Description 超级管理员后台修改邮件系统配置后发送的测试邮箱可用性的测试邮件。
|
||||
* @Return
|
||||
* @Since 2021/1/14
|
||||
*/
|
||||
@Override
|
||||
public void testEmail(String email) throws MessagingException {
|
||||
public void testEmail(String email) {
|
||||
MimeMessage mimeMessage = mailSender.createMimeMessage();
|
||||
try {
|
||||
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\"> HOJ </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 \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);
|
||||
// 设置渲染到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("oj.hcode@qq.com");
|
||||
// 发送人
|
||||
mimeMessageHelper.setFrom(Constants.Email.EMAIL_FROM.getValue());
|
||||
mailSender.send(mimeMessage);
|
||||
} catch (MessagingException e) {
|
||||
log.error("超级管理员重置邮件系统配置的测试邮箱可用性的任务发生异常------------>{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,8 @@ public class ScheduleServiceImpl implements ScheduleService {
|
|||
@Autowired
|
||||
private FileServiceImpl fileService;
|
||||
|
||||
@Scheduled(cron = "0/5 * * * * *")
|
||||
// 每天3:00执行一次
|
||||
@Scheduled(cron = "0 0 3 * * *")
|
||||
@Override
|
||||
public void deleteAvatar() {
|
||||
List<File> files = fileService.queryDeleteAvatarList();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
|
@ -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"> HOJ </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>
|
||||
|
||||
|
||||
<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>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -153,6 +153,10 @@ const ojApi = {
|
|||
}
|
||||
})
|
||||
},
|
||||
// 获取验证码
|
||||
getCaptcha(){
|
||||
return ajax('/api/captcha', 'get')
|
||||
},
|
||||
// 注册
|
||||
register(data) {
|
||||
return ajax('/api/register', 'post', {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue