Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 邮箱验证码验证 #14

Merged
merged 62 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
f537063
feat: add a status code
Macaku Jan 17, 2024
ae18955
EmailIdentifyingException.java
Macaku Jan 17, 2024
490f969
feat: add a definition of exception
Macaku Jan 17, 2024
e35bba2
feat: add a tool about email check
Macaku Jan 17, 2024
37a5c88
feat: add a email check service
Macaku Jan 17, 2024
297ff50
feat: add a Reposiroty class to exchange with Redis
Macaku Jan 17, 2024
549f8e1
feat: definition entity of model html
Macaku Jan 17, 2024
78338d9
feat: add email model html
Macaku Jan 17, 2024
c4e415f
feat: add two api
Macaku Jan 17, 2024
cd062a0
feat: add a default mail against error
Macaku Jan 17, 2024
55affde
feat: add a annotation
Macaku Jan 17, 2024
f0062c1
feat: add a validator
Macaku Jan 17, 2024
5d3e440
feat: add a dependencies
Macaku Jan 17, 2024
c7c77c3
fix: 修复 validate 使用上的一些问题
BanTanger Jan 17, 2024
1a0fdb6
feat: add a definition of exception
Macaku Jan 17, 2024
67b5e9c
feat: add predicate of email pattern
Macaku Jan 17, 2024
d6e7df9
feat: add some status code
Macaku Jan 17, 2024
f71a3b0
feat: close a worthless log property
Macaku Jan 17, 2024
022f027
feat: change some properties
Macaku Jan 17, 2024
6332f8d
Merge branch 'feat-email-validate' of github.com:AchoBeta/AchoBeta-Re…
Macaku Jan 17, 2024
2eef345
fix: adjust some code
Macaku Jan 17, 2024
f880b38
fix: 调整代码位置,更改代码逻辑,还有点待做明天搞
BanTanger Jan 17, 2024
2d5eaed
fix: delete some unrelated code
Macaku Jan 17, 2024
1c0067f
fix: modify the definition of status codes
Macaku Jan 17, 2024
0ebb03a
fix: delete some blank link
Macaku Jan 17, 2024
cf3ad64
fix: adjust the code to separate RedisCache
Macaku Jan 17, 2024
ca49738
fix: delete some sensitive properties
Macaku Jan 17, 2024
2b9e5d7
feat: add some methods
Macaku Jan 17, 2024
632be08
feat: change to a detail name
Macaku Jan 17, 2024
0a155ce
extract email verification service
Macaku Jan 17, 2024
8a19c94
fix: adjust some codes
Macaku Jan 17, 2024
4408398
Merge branch 'feat-email-validate' of github.com:AchoBeta/AchoBeta-Re…
Macaku Jan 17, 2024
19376dc
fix: fix a bug
Macaku Jan 17, 2024
1680de7
feat: add a check opportunities for users
Macaku Jan 17, 2024
76bc9e5
fix: code format and location
BanTanger Jan 18, 2024
287509c
fix: code reformat
BanTanger Jan 18, 2024
e1f1d9b
feat: delete a file
Macaku Jan 18, 2024
0378d43
fix: add timeout
Macaku Jan 18, 2024
b7293cb
Merge branch 'feat-email-validate' of github.com:AchoBeta/AchoBeta-Re…
Macaku Jan 18, 2024
e265237
improve email exception handling
Macaku Jan 18, 2024
385c3ea
fix: adjust some codes
Macaku Jan 18, 2024
98fa2dc
fix: adjust some codes
Macaku Jan 18, 2024
5e88432
feat: add a global exception
Macaku Jan 18, 2024
44a6476
fix: remove a file
Macaku Jan 18, 2024
4a49ba7
fix: adjust the code about handling exception
Macaku Jan 18, 2024
93cf8e5
feat: check email pattern because the annotation is invalid
Macaku Jan 18, 2024
a02f455
fix: adjust some code
Macaku Jan 18, 2024
445506c
feat: add some commom method
Macaku Jan 18, 2024
13e0f3b
fix: adjust som codes
Macaku Jan 18, 2024
63fbd39
fix: fix a bug
Macaku Jan 18, 2024
4bafd2a
fix: adjust some codes
Macaku Jan 18, 2024
35ef43f
feat: move two files
Macaku Jan 18, 2024
203a217
feat: add configuration to prevent errors
Macaku Jan 18, 2024
c40272b
fix: remove two files
Macaku Jan 18, 2024
1b71251
fix: adjust the overall logic of the code
Macaku Jan 18, 2024
de5d3ab
fix: rename some field and files
Macaku Jan 18, 2024
a7d0466
feat: add some method
Macaku Jan 18, 2024
4d65107
fix: move some files
Macaku Jan 19, 2024
4aaaf5a
fix: remove some files
Macaku Jan 19, 2024
fa13997
fix:
Macaku Jan 19, 2024
6a01c6d
feat: add a todo mask
Macaku Jan 19, 2024
bbb3a11
Merge branch 'master' into feat-email-validate
CarefreeState Jan 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
Expand Down Expand Up @@ -118,19 +123,22 @@
<version>5.8.11</version>
</dependency>

