HTML 이메일 전송하기
- MimeMessage 전송
- MimeMessageHelper: MimeMessage 만들 때 사용할 수 있는 유틸리티
EmailService 인터페이스
- void sendEmail(EmailMessage emailMessage);
EmailService 인터페이스 구현체
- ConsoleEmailService: 콘솔 출력
- HtmlEmailService: JavaMailSender를 사용해서 HTML로 이메일 전송
우리는 지금까지 SimpleMailMessage로 사용해서 보냈지만 실제로 특정한 웹서비스 에서 보내는 이메일은 대부분 HTML로 만들어진 이메일이다. HTML로 만들어진 이메일을 보내려면 MIME 메시지로 보내야 한다.
package me.weekbelt.studyolle.account;
@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final JavaMailSender javaMailSender;
private final PasswordEncoder passwordEncoder;
private final ModelMapper modelMapper;
// .................
public void sendSignUpConfirmEmail(Account newAccount) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(newAccount.getEmail());
mailMessage.setSubject("스터디올래, 회원 가입 인증");
mailMessage.setText("/check-email-token?token=" + newAccount.getEmailCheckToken() + "&email=" + newAccount.getEmail());
javaMailSender.send(mailMessage);
}
// ................
}
package me.weekbelt.studyolle.account;
@Slf4j // 로깅메시지를 위해 추가
@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {
// ...........
public void sendSignUpConfirmEmail(Account newAccount) throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper =
new MimeMessageHelper(mimeMessage, false, "UTF-8");
mimeMessageHelper.setTo(newAccount.getEmail());
mimeMessageHelper.setSubject("스터디올래, 회원 가입 인증");
mimeMessageHelper.setText("/check-email-token?token=" + newAccount.getEmailCheckToken() +
"&email=" + newAccount.getEmail(), false);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
log.error("failed to send email", e);
}
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(newAccount.getEmail());
mailMessage.setSubject("스터디올래, 회원 가입 인증");
mailMessage.setText("/check-email-token?token=" +
newAccount.getEmailCheckToken() + "&email=" + newAccount.getEmail());
javaMailSender.send(mailMessage);
}
// .............
}
위 코드 처럼 실제로 메일을 보낼때는 MimeMessage로 보내고 로컬로 보낼때는 SimpleMailMessage로 보내려고 하면 번거롭기 때문에 EmailService를 추상화 해야 한다.
EmailService 인터페이스 생성
package me.weekbelt.studyolle.mail;
public interface EmailService {
void sendEmail(EmailMessage emailMessage);
}
EmailMessage DTO 생성
package me.weekbelt.studyolle.mail;
@Data
@Builder
public class EmailMessage {
private String to;
private String subject;
private String message;
}
로컬과 실제로 보낼 이메일 처리를 위한 EmailService의 구현체 생성
로컬을 위한 서비스
package me.weekbelt.studyolle.mail;
@Slf4j
@Profile("local")
@Component
public class ConsoleEmailService implements EmailService{
@Override
public void sendEmail(EmailMessage emailMessage) {
log.info("sent email: {}" + emailMessage.getMessage());
}
}
실제 HTML 이메일을 보내는 구현체
package me.weekbelt.studyolle.mail;
@Slf4j
@RequiredArgsConstructor
@Profile("dev")
@Component
public class HtmlEmailService implements EmailService{
private final JavaMailSender javaMailSender;
@Override
public void sendEmail(EmailMessage emailMessage) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper =
new MimeMessageHelper(mimeMessage, false, "UTF-8");
mimeMessageHelper.setTo(emailMessage.getTo());
mimeMessageHelper.setSubject(emailMessage.getSubject());
mimeMessageHelper.setText(emailMessage.getMessage(), false); // 지금은 html이 아니므로 false
javaMailSender.send(mimeMessage);
log.info("sent email: {}", emailMessage.getMessage());
} catch (MessagingException e) {
log.error("failed to send email", e);
}
}
}
ConsoleMailSender 삭제
JavaMailSender를 추상화한 EmailService로 대체
package me.weekbelt.studyolle.account;
@Slf4j
@Transactional
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {
// ....
// private final JavaMailSender javaMailSender;
private final EmailService emailService; // 대체
// ....
public void sendSignUpConfirmEmail(Account newAccount) throws MessagingException {
EmailMessage emailMessage = EmailMessage.builder()
.to(newAccount.getEmail())
.subject("스터디올래, 회원 가입 인증")
.message("/check-email-token?token=" + // message는 나중에 HTML로 수정
newAccount.getEmailCheckToken() + "&email=" + newAccount.getEmail())
.build();
emailService.sendEmail(emailMessage);
}
// ....
public void sendLoginLink(Account account) {
account.generateEmailCheckToken();
EmailMessage emailMessage = EmailMessage.builder()
.to(account.getEmail())
.subject("스터디올래, 로그인 링크")
.message("/login-by-email?token=" + account.getEmailCheckToken() + // message는 나중에 HTML로 수정
"&email=" + account.getEmail())
.build();
emailService.sendEmail(emailMessage);
}
// ......
}
깨진 테스트 수정
package me.weekbelt.studyolle.account;
@Transactional
@AutoConfigureMockMvc
@SpringBootTest
class AccountControllerTest {
// .......
//@MockBean JavaMailSender javaMailSender;
@MockBean EmailService emailService; // 대체
// ........
@DisplayName("회원 가입 처리 - 입력값 정상")
@Test
public void signUpSubmit_with_correct_input() throws Exception {
//......
then(emailService).should().sendEmail(any(EmailMessage.class)); // 수정
}
// ........
}
참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#
'스프링과 JPA 기반 웹 어플리케이션 개발 > 3부 개발 환경 설정' 카테고리의 다른 글
45. HTML 이메일 전송하기 (0) | 2020.04.23 |
---|---|
42. 인텔리J 데이터베이스 탭 (0) | 2020.04.23 |
41. MySql 설정 (0) | 2020.04.23 |