회원관리 기능구현을 위한 학습 두 번째로 이메일을 보내는 기능을 구현해 보자. 이를 위해 SMTP에 대한 개념을 알고 Gmail의 SMTP 서버와 스프링에서 제공하는 이메일 라이브러리를 사용해 보자.
SMTP는 TCP/IP에서 이메일을 주고받는 데 사용되는 통신 프로토콜이다. 일반적으로 POP3/IMAP과 같이 서버에 메시지를 저장하고 내려받을 수 있는 프로토콜을 함께 사용하여 메일 서버를 운영한다.
메일서버는 메일 전송 중 오류가 발생하면 메일 대기열에 보류시키고 메일 재전송을 시도한다. 최종적으로 이메일 전송이 실패하게 될 경우 보낸 사람의 이메일 주소로 반송 이유를 설명하는 반송 메일을 보낸다.
POP3는 원래 컴퓨터 한 대에서만 사용하도록 설계된 프로토콜로 한 방향으로 서버에서 클라이언트로 메일을 내려받는 것만 허용된다. 여러 기기를 사용할 경우 메일을 읽었는지 확인하기 위해서는 별도의 작업이 필요하다.
IMAP는 서버에서 메시지를 저장하는 방식으로 여러 기기에서 동일한 메일을 읽을 수 있다. 서버에서 메일을 관리하기 때문에 메일을 읽었는지 확인할 수 있으며 사용자가 메일을 삭제할 때까지 서버에 저장된다.
Gmail의 SMTP 서버에서는 2022년 5월 30일부터 사용자 이름과 비밀번호만으로 SMTP 서버를 사용할 수 없게 만들었다. SMTP 서버를 사용하려면 2단계 인증을 지원하지 않는 앱에서도 로그인 할 수 있는 앱 비밀번호를 생성해야 한다.
구글 계정의 프로필에서 구글 계정관리 메뉴로 들어간다.
구글 계정관리 화면에서 보안메뉴를 선택하면 2단계 인증을 사용중인지 알 수 있는데 2단계 인증이 사용중지 상태라면 안내에 따라 2단계인증을 진행하도록 한다.
2단계 인증 메뉴로 들어오면 아래에 앱 비밀번호를 생성할 수 있다.
앱 비밀번호를 생성하고 SMTP 라이브러리를 사용할 때 비밀번호 대신 사용하면 된다.
회원 관리 기능 구현 시 스프링 부트 프로젝트 환경에서 구현할 예정이기 때문에 본 게시글은 스프링 부트가 관리해 주는
spring-boot-starter-mail
을 통해 이메일을 보내는 데 필요한 라이브러리들을 사용한다.
implementation 'org.springframework.boot:spring-boot-starter-mail'
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
스프링에서는 보낸 사람, 받는 사람, 참조, 제목, 내용 같은 것만 포함하는 간단한 데이터만 포함하는 SimpleMailMessage와 첨부파일 같은 것을 추가할 수 있는 MimeMessage를 사용할수 있다.
SimpleMailMessage, MimeMessage는 각각 MailSender, JavaMailSender의 send 메서드를 통해 메일을 보내게 되는데 이때 MailSender와 JavaMailSender는 스프링 부트에서 bean으로 자동 등록 해 준다. application.properties(또는 yml)에 설정값을 적어주기만 하면 된다.
// application.properties
spring.mail.host=smtp.gmail.com //구글 SMTP서버 domain
spring.mail.port=587 // SMTP 포트 번호
spring.mail.username="사용자 이메일"
spring.mail.password="구글 앱 비밀번호"
spring.mail.properties.mail.smtp.auth=true // 사용자 인증 true
spring.mail.properties.mail.smtp.starttls.enable=true // TLS를 통해 안전한 통신 사용 true
SimpleMailMessage
@Service
public class SimpleMailMessageService {
private final MailSender mailSender;
public SimpleMailMessageService(MailSender mailSender) {
this.mailSender = mailSender;
}
public void sendEmail(String emailAddress) {
SimpleMailMessage msg = new SimpleMailMessage();
// 받는 사람 이메일
msg.setTo(emailAddress);
// 이메일 제목
msg.setSubject("Test Subject");
// 이메일 내용
msg.setText("this is email test");
try {
// 메일 보내기
this.mailSender.send(msg);
System.out.println("이메일 전송 성공!");
} catch (MailException e) {
throw e;
}
}
}
스프링 부트가 관리하는 MailSender를 주입받고 SimpleMailMessage 객체를 만들어서 받는사람, 제목, 내용을 넣고 MailSender의 send 메서드로 이메일을 보내는 것으로 간단하게 이메일을 전송 할 수 있다.
JavaMailSender와 MimeMessage만으로 메일을 보낼 수 있지만 스프링에서는 MimeMessage를 좀 더 편하게 작성하는 MimeMessageHelper와 메일 작성하는 부분을 메서드로 콜백으로 하는 MimeMessagePreparator 인터페이스를 제공한다.
@Service
public class MimeMessageHelperService {
private final JavaMailSender javaMailSender;
@Autowired
public MimeMessageHelperService(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
public void sendEmail(String email) throws MessagingException {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
// 콜백 메서드 구현
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
// MimeMessageHelper 생성
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// 받는 사람 이메일
helper.setTo(email);
// 이메일 제목
helper.setSubject("MimeMessageHelper Subject");
// 메일 내용
helper.setText("this is MimeMessageHelper test");
// 첨부 파일 추가
ClassPathResource imageResource = new ClassPathResource("images/test.png");
helper.addAttachment("test.png", imageResource);
}
};
try {
// 메일 전송
this.javaMailSender.send(preparator);
} catch (MailException e) {
throw e;
}
}
}
스프링 부트가 관리하는 JavaMailSender를 주입받고 MimePreparator의 prepare 메서드를 오버라이드 한다.
MimeMessage는 MimeMessageHelper를 통해 구성되게 되는데 이때 생성자에서 MimeMessageHelper가 관리할 MimeMessage, 첨부파일 같은 것을 추가하는 멀티파트 모드 여부, 인코딩 방식을 받는다. 받는 사람, 제목, 내용, 첨부파일을 추가하면 JavaMailSender의 send 메서드로 이메일을 보낸다.
스프링에서는 MimeMessagePreparator를 통한 구현을 권장한다.
간단한 메일을 보내는데 설계된 인터페이스 이다. JavaMailSenderImpl로 구현되어 있다.
MailSender를 확장한 인터페이스로 MimeMessage를 보낼 수 있다. JavaMailSenderImpl로 구현되어 있다.
보낸 사람, 받는 사람, 제목, 내용 등을 포함하는 간단한 메일 메시지를 담는 데 사용되는 클래스이다.
MIME 메세지로 파일을 텍스트로 변환하여 보내는 방식으로 메일을 구성하는 클래스이다.
MimeMessage를 동적으로 만드는 prepare 메서드가 있는 콜백 인터페이스이다.
MimeMessage를 편하게 구성하게 해주는 클래스이다.
https://docs.spring.io/spring-framework/reference/integration/email.html
https://www.baeldung.com/spring-email
https://aws.amazon.com/ko/what-is/smtp/
https://docs.cheetahces.com/en-us/messaging/product/01_Overview/Getting_Started/How_Email_Works.htm
https://www.interserver.net/tips/kb/exactly-emails-works-steps-explanation/