Skip to content

Commit 39b114b

Browse files
authored
Merge pull request #194 from UDR-Sequence/feat/email
feat: 간단한 이메일 인증 폼 추가
2 parents 1fc92d9 + 445455a commit 39b114b

3 files changed

Lines changed: 59 additions & 26 deletions

File tree

sequence_member/src/main/java/sequence/sequence_member/member/controller/EmailAuthController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import org.springframework.web.bind.annotation.PostMapping;
55
import org.springframework.web.bind.annotation.RequestBody;
66
import org.springframework.web.bind.annotation.RequestMapping;
7-
import org.springframework.web.bind.annotation.RequestParam;
87
import org.springframework.web.bind.annotation.RestController;
98

109
import lombok.RequiredArgsConstructor;

sequence_member/src/main/java/sequence/sequence_member/member/service/EmailAuthService.java

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,37 @@
33
import java.time.LocalDateTime;
44
import java.util.UUID;
55

6+
import org.springframework.beans.factory.annotation.Value;
67
import org.springframework.mail.javamail.JavaMailSender;
78
import org.springframework.mail.javamail.MimeMessageHelper;
89
import org.springframework.stereotype.Service;
10+
import org.thymeleaf.context.Context;
11+
import org.thymeleaf.spring6.SpringTemplateEngine;
912

1013
import jakarta.mail.MessagingException;
1114
import jakarta.mail.internet.MimeMessage;
1215
import lombok.RequiredArgsConstructor;
1316
import sequence.sequence_member.member.entity.EmailAuthTokenEntity;
1417
import sequence.sequence_member.member.repository.EmailAuthTokenRepository;
15-
import org.springframework.beans.factory.annotation.Value;
16-
1718

1819
@RequiredArgsConstructor
1920
@Service
2021
public class EmailAuthService {
2122

2223
private final JavaMailSender mailSender;
24+
private final EmailAuthTokenRepository tokenRepo;
25+
private final SpringTemplateEngine templateEngine;
2326

2427
@Value("${NAVER_MAIL_USERNAME:dev_mj_@naver.com}")
2528
private String fromEmail;
26-
private final EmailAuthTokenRepository tokenRepo;
2729

2830
public void requestEmailVerification(String email) {
2931
tokenRepo.findAllByEmail(email).forEach(token -> {
3032
token.setExpired(true);
3133
tokenRepo.save(token);
3234
});
3335

34-
String token = UUID.randomUUID().toString().substring(0, 6);
36+
String token = UUID.randomUUID().toString().substring(0, 6).toUpperCase();
3537

3638
EmailAuthTokenEntity emailAuthToken = EmailAuthTokenEntity.builder()
3739
.email(email)
@@ -41,11 +43,9 @@ public void requestEmailVerification(String email) {
4143
.build();
4244

4345
tokenRepo.save(emailAuthToken);
44-
4546
sendAuthEmail(email, token);
4647
}
4748

48-
// 인증 확인
4949
public void verifyEmailToken(String email, String token) {
5050
EmailAuthTokenEntity authToken = tokenRepo.findByEmailAndToken(email, token)
5151
.orElseThrow(() -> new IllegalArgumentException("잘못된 인증 정보입니다."));
@@ -61,42 +61,33 @@ public void verifyEmailToken(String email, String token) {
6161
throw new IllegalStateException("시간 초과로 인하여 토큰이 만료되었습니다.");
6262
}
6363

64-
// 해당 이메일의 모든 토큰 만료 처리
6564
tokenRepo.findAllByEmail(email).forEach(t -> {
66-
t.setVerified(false); // 기존 것들 다 false로 초기화
65+
t.setVerified(false);
6766
tokenRepo.save(t);
6867
});
6968

70-
// 현재 토큰만 인증 처리
7169
authToken.setVerified(true);
7270
tokenRepo.save(authToken);
7371
}
7472

75-
76-
77-
// MimeMessage 방식으로 인증 메일 전송
7873
private void sendAuthEmail(String email, String token) {
7974
try {
8075
MimeMessage message = mailSender.createMimeMessage();
81-
MimeMessageHelper helper = new MimeMessageHelper(message, true);
76+
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
77+
78+
Context context = new Context();
79+
context.setVariable("token", token);
80+
81+
String htmlContent = templateEngine.process("emailAuth", context);
8282

8383
helper.setFrom(fromEmail);
8484
helper.setTo(email);
85-
helper.setSubject("[Sequence] 이메일 인증 코드");
85+
helper.setSubject("[Sequence] 이메일 인증 안내");
86+
helper.setText(htmlContent, true);
8687

87-
String content = "<html><body>"
88-
+ "<h2>이메일 인증 안내</h2>"
89-
+ "<p>아래의 인증 코드를 입력해주세요.</p>"
90-
+ "<p><strong>인증 코드: " + token + "</strong></p>"
91-
+ "</body></html>";
92-
93-
helper.setText(content, true);
9488
mailSender.send(message);
95-
9689
} catch (MessagingException e) {
97-
throw new RuntimeException("이메일 전송 실패", e);
90+
throw new RuntimeException("이메일 발송 중 오류가 발생했습니다.", e);
9891
}
9992
}
100-
10193
}
102-
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Sequence 이메일 인증</title>
6+
</head>
7+
8+
<body style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; margin: 0; padding: 0; background-color: #121212; width: 100%;">
9+
<table width="100%" border="0" cellspacing="0" cellpadding="0">
10+
<tr>
11+
<td align="center" style="padding: 40px 20px;">
12+
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width: 580px; color: #E0E0E0;">
13+
<tr>
14+
<td align="left" style="padding-bottom: 20px;">
15+
<h1 style="color: #D9230F; font-family: 'Georgia', 'Times New Roman', Times, serif; font-size: 36px; margin: 0;">Sequence</h1>
16+
</td>
17+
</tr>
18+
<tr>
19+
<td style="padding: 30px; background-color: #1e1e1e; border-radius: 8px;">
20+
<h2 style="font-size: 24px; color: #D9230F; margin: 0 0 20px 0;">이메일 인증 안내</h2>
21+
<p style="font-size: 16px; line-height: 1.6; color: #BDBDBD; margin: 0 0 20px 0;">회원가입을 완료하려면 아래 인증 코드를 입력해주세요.</p>
22+
23+
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #2a2a2a; border-radius: 8px; margin: 20px 0;">
24+
<tr>
25+
<td align="center" style="padding: 25px;">
26+
<span style="font-size: 28px; font-weight: bold; color: #FFFFFF; letter-spacing: 5px;" th:text="${token}">A1B2C3</span>
27+
</td>
28+
</tr>
29+
</table>
30+
<p style="font-size: 14px; line-height: 1.6; color: #BDBDBD;">본인이 요청하지 않은 인증 메일이라면 이 메일을 무시하셔도 좋습니다.</p>
31+
</td>
32+
</tr>
33+
<tr>
34+
<td align="center" style="font-size: 12px; color: #888888; padding: 30px 0;">
35+
<p style="margin: 0;">&copy; <span th:text="${#dates.year(#dates.createNow())}">2025</span> Sequence. All Rights Reserved.</p>
36+
</td>
37+
</tr>
38+
</table>
39+
</td>
40+
</tr>
41+
</table>
42+
</body>
43+
</html>

0 commit comments

Comments
 (0)