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

refactor: 이메일 템플릿 하드코딩 개선 및 외부 관리로 전환 완료 #580

Merged
merged 7 commits into from
Oct 1, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void processApplicationMemberCreated(ApplicationMemberCreationDto dto) {
String finalPassword = manageMemberPasswordUseCase.generateOrRetrievePassword(member.getPassword());
member.updatePassword(finalPassword, passwordEncoder);
registerMemberPort.save(member);
emailService.broadcastEmailToApprovedMember(member, finalPassword);
emailService.sendAccountCreationEmail(member, finalPassword);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public String resendMemberPassword(String memberId) {
member.updatePassword(newPassword, passwordEncoder);
registerMemberPort.save(member);

emailService.broadcastEmailToApprovedMember(member, newPassword);
emailService.sendNewPasswordEmail(member, newPassword);
return member.getId();
}

Expand All @@ -45,7 +45,7 @@ public String requestMemberPasswordReset(MemberResetPasswordRequestDto requestDt
Member member = validateResetPasswordRequest(requestDto);
String code = verificationService.generateVerificationCode();
verificationService.saveVerificationCode(member.getId(), code);
emailService.sendPasswordResetEmail(member, code);
emailService.sendPasswordResetCodeEmail(member, code);
return member.getId();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public String registerMember(MemberRequestDto requestDto) {
member.updatePassword(finalPassword, passwordEncoder);
registerMemberPort.save(member);
createPositionByMember(member);
emailService.broadcastEmailToApprovedMember(member, finalPassword);
emailService.sendAccountCreationEmail(member, finalPassword);
return member.getId();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ public void sendBatchEmail(List<EmailTask> emailTasks) throws MessagingException
messageHelper.setTo(task.getTo());
messageHelper.setSubject(task.getSubject());
messageHelper.setText(task.getContent(), true);

setImageInTemplate(messageHelper, task.getTemplateType());

if (task.getFiles() != null) {
for (File file : task.getFiles()) {
messageHelper.addAttachment(MimeUtility.encodeText(file.getName(), "UTF-8", "B"), file);
Expand All @@ -91,7 +93,7 @@ public void sendBatchEmail(List<EmailTask> emailTasks) throws MessagingException
}

private void setImageInTemplate(MimeMessageHelper messageHelper, EmailTemplateType templateType) throws MessagingException {
if (Objects.requireNonNull(templateType) == EmailTemplateType.NORMAL) {
if (Objects.equals(templateType.getTemplateName(), "clabEmail.html")) {
messageHelper.addInline("image-1", new ClassPathResource("images/image-1.png"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import page.clab.api.global.common.email.domain.EmailTemplateType;
import page.clab.api.global.common.email.dto.request.EmailDto;
import page.clab.api.global.common.email.exception.MessageSendingFailedException;
import page.clab.api.global.config.EmailTemplateProperties;
import page.clab.api.global.util.FileUtil;

import java.io.File;
Expand All @@ -30,6 +31,7 @@ public class EmailService {
private final ExternalRetrieveMemberUseCase externalRetrieveMemberUseCase;
private final SpringTemplateEngine springTemplateEngine;
private final EmailAsyncService emailAsyncService;
private final EmailTemplateProperties emailTemplateProperties;

@Value("${resource.file.path}")
private String filePath;
Expand All @@ -54,19 +56,21 @@ public List<String> broadcastEmail(EmailDto emailDto, List<MultipartFile> multip
return successfulAddresses;
}

public void broadcastEmailToApprovedMember(Member member, String password) {
String subject = "C-Lab 계정 발급 안내";
String content = """
정식으로 C-Lab의 일원이 된 것을 축하드립니다.
C-Lab과 함께하는 동안 불타는 열정으로 모든 원하는 목표를 이루어 내시기를 바라고,
훗날, 당신의 합류가 C-Lab에겐 최고의 행운이었다고 기억되기를 희망합니다.

로그인을 위해 아래의 계정 정보를 확인해주세요.
ID: %s
Password: %s
로그인 후 비밀번호를 변경해주세요.
""".formatted(member.getId(), password);
EmailDto emailDto = EmailDto.create(List.of(member.getEmail()), subject, content, EmailTemplateType.NORMAL);
public void sendAccountCreationEmail(Member member, String password) {
EmailTemplateProperties.Template template = emailTemplateProperties.getTemplate(EmailTemplateType.ACCOUNT_CREATION);

String subject = template.getSubject();
String content = template.getContent()
.replace("{{id}}", member.getId())
.replace("{{password}}", password);

EmailDto emailDto = EmailDto.create(
List.of(member.getEmail()),
subject,
content,
EmailTemplateType.ACCOUNT_CREATION
);

try {
String emailContent = generateEmailContent(emailDto, member.getName());
emailAsyncService.sendEmailAsync(member.getEmail(), emailDto.getSubject(), emailContent, null, emailDto.getEmailTemplateType());
Expand All @@ -75,22 +79,43 @@ public void broadcastEmailToApprovedMember(Member member, String password) {
}
}

public void sendPasswordResetEmail(Member member, String code) {
String subject = "C-Lab 비밀번호 재발급 인증 안내";
String content = """
C-Lab 비밀번호 재발급 인증 안내 메일입니다.
인증번호는 %s입니다.
해당 인증번호를 비밀번호 재설정 페이지에 입력해주세요.
재설정시 비밀번호는 인증번호로 대체됩니다.
""".formatted(code);
EmailDto emailDto = EmailDto.create(List.of(member.getEmail()), subject, content, EmailTemplateType.NORMAL);
public void sendPasswordResetCodeEmail(Member member, String code) {
EmailTemplateProperties.Template template = emailTemplateProperties.getTemplate(EmailTemplateType.PASSWORD_RESET_CODE);

String subject = template.getSubject();
String content = template.getContent()
.replace("{{code}}", code);

EmailDto emailDto = EmailDto.create(
List.of(member.getEmail()),
subject,
content,
EmailTemplateType.PASSWORD_RESET_CODE
);

try {
broadcastEmail(emailDto, null);
String emailContent = generateEmailContent(emailDto, member.getName());
emailAsyncService.sendEmailAsync(member.getEmail(), emailDto.getSubject(), emailContent, null, emailDto.getEmailTemplateType());
} catch (Exception e) {
throw new MessageSendingFailedException(member.getEmail() + " 비밀번호 재발급 인증 메일 전송에 실패했습니다.");
}
}

public void sendNewPasswordEmail(Member member, String newPassword) {
EmailTemplateProperties.Template template = emailTemplateProperties.getTemplate(EmailTemplateType.NEW_PASSWORD);
String content = template.getContent()
.replace("{{id}}", member.getId())
.replace("{{password}}", newPassword);

EmailDto emailDto = EmailDto.create(List.of(member.getEmail()), template.getSubject(), content, EmailTemplateType.NEW_PASSWORD);
try {
String emailContent = generateEmailContent(emailDto, member.getName());
emailAsyncService.sendEmailAsync(member.getEmail(), emailDto.getSubject(), emailContent, null, emailDto.getEmailTemplateType());
} catch (MessagingException e) {
throw new MessageSendingFailedException(member.getEmail() + " 비밀번호 재설정 안내 메일 전송에 실패했습니다.");
}
}

private List<File> convertMultipartFiles(List<MultipartFile> multipartFiles) {
List<File> convertedFiles = new ArrayList<>();
for (MultipartFile multipartFile : multipartFiles) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package page.clab.api.global.common.email.domain;

import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum EmailTemplateType {

NORMAL("NORMAL", "기본", "clabEmail.html");
ACCOUNT_CREATION("account-creation", "계정 생성", "clabEmail.html"),
PASSWORD_RESET_CODE("password-reset-code", "비밀번호 재설정", "clabEmail.html"),
NEW_PASSWORD("new-password", "새 비밀번호", "clabEmail.html");

@Enumerated(EnumType.STRING)
private final String key;
private final String description;
private final String templateName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class EmailDto {
private String content;

@NotNull(message = "{notNull.email.templateType}")
@Schema(description = "이메일 템플릿", example = "NORMAL")
@Schema(description = "이메일 템플릿", example = "ACCOUNT_CREATION")
private EmailTemplateType emailTemplateType;

public static EmailDto create(List<String> to, String subject, String content, EmailTemplateType emailTemplateType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package page.clab.api.global.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import page.clab.api.global.common.email.domain.EmailTemplateType;

import java.util.Map;

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "email")
public class EmailTemplateProperties {

private Map<String, Template> templates;

public Template getTemplate(EmailTemplateType templateType) {
Template template = templates.get(templateType.getKey());
if (template == null) {
throw new IllegalArgumentException("템플릿을 찾을 수 없습니다: " + templateType);
}
return template;
}

@Getter
@Setter
public static class Template {
private String subject;
private String content;
}
}
2 changes: 1 addition & 1 deletion src/main/resources/templates/clabEmail.html
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ <h1 class="v-font-size" style="margin: 0px; color: #2a2c32; line-height: 140%; t
<td class="v-container-padding-padding" style="overflow-wrap:break-word;word-break:break-word;padding:10px;font-family:'Montserrat',sans-serif;" align="center">

<div class="v-font-size" style="font-size: 14px; color: #908f8f; line-height: 200%; text-align: center; word-wrap: break-word;">
<p style="line-height: 200%;">C-Lab  |  경기대학교 컴퓨터공학부 개발보안동아리</p>
<p style="line-height: 200%;">C-Lab  |  경기대학교 AI컴퓨터공학부 개발동아리</p>
</div>

</td>
Expand Down