<!-- 表格生成 -->
<!-- 表格生成 -->
<!--easypoi-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>

</dependencies>



<build>
<resources>
<resource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, "用户未登录"),
Expand All @@ -42,6 +43,13 @@ public enum GlobalServiceStatusCode {
USER_NO_PERMISSION(2403, "用户无权限"),
USER_NO_PHONE_CODE(2500, "验证码错误"),

CarefreeState marked this conversation as resolved.
Show resolved Hide resolved
/* 邮箱错误 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, "验证次数达到上限"),

/* -------------- */;

Expand All @@ -53,7 +61,6 @@ public enum GlobalServiceStatusCode {
this.message = message;
}


/**
* 根据code获取message
*
Expand Down
103 changes: 51 additions & 52 deletions src/main/java/com/achobeta/domain/email/component/EmailSender.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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));
Expand All @@ -101,43 +99,44 @@ 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));
//合并模板与数据
String content = templateEngine.process(template, context);
mimeMessageHelper.setText(content, true);
// 添加附件
for(File file : files) {
if(Objects.nonNull(file)) {
for (File file : files) {
CarefreeState marked this conversation as resolved.
Show resolved Hide resolved
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 <T, R> void customizedSendEmail(Email email, String template, Function<T, R> function, File... files) {
if(Objects.isNull(email)) {
throw new ParameterValidateException("email不能为空");
public <T, R> void customizedSendEmail(EmailMessage emailMessage, String template, Function<T, R> 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 -> {
Expand All @@ -150,8 +149,8 @@ public <T, R> void customizedSendEmail(Email email, String template, Function<T,
mimeMessageHelper.setCc(carbonCopy);
mimeMessageHelper.setSubject(title);
// 添加附件
for(File file : files) {
if(Objects.nonNull(file)) {
for (File file : files) {
CarefreeState marked this conversation as resolved.
Show resolved Hide resolved
if (Objects.nonNull(file)) {
mimeMessageHelper.addAttachment(file.getName(), file);
}
}
Expand All @@ -166,7 +165,7 @@ public <T, R> void customizedSendEmail(Email email, String template, Function<T,
//发送
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new SendMailException(e.getMessage());
throw new GlobalServiceException(e.getMessage(), GlobalServiceStatusCode.EMAIL_SEND_FAIL);
}
});
}
Expand Down
CarefreeState marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.achobeta.domain.email.component;

public class EmailValidator {

public static final String EMAIL_PATTERN = "^[\\w\\.-]+@[a-zA-Z\\d\\.-]+\\.[a-zA-Z]{2,}$";

public static boolean isEmailAccessible(String email) {
return email.matches(EMAIL_PATTERN);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* 封装这个对象,传给EmailSender就可以了
*/
@Data
public class Email implements Serializable {
public class EmailMessage implements Serializable {


private String sender;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.achobeta.domain.email.controller;

import com.achobeta.common.SystemJsonResponse;
import com.achobeta.domain.email.service.EmailService;
import com.achobeta.domain.email.util.IdentifyingCodeValidator;
import jakarta.validation.constraints.Email;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
@RequiredArgsConstructor
@Validated
@RequestMapping("/api/v1/email")
public class EmailController {

private final EmailService emailService;

/**
* 发送验证码接口
*
* @param email
* @return
*/
@PostMapping("/check")
public SystemJsonResponse emailIdentityCheck(@RequestParam("email") @Email String email) {
// 获得随机验证码
String code = IdentifyingCodeValidator.getIdentifyingCode();
emailService.sendIdentifyingCode(email, code);
// 能到这一步就成功了
log.info("发送验证码:{} -> 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();
}

}
Original file line number Diff line number Diff line change
@@ -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; // 过期时间分钟数

}
Loading
Loading