diff --git a/pom.xml b/pom.xml
index 37afbde5..354f7dc3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,11 @@
org.springframework.boot
spring-boot-starter-jdbc
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
mysql
@@ -118,7 +123,7 @@
5.8.11
-
+
cn.afterturn
@@ -126,11 +131,14 @@
4.3.0
+
+ com.alibaba
+ fastjson
+ 1.2.31
+
-
-
diff --git a/src/main/java/com/achobeta/common/constants/GlobalServiceStatusCode.java b/src/main/java/com/achobeta/common/constants/GlobalServiceStatusCode.java
index 138fc874..e4614287 100644
--- a/src/main/java/com/achobeta/common/constants/GlobalServiceStatusCode.java
+++ b/src/main/java/com/achobeta/common/constants/GlobalServiceStatusCode.java
@@ -27,6 +27,7 @@ public enum GlobalServiceStatusCode {
PARAM_IS_BLANK(1002, "参数为空"),
PARAM_TYPE_ERROR(1003, "参数类型错误"),
PARAM_NOT_COMPLETE(1004, "参数缺失"),
+ PARAM_FAILED_VALIDATE(1005, "参数未通过验证"),
/* 用户错误 2001-3000 */
USER_NOT_LOGIN(2001, "用户未登录"),
@@ -42,6 +43,13 @@ public enum GlobalServiceStatusCode {
USER_NO_PERMISSION(2403, "用户无权限"),
USER_NO_PHONE_CODE(2500, "验证码错误"),
+ /* 邮箱错误 3001-4000 */
+ EMAIL_PATTERN_ERROR(3001, "邮箱格式错误"),
+ EMAIL_SEND_FAIL(3002, "邮箱发送失败"),
+
+ EMAIL_NOT_EXIST_RECORD(3101, "邮箱不存在记录"),
+ EMAIL_CODE_NOT_CONSISTENT(3102, "邮箱验证码不一致"),
+ EMAIL_CODE_OPPORTUNITIES_EXHAUST(3103, "验证次数达到上限"),
/* -------------- */;
@@ -53,7 +61,6 @@ public enum GlobalServiceStatusCode {
this.message = message;
}
-
/**
* 根据code获取message
*
diff --git a/src/main/java/com/achobeta/domain/email/component/EmailSender.java b/src/main/java/com/achobeta/domain/email/component/EmailSender.java
index 8031cd2e..3f3676f7 100644
--- a/src/main/java/com/achobeta/domain/email/component/EmailSender.java
+++ b/src/main/java/com/achobeta/domain/email/component/EmailSender.java
@@ -1,9 +1,9 @@
package com.achobeta.domain.email.component;
import cn.hutool.core.bean.BeanUtil;
-import com.achobeta.domain.email.component.po.Email;
-import com.achobeta.exception.ParameterValidateException;
-import com.achobeta.exception.SendMailException;
+import com.achobeta.common.constants.GlobalServiceStatusCode;
+import com.achobeta.domain.email.component.po.EmailMessage;
+import com.achobeta.exception.GlobalServiceException;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
@@ -20,79 +20,77 @@
import java.util.Objects;
import java.util.function.Function;
-
@Component
@Slf4j
@RequiredArgsConstructor
public class EmailSender {
+
private final JavaMailSender javaMailSender;
private final TemplateEngine templateEngine;
- public SimpleMailMessage emailToSimpleMailMessage(Email email) {
+ public SimpleMailMessage emailToSimpleMailMessage(EmailMessage emailMessage) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
- simpleMailMessage.setFrom(email.getSender());
- simpleMailMessage.setTo(email.getRecipient());
- simpleMailMessage.setCc(email.getCarbonCopy());
- simpleMailMessage.setSubject(email.getTitle());
- simpleMailMessage.setText(email.getContent());
+ simpleMailMessage.setFrom(emailMessage.getSender());
+ simpleMailMessage.setTo(emailMessage.getRecipient());
+ simpleMailMessage.setCc(emailMessage.getCarbonCopy());
+ simpleMailMessage.setSubject(emailMessage.getTitle());
+ simpleMailMessage.setText(emailMessage.getContent());
return simpleMailMessage;
}
-
- public MimeMessageHelper emailIntoMimeMessageByHelper(MimeMessage mimeMessage, Email email) {
+ public MimeMessageHelper emailIntoMimeMessageByHelper(MimeMessage mimeMessage, EmailMessage emailMessage) {
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
- mimeMessageHelper.setFrom(email.getSender());
- mimeMessageHelper.setCc(email.getCarbonCopy());
- mimeMessageHelper.setSubject(email.getTitle());
- mimeMessageHelper.setTo(email.getRecipient());
+ mimeMessageHelper.setFrom(emailMessage.getSender());
+ mimeMessageHelper.setCc(emailMessage.getCarbonCopy());
+ mimeMessageHelper.setSubject(emailMessage.getTitle());
+ mimeMessageHelper.setTo(emailMessage.getRecipient());
return mimeMessageHelper;
} catch (MessagingException e) {
- throw new SendMailException(e.getMessage());
+ throw new GlobalServiceException(e.getMessage(), GlobalServiceStatusCode.EMAIL_SEND_FAIL);
}
}
- public void sendSimpleMailMessage(Email email) {
- if(Objects.isNull(email)) {
- throw new ParameterValidateException("email不能为空");
+ public void sendSimpleMailMessage(EmailMessage emailMessage) {
+ if (Objects.isNull(emailMessage)) {
+ throw new GlobalServiceException("email不能为空", GlobalServiceStatusCode.PARAM_IS_BLANK);
}
// 封装simpleMailMessage对象
- SimpleMailMessage simpleMailMessage = emailToSimpleMailMessage(email);
+ SimpleMailMessage simpleMailMessage = emailToSimpleMailMessage(emailMessage);
// 发送
javaMailSender.send(simpleMailMessage);
}
-
- public void sendMailWithFile(Email email, File... files) {
- if(Objects.isNull(email)) {
- throw new ParameterValidateException("email不能为空");
+ public void sendMailWithFile(EmailMessage emailMessage, File... files) {
+ if (Objects.isNull(emailMessage)) {
+ throw new GlobalServiceException("email不能为空", GlobalServiceStatusCode.PARAM_IS_BLANK);
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
- MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, email);
+ MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 添加附件
- for(File file : files) {
- if(Objects.nonNull(file)) {
+ for (File file : files) {
+ if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
- mimeMessageHelper.setText(email.getContent(), false);
+ mimeMessageHelper.setText(emailMessage.getContent(), false);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
- throw new SendMailException(e.getMessage());
+ throw new GlobalServiceException(e.getMessage(), GlobalServiceStatusCode.EMAIL_SEND_FAIL);
}
}
- public void sendModelMail(Email email, String template, Object modelMessage) {
- if(Objects.isNull(email)) {
- throw new ParameterValidateException("email不能为空");
+ public void sendModelMail(EmailMessage emailMessage, String template, Object modelMessage) {
+ if (Objects.isNull(emailMessage)) {
+ throw new GlobalServiceException("email不能为空", GlobalServiceStatusCode.PARAM_IS_BLANK);
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
- MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, email);
+ MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 构造模板消息
Context context = new Context();
context.setVariables(BeanUtil.beanToMap(modelMessage));
@@ -101,17 +99,18 @@ public void sendModelMail(Email email, String template, Object modelMessage) {
mimeMessageHelper.setText(content, true);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
- throw new SendMailException(e.getMessage());
+ throw new GlobalServiceException(e.getMessage(), GlobalServiceStatusCode.EMAIL_SEND_FAIL);
}
}
- public void sendModelMailWithFile(Email email, String template, Object modelMessage, File... files) {
- if(Objects.isNull(email)) {
- throw new ParameterValidateException("email不能为空");
+
+ public void sendModelMailWithFile(EmailMessage emailMessage, String template, Object modelMessage, File... files) {
+ if (Objects.isNull(emailMessage)) {
+ throw new GlobalServiceException("email不能为空", GlobalServiceStatusCode.PARAM_IS_BLANK);
}
// 封装对象
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
- MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, email);
+ MimeMessageHelper mimeMessageHelper = emailIntoMimeMessageByHelper(mimeMessage, emailMessage);
// 构造模板消息
Context context = new Context();
context.setVariables(BeanUtil.beanToMap(modelMessage));
@@ -119,25 +118,25 @@ public void sendModelMailWithFile(Email email, String template, Object modelMess
String content = templateEngine.process(template, context);
mimeMessageHelper.setText(content, true);
// 添加附件
- for(File file : files) {
- if(Objects.nonNull(file)) {
+ for (File file : files) {
+ if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
- throw new SendMailException(e.getMessage());
+ throw new GlobalServiceException(e.getMessage(), GlobalServiceStatusCode.EMAIL_SEND_FAIL);
}
}
- public void customizedSendEmail(Email email, String template, Function function, File... files) {
- if(Objects.isNull(email)) {
- throw new ParameterValidateException("email不能为空");
+ public void customizedSendEmail(EmailMessage emailMessage, String template, Function function, File... files) {
+ if (Objects.isNull(emailMessage)) {
+ throw new GlobalServiceException("email不能为空", GlobalServiceStatusCode.PARAM_IS_BLANK);
}
- String sender = email.getSender();
- String[] carbonCopy = email.getCarbonCopy();
- String title = email.getTitle();
- Arrays.stream(email.getRecipient())
+ String sender = emailMessage.getSender();
+ String[] carbonCopy = emailMessage.getCarbonCopy();
+ String title = emailMessage.getTitle();
+ Arrays.stream(emailMessage.getRecipient())
.parallel()
.distinct()
.forEach(s -> {
@@ -150,8 +149,8 @@ public void customizedSendEmail(Email email, String template, Function void customizedSendEmail(Email email, String template, Function email:{}", code, email);
+ return SystemJsonResponse.SYSTEM_SUCCESS();
+ }
+
+ @PostMapping("/check/{code}")
+ public SystemJsonResponse checkCode(@RequestParam("email") @Email String email,
+ @PathVariable("code") @NonNull String code) {
+ // 验证
+ emailService.checkIdentifyingCode(email, code);
+ // 成功
+ log.info("email:{}, 验证码:{} 验证成功", email, code);
+ return SystemJsonResponse.SYSTEM_SUCCESS();
+ }
+
+}
diff --git a/src/main/java/com/achobeta/domain/email/model/vo/VerificationCodeTemplate.java b/src/main/java/com/achobeta/domain/email/model/vo/VerificationCodeTemplate.java
new file mode 100644
index 00000000..7101c4d6
--- /dev/null
+++ b/src/main/java/com/achobeta/domain/email/model/vo/VerificationCodeTemplate.java
@@ -0,0 +1,17 @@
+package com.achobeta.domain.email.model.vo;
+
+import lombok.Builder;
+import lombok.Getter;
+
+/**
+ * 生命周期只有一次,成员变量对修改关闭,直接通过 builder 构建对象
+ */
+@Getter
+@Builder
+public class VerificationCodeTemplate {
+
+ private String code; // 验证码
+
+ private int minutes; // 过期时间分钟数
+
+}
diff --git a/src/main/java/com/achobeta/domain/email/repository/EmailRepository.java b/src/main/java/com/achobeta/domain/email/repository/EmailRepository.java
new file mode 100644
index 00000000..fa159f76
--- /dev/null
+++ b/src/main/java/com/achobeta/domain/email/repository/EmailRepository.java
@@ -0,0 +1,50 @@
+package com.achobeta.domain.email.repository;
+
+import com.achobeta.domain.email.util.IdentifyingCodeValidator;
+import com.achobeta.redis.RedisCache;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Repository;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+
+@Repository
+@RequiredArgsConstructor
+public class EmailRepository {
+
+ private final RedisCache redisCache;
+
+ /**
+ * 设置验证码到 redis 里(携带超时时间点,与验证机会数)
+ *
+ * @param redisKey 用户邮箱在 redis 对应的key
+ * @param code 验证码
+ * @param timeout 超时时间
+ * @param opportunities 验证机会
+ */
+ public void setIdentifyingCode(String redisKey, String code, long timeout, int opportunities) {
+ Map data = new HashMap<>();
+ data.put(IdentifyingCodeValidator.IDENTIFYING_CODE, code); // 验证码
+ data.put(IdentifyingCodeValidator.IDENTIFYING_OPPORTUNITIES, opportunities); // 有效次数
+ redisCache.setCacheMap(redisKey, data);
+ redisCache.expire(redisKey, timeout); // 设置超时时间
+ }
+
+ public long getTTLOfCode(String redisKey) {
+ return redisCache.getKeyTTL(redisKey);
+ }
+
+ public long decrementOpportunities(String redisKey) {
+ return redisCache.decrementCacheMapNumber(redisKey, IdentifyingCodeValidator.IDENTIFYING_OPPORTUNITIES);
+ }
+
+ public Optional