Skip to content

Commit 6cc43df

Browse files
authored
Merge pull request #196 from UDR-Sequence/feat/minji/project-invite-email
이메일 템플릿 반응형 디자인 적용
2 parents 8cac5ba + 5b98941 commit 6cc43df

File tree

5 files changed

+652
-6
lines changed

5 files changed

+652
-6
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
11
package sequence.sequence_member.global.config;
22

3+
import org.springframework.context.annotation.Bean;
34
import org.springframework.context.annotation.Configuration;
45
import org.springframework.scheduling.annotation.EnableAsync;
6+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
7+
8+
import java.util.concurrent.Executor;
59

610
@Configuration
711
@EnableAsync
812
public class AsyncConfig {
13+
14+
@Bean(name = "emailTaskExecutor")
15+
public Executor emailTaskExecutor() {
16+
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
17+
executor.setCorePoolSize(2);
18+
executor.setMaxPoolSize(5);
19+
executor.setQueueCapacity(100);
20+
executor.setThreadNamePrefix("Email-");
21+
executor.setWaitForTasksToCompleteOnShutdown(true);
22+
executor.setAwaitTerminationSeconds(30);
23+
executor.initialize();
24+
return executor;
25+
}
926
}

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

Lines changed: 155 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,166 @@ private void sendPasswordResetEmail(String email, String temporaryPassword) {
7676
helper.setTo(email);
7777
helper.setSubject("[Sequence] 임시 비밀번호 발급 안내");
7878

79-
String content = "<html><body>"
80-
+ "<h2>임시 비밀번호 발급 안내</h2>"
81-
+ "<p>안녕하세요. 임시 비밀번호가 발급되었습니다.</p>"
82-
+ "<p>아래의 임시 비밀번호로 로그인 후, 보안을 위해 마이페이지에서 비밀번호를 변경해주세요.</p>"
83-
+ "<p><strong>임시 비밀번호: " + temporaryPassword + "</strong></p>"
84-
+ "</body></html>";
79+
String content = "<!DOCTYPE html>" +
80+
"<html lang=\"ko\">" +
81+
"<head>" +
82+
"<meta charset=\"UTF-8\">" +
83+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">" +
84+
"<title>Sequence 임시비밀번호 발송</title>" +
85+
"<style>" +
86+
"@media only screen and (max-width: 600px) {" +
87+
".container { width: 100% !important; max-width: 100% !important; }" +
88+
".mobile-padding { padding: 20px !important; }" +
89+
".mobile-text { font-size: 16px !important; }" +
90+
".mobile-title { font-size: 18px !important; }" +
91+
".mobile-password { font-size: 22px !important; padding: 12px 20px !important; }" +
92+
".mobile-center { text-align: center !important; }" +
93+
".mobile-hide { display: none !important; }" +
94+
"}" +
95+
"@media only screen and (max-width: 480px) {" +
96+
".mobile-padding { padding: 15px !important; }" +
97+
".mobile-text { font-size: 14px !important; }" +
98+
".mobile-title { font-size: 16px !important; }" +
99+
".mobile-password { font-size: 20px !important; padding: 10px 15px !important; }" +
100+
"}" +
101+
"</style>" +
102+
"</head>" +
103+
"<body style=\"margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #151515; color: #ffffff; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%;\">" +
104+
105+
// 외부 컨테이너
106+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"background-color: #151515; min-height: 100vh;\">" +
107+
"<tr>" +
108+
"<td align=\"center\" style=\"padding: 10px;\">" +
109+
110+
// 메인 컨테이너 (반응형)
111+
"<table class=\"container\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"600\" style=\"max-width: 600px; width: 100%; background-color: #151515; margin: 0 auto;\">" +
112+
113+
// 헤더 섹션
114+
"<tr>" +
115+
"<td class=\"mobile-padding\" align=\"center\" style=\"background-color: #0f0f0f; padding: 40px 30px; border-bottom: 2px solid #E32929;\">" +
116+
"<h1 style=\"font-size: 32px; font-weight: 900; color: #E32929; margin: 0 0 15px 0; font-family: Arial, sans-serif; line-height: 1.2;\">Sequence</h1>" +
117+
"<h2 class=\"mobile-title\" style=\"font-size: 24px; color: #ffffff; margin: 0 0 10px 0; font-weight: 700; font-family: Arial, sans-serif; line-height: 1.3;\">🔑 임시 비밀번호 발급</h2>" +
118+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 16px; margin: 0; font-family: Arial, sans-serif; line-height: 1.4;\">계정 복구를 위한 임시 비밀번호를 발급했습니다</p>" +
119+
"</td>" +
120+
"</tr>" +
121+
122+
// 컨텐츠 섹션
123+
"<tr>" +
124+
"<td class=\"mobile-padding\" style=\"padding: 40px 30px; background-color: #151515;\">" +
125+
126+
// 안내 메시지
127+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin-bottom: 25px;\">" +
128+
"<tr>" +
129+
"<td style=\"padding: 0;\">" +
130+
"<p class=\"mobile-text\" style=\"font-size: 18px; color: #ffffff; margin: 0 0 15px 0; font-family: Arial, sans-serif; line-height: 1.5;\">" +
131+
"안녕하세요," +
132+
"</p>" +
133+
"<p class=\"mobile-text\" style=\"font-size: 16px; color: #cccccc; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">" +
134+
"요청하신 임시 비밀번호가 발급되었습니다. 아래의 임시 비밀번호로 로그인 후, 보안을 위해 마이페이지에서 비밀번호를 변경해주세요." +
135+
"</p>" +
136+
"</td>" +
137+
"</tr>" +
138+
"</table>" +
139+
140+
// 임시 비밀번호 섹션
141+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin: 30px 0;\">" +
142+
"<tr>" +
143+
"<td style=\"background-color: #1a1a1a; border: 2px solid #E32929; border-radius: 8px; padding: 25px 20px;\">" +
144+
145+
// 비밀번호 라벨
146+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin-bottom: 15px;\">" +
147+
"<tr>" +
148+
"<td align=\"center\">" +
149+
"<p style=\"color: #E32929; font-size: 12px; margin: 0; text-transform: uppercase; letter-spacing: 2px; font-weight: 600; font-family: Arial, sans-serif;\">임시 비밀번호</p>" +
150+
"</td>" +
151+
"</tr>" +
152+
"</table>" +
153+
154+
// 비밀번호 표시
155+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\">" +
156+
"<tr>" +
157+
"<td align=\"center\">" +
158+
"<div class=\"mobile-password\" style=\"background-color: #ffffff; color: #151515; font-size: 28px; font-weight: 900; padding: 15px 25px; border-radius: 4px; letter-spacing: 2px; font-family: 'Courier New', monospace; display: inline-block; margin: 0; word-break: break-all; max-width: 100%; box-sizing: border-box;\">" +
159+
temporaryPassword +
160+
"</div>" +
161+
"</td>" +
162+
"</tr>" +
163+
"</table>" +
164+
165+
"</td>" +
166+
"</tr>" +
167+
"</table>" +
168+
169+
// 보안 안내 섹션
170+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" style=\"margin: 25px 0;\">" +
171+
"<tr>" +
172+
"<td style=\"background-color: #1a1a1a; padding: 20px; border-radius: 6px;\">" +
173+
"<h3 class=\"mobile-title\" style=\"color: #E32929; font-size: 16px; font-weight: 700; margin: 0 0 15px 0; text-transform: uppercase; font-family: Arial, sans-serif;\">보안 알림 및 이용 안내</h3>" +
174+
175+
// 안내사항 목록
176+
"<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\">" +
177+
"<tr>" +
178+
"<td style=\"vertical-align: top; padding-bottom: 5px;\">" +
179+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 14px; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">• 로그인 즉시 마이페이지에서 새로운 비밀번호로 변경하세요</p>" +
180+
"</td>" +
181+
"</tr>" +
182+
"<tr>" +
183+
"<td style=\"vertical-align: top; padding-bottom: 5px;\">" +
184+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 14px; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">• 비밀번호를 타인과 공유하지 마세요</p>" +
185+
"</td>" +
186+
"</tr>" +
187+
"<tr>" +
188+
"<td style=\"vertical-align: top; padding-bottom: 5px;\">" +
189+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 14px; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">• Sequence 로그인 페이지에 접속합니다</p>" +
190+
"</td>" +
191+
"</tr>" +
192+
"<tr>" +
193+
"<td style=\"vertical-align: top; padding-bottom: 5px;\">" +
194+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 14px; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">• 이메일과 임시 비밀번호를 입력합니다</p>" +
195+
"</td>" +
196+
"</tr>" +
197+
"<tr>" +
198+
"<td style=\"vertical-align: top;\">" +
199+
"<p class=\"mobile-text\" style=\"color: #cccccc; font-size: 14px; margin: 0; line-height: 1.6; font-family: Arial, sans-serif;\">• 로그인 후 마이페이지에서 비밀번호 변경을 완료합니다</p>" +
200+
"</td>" +
201+
"</tr>" +
202+
"</table>" +
203+
204+
"</td>" +
205+
"</tr>" +
206+
"</table>" +
207+
208+
"</td>" +
209+
"</tr>" +
210+
211+
// 구분선
212+
"<tr>" +
213+
"<td style=\"padding: 0 30px;\">" +
214+
"<div style=\"height: 1px; background-color: #E32929; margin: 20px 0;\"></div>" +
215+
"</td>" +
216+
"</tr>" +
217+
218+
// 푸터 섹션
219+
"<tr>" +
220+
"<td class=\"mobile-padding mobile-center\" align=\"center\" style=\"background-color: #0f0f0f; padding: 30px; border-top: 1px solid #333;\">" +
221+
"<h2 style=\"font-size: 24px; font-weight: 900; color: #E32929; margin: 0 0 15px 0; font-family: Arial, sans-serif;\">Sequence</h2>" +
222+
"<p class=\"mobile-text\" style=\"color: #888888; font-size: 13px; margin: 5px 0; font-family: Arial, sans-serif;\">이 메시지는 발신 전용입니다.</p>" +
223+
"<p class=\"mobile-text\" style=\"color: #888888; font-size: 13px; margin: 5px 0; font-family: Arial, sans-serif;\">Sequence © 2025</p>" +
224+
"</td>" +
225+
"</tr>" +
226+
227+
"</table>" +
228+
"</td>" +
229+
"</tr>" +
230+
"</table>" +
231+
"</body>" +
232+
"</html>";
85233

86234
helper.setText(content, true);
87235
mailSender.send(message);
88236
} catch (MessagingException e) {
89237
throw new RuntimeException("이메일 발송 중 오류가 발생했습니다.",e);
90238
}
91239
}
240+
92241
}

0 commit comments

Comments
 (0)