-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[Feature] 이메일 전송 및 인증 기능 구현
- Loading branch information
Showing
7 changed files
with
177 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/main/java/com/guttery/madii/domain/mail/application/MailSendService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.guttery.madii.domain.mail.application; | ||
|
||
import com.guttery.madii.common.exception.CustomException; | ||
import com.guttery.madii.common.exception.ErrorDetails; | ||
import jakarta.mail.MessagingException; | ||
import jakarta.mail.internet.InternetAddress; | ||
import jakarta.mail.internet.MimeMessage; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.mail.javamail.JavaMailSender; | ||
import org.springframework.stereotype.Service; | ||
import org.thymeleaf.context.Context; | ||
import org.thymeleaf.spring6.SpringTemplateEngine; | ||
|
||
import java.io.UnsupportedEncodingException; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
@RequiredArgsConstructor | ||
@Slf4j | ||
@Service | ||
public class MailSendService { | ||
private static final Long EXPIRE_TIME = 1000 * 60 * 3L + 1000 * 10; // 3분 10초 | ||
|
||
private final JavaMailSender javaMailSender; | ||
private final SpringTemplateEngine springTemplateEngine; | ||
private final RedisTemplate<String, String> redisTemplate; | ||
|
||
public void sendSignUpMail(final String email) { | ||
final String code = MailVerificationCodeGenerator.generate(); // 인증코드 생성 | ||
final MimeMessage message = javaMailSender.createMimeMessage(); | ||
|
||
try { | ||
message.addRecipients(MimeMessage.RecipientType.TO, email); // 보낼 이메일 설정 | ||
message.setSubject("[MADII] 회원가입 인증번호 발송"); // 이메일 제목 | ||
message.setText(setContext(code), "utf-8", "html"); // 내용 설정(Template Process) | ||
message.setFrom(new InternetAddress("[email protected]", "마디")); | ||
} catch (final MessagingException | UnsupportedEncodingException e) { | ||
throw CustomException.of(ErrorDetails.MAIL_SEND_FAILED); | ||
} | ||
|
||
redisTemplate.opsForValue().set(email, code, EXPIRE_TIME, TimeUnit.MILLISECONDS); // Redis에 인증코드 저장 | ||
javaMailSender.send(message); // 이메일 전송 | ||
} | ||
|
||
private String setContext(final String code) { // 타임리프 설정하는 코드 | ||
final Context context = new Context(); | ||
context.setVariable("code", code); // Template에 전달할 데이터 설정 | ||
|
||
return springTemplateEngine.process("mail", context); // mail.html | ||
} | ||
|
||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/guttery/madii/domain/mail/application/MailVerificationCodeGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.guttery.madii.domain.mail.application; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
import org.apache.commons.lang3.RandomUtils; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class MailVerificationCodeGenerator { | ||
private static final int CODE_LOWER_BOUND = 100000; | ||
private static final int CODE_UPPER_BOUND = 1000000; | ||
|
||
public static String generate() { | ||
return String.valueOf(RandomUtils.nextInt(CODE_LOWER_BOUND, CODE_UPPER_BOUND)); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/guttery/madii/domain/mail/application/MailVerifyService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.guttery.madii.domain.mail.application; | ||
|
||
import com.guttery.madii.common.exception.CustomException; | ||
import com.guttery.madii.common.exception.ErrorDetails; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Propagation; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@RequiredArgsConstructor | ||
@Slf4j | ||
@Service | ||
public class MailVerifyService { | ||
private final RedisTemplate<String, String> redisTemplate; | ||
|
||
@Transactional(readOnly = true, propagation = Propagation.MANDATORY) | ||
public void verifyEmail(final String email, final String code) { | ||
final String redisCode = redisTemplate.opsForValue().get(email); | ||
if (redisCode == null || !redisCode.equals(code)) { | ||
throw CustomException.of(ErrorDetails.MAIL_VERIFY_FAILED); | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/com/guttery/madii/domain/mail/presentation/MailController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.guttery.madii.domain.mail.presentation; | ||
|
||
import com.guttery.madii.domain.mail.application.MailSendService; | ||
import com.guttery.madii.domain.mail.application.MailVerifyService; | ||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RequiredArgsConstructor | ||
@RestController | ||
@RequestMapping("/mail") | ||
@Validated | ||
public class MailController { | ||
private final MailSendService mailSendService; | ||
private final MailVerifyService mailVerifyService; | ||
|
||
@GetMapping("/v1/sign-up") | ||
public void sendSignUpMail( | ||
@NotBlank @RequestParam("email") final String email | ||
) { | ||
mailSendService.sendSignUpMail(email); | ||
} | ||
|
||
@GetMapping("/v1/password-reset") | ||
public void sendPasswordResetMail( | ||
@NotBlank @RequestParam("email") final String email | ||
) { | ||
mailSendService.sendSignUpMail(email); // TODO: 추후 수정 필요 | ||
} | ||
|
||
@GetMapping("/v1/verify") | ||
public void verifyEmail( | ||
@NotBlank @RequestParam("email") final String email, | ||
@NotBlank @RequestParam("code") final String code | ||
) { | ||
mailVerifyService.verifyEmail(email, code); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<!DOCTYPE html> | ||
<html lang="ko"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta content="width=device-width, initial-scale=1.0" name="viewport"> | ||
<title>회원가입 인증</title> | ||
</head> | ||
<body style="margin: 0; padding: 0; background-color: #F6F6F6; font-family: 'Pretendard', sans-serif;"> | ||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="background-color: #F6F6F6;" width="100%"> | ||
<tr> | ||
<td align="center" style="padding: 20px;" valign="top"> | ||
<!-- 이메일 본문 테이블 --> | ||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" | ||
style="border-radius: 14px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);"> | ||
<tr> | ||
<td style="background-image: url('https://cdn.madii.kr/signup_email_background.png'); background-size: cover; background-position: top; border-radius: 14px 14px 0 0; padding: 50px; text-align: left;"> | ||
<!-- 상단 이미지와 텍스트 --> | ||
<h1 style="color: #FFFFFF; font-size: 28px; font-weight: 700; margin-top: 0; margin-bottom: 24px;"> | ||
회원가입을 진심으로 환영합니다!</h1> | ||
<p style="color: #FFFFFF; font-size: 16px; font-weight: 500; margin-top: 0; margin-bottom: 24px;"> | ||
안녕하세요. 마디입니다.<br> | ||
아래의 인증코드 6자리를 입력하여 회원가입을 완료해주세요.<br> | ||
만약 해당 이메일로 가입을 시도한 적이 없다면 [email protected]로 문의바랍니다. | ||
</p> | ||
<!-- 인증코드 표시 부분 --> | ||
<td style="font-size: 42px; font-family: 'Pretendard', sans-serif; font-weight: 600; line-height: 63px; color: black; padding-top: 30px;"> | ||
<p style="text-align: center; font-size: 1.25rem; font-weight: bold; border: none; border-radius: 0.25rem; padding: 1rem 1.25rem; margin-bottom: 1rem; background-color: #F6F6F6; color: #717171;" | ||
th:text="${code}"></p> | ||
</td> | ||
</tr> | ||
</table> | ||
</td> | ||
</tr> | ||
</table> | ||
</body> | ||
</html> |