이전 포스팅에서는 html 형식으로 이메일 내용을 작성할 때 StringBuilder를 이용해서 추가하는 식으로 html 코드를 작성했다.
하지만 더 깔끔하게 적용할 수 있는 방법은 없을까 생각하다가 Thymeleaf 템플릿을 이용한 방법을 알아냈다.
(세팅도 업데이트 되었으니 이 글 참고 바람)
Thymeleaf 템플릿을 적용하지 않은 코드
private MimeMessage sendEmailMessage(String email, String code) throws Exception { MimeMessage message = emailSender.createMimeMessage(); String code = createKey(); message.addRecipients(MimeMessage.RecipientType.TO, email); message.setSubject("[인증 코드]" + code); message.setText(createHtml(code), "utf-8", "html"); emailSender.send(message); } private String createHtml(String code) { sb.append("<div align=\"center\" style=\"font-size: 15px\">"); sb.append("<br/><img src=\"").append("~").append("\"/>"); sb.append("<br/><br/>~"); sb.append("<br/><br/>인증번호를 입력해 주세요.<br/><br/>"); sb.append("~"); return sb.toString(); }
이제 템플릿 언어를 적용하면 코드가 얼마나 깔끔해는지 살펴 보자
// 이메일 전송
implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '2.5.1'
// 타임리프(이메일 내용 화면)
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
spring:
mail:
host: smtp.gmail.com
port: 587
username: [이메일 계정]
password: [계정 비밀번호]
properties:
mail:
smtp:
auth: true
starttls: # 추가 안하면 SMTPSendFailedException
enalble: true
required: true
타임리프는 따로 설정하지 않아도 된다.
이때 먼저, gmail 계정 보안을 낮춰야 메일 전송이 가능하다
해당 링크에 들어가 설정하고 진행하자!
@Slf4j
@RequiredArgsConstructor
@Service
public class EmailService {
private final JavaMailSender emailSender;
private final SpringTemplateEngine templateEngine;
public void sendEmailMessage(String email) throws Exception {
String code = createCode(); // 인증코드 생성
MimeMessage message = emailSender.createMimeMessage();
message.addRecipients(MimeMessage.RecipientType.TO, email); // 보낼 이메일 설정
message.setSubject("[인증 코드] " + code); // 이메일 제목
message.setText(setContext(code), "utf-8", "html"); // 내용 설정(Template Process)
// 보낼 때 이름 설정하고 싶은 경우
// message.setFrom(new InternetAddress([이메일 계정], [설정할 이름]));
emailSender.send(message); // 이메일 전송
}
private String setContext(String code) { // 타임리프 설정하는 코드
Context context = new Context();
context.setVariable("code", code); // Template에 전달할 데이터 설정
return templateEngine.process("mail", context); // mail.html
}
}
private String createCode() {
// 인증 코드 생성
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
<body>
<div align="center" style="font-size: 15px">
<img src="https://media.vlpt.us/images/ayoung0073/post/090c55bf-79cb-4724-b081-a843a0c3d0c7/springboot.jpeg" width="400" alt=""/>
<br><br>
<span style="border: 1px solid; padding: 8px;font-size: 20px;" th:text="${code}"></span>
</div>
</body>
</html>
@SpringBootTest
class EmailServiceTest {
@Autowired
private EmailService emailService;
@Test
void sendMail() throws Exception {
emailService.sendEmailMessage([보낼 이메일 계정]);
}
}
성공!
다시 한 번 Thymeleaf 적용 여부 차이를 보자!
- Thymeleaf 템플릿을 적용하지 않은 코드
private MimeMessage sendEmailMessage(String email, String code) throws Exception { MimeMessage message = emailSender.createMimeMessage(); String code = createKey(); message.addRecipients(MimeMessage.RecipientType.TO, email); message.setSubject("[인증 코드]" + code); message.setText(createHtml(code), "utf-8", "html"); emailSender.send(message); } private String createHtml(String code) { sb.append("<div align=\"center\" style=\"font-size: 15px\">"); sb.append("<br/><img src=\"").append("~").append("\"/>"); sb.append("<br/><br/>~"); sb.append("<br/><br/>인증번호를 입력해 주세요.<br/><br/>"); sb.append("~"); return sb.toString(); }
- Thymeleaf 템플릿을 적용한 코드
public void sendEmailMessage(String email) throws Exception { String code = createCode(); MimeMessage message = emailSender.createMimeMessage(); message.addRecipients(MimeMessage.RecipientType.TO, email); message.setSubject("[인증 코드] " + code); message.setText(setContext(code), "utf-8", "html"); emailSender.send(message); } private String setContext(String code) { Context context = new Context(); context.setVariable("code", code); return templateEngine.process("mail", context); } }
이렇게 html 코드 쓰는 파일을 따로 생성하는 것이 보기에도 깔끔해보이고, 이메일 화면 수정할 때도 훨씬 편할 듯하다
private String createCode() {
StringBuilder code = new StringBuilder();
Random rnd = new Random();
for (int i = 0; i < 7; i++) {
int rIndex = rnd.nextInt(3);
switch (rIndex) {
case 0:
code.append((char) (rnd.nextInt(26) + 97));
break;
case 1:
code.append((char) (rnd.nextInt(26) + 65));
break;
case 2:
code.append((rnd.nextInt(10)));
break;
}
}
return code.toString();
}