본문 바로가기
Back-End/Spring

Spring Boot에서 메일 발송하기(Google SMTP)

by 달의 조각 2022. 9. 17.
회원가입을 하면 이메일로 회원가입 성공 메시지를 전송할 수 있다!
전체 로직: 클라이언트 > Controller Post 요청 > Service의 회원가입 로직 > Event 발행 > Email 전송 로직 실행

 

0. Google 앱 비밀번호 발급

Google 계정 관리 > 2단계 인증 활성화 > 앱 비밀번호 > 메일, Windows 컴퓨터로 지정하고 발급

 

1. 의존성 추가

//build.gradle
implementation 'org.springframework.boot:spring-boot-starter-mail'

 

2. Gmail SMTP 설정 추가

//application-local.yml
mail:
  smtp:
    host: smtp.gmail.com
    port: 587
    username: ${EMAIL_USERNAME} //Gmail email
    password: ${EMAIL_PASSWORD} //Google 계정 2단계 인증 생성 후 앱 비밀번호 생성
    auth: true
    starttls:
      enable: true //일부 SMTP 서버에는 TLS 연결이 필요하므로 TLS 보호 연결을 활성화한다
  subject:
    member:
      registration: Thank you for joining our cafe!

 

3. 메일 전송을 위한 구성

  • 📗 MailSender: 이메일 전송을 위한 기본 기능을 제공하는 최상위 인터페이스이다.
  • 📗 JavaMailSender: MailSender의 하위 인터페이스
    MIME 메시지를 지원하며 이를 생성하기 위해 MimeMessageHelper 클래스와 함께 사용된다.
  • 📄 JavaMailSendImpl: MimeMessage 및 SimpleMailMessage를 지원한다.
    SMTP 서버를 지정하는 데에 필요한 메일 속성을 정의한다.
  • 📄 SimpleMailMessage: 보낸 사람, 받는 사람, 참조, 제목 및 텍스트를 포함하는 메시지를 만드는 데에 사용된다.
  • 📗 MimeMessagePreparator: MIME 메시지 준비를 위한 콜백 인터페이스이다.
  • 📄 MimeMessageHelper: MIME 메시지 생성을 위한 도우미 클래스이다. HTML 레이아웃 등의 지원을 제공한다.

 


 

📄 MemberRegistrationEventListener

회원 가입 요청이 들어오면 EamilSender의 sendEmail 메서드에 이메일, 제목, 메시지를 파라미터로 넘긴다.

@EnableAsync
@Configuration
@Component
@Slf4j
public class MemberRegistrationEventListener {
    @Value("${mail.subject.member.registration}") //"Thank you for joining our cafe!" 메시지 주입
    private String subject;
    private final EmailSender emailSender;
    private final MemberService memberService;

    public MemberRegistrationEventListener(EmailSender emailSender, MemberService memberService) {
        this.emailSender = emailSender;
        this.memberService = memberService;
    }

    @Async
    @EventListener
    public void listen(MemberRegistrationApplicationEvent event) throws Exception {
        try {
            String[] to = new String[]{event.getMember().getEmail()};
            String message = event.getMember().getEmail() + "님, 회원 가입이 성공적으로 완료되었습니다.";
            emailSender.sendEmail(to, subject, message);
        } catch (MailSendException e) {
            e.printStackTrace();
            log.error("MailSendException: rollback for Member Registration:");
            Member member = event.getMember();
            memberService.deleteMember(member.getMemberId());
        }
    }
}

 

📄 EmailSender

sendEmail 메서드는 EmailSendable의 send 메서드를 호출한다.

@Service
public class EmailSender {
    private final JavaMailSender mailSender;
    private final EmailSendable emailSendable;

    public EmailSender(JavaMailSender mailSender, EmailSendable emailSendable) {
        this.mailSender = mailSender;
        this.emailSendable = emailSendable;
    }

    public void sendEmail(String[] to, String subject, String message) throws MailSendException, InterruptedException {
        emailSendable.send(to, subject, message);
    }
}

 

📗 EmailSendable

이메일 전송을 위한 기본 기능을 제공하는 최상위 인터페이스이다.
구현체: MockEmailSendable, MockExceptionEmailSendable, SimpleEmailSendable, TemplateEmailSendable

@Component
public interface EmailSendable {
    void send(String[] to, String subject, String message) throws InterruptedException;
}

 

📄 SimpleEmailSendable

첨부 파일 없이 간단한 이메일 메시지를 작성한다. 많은 SMTP 서버에서는 from address를 제공하지 않으면 메시지를 거부한다.

@Slf4j
public class SimpleEmailSendable implements EmailSendable {
    private final JavaMailSender javaMailSender;

    public SimpleEmailSendable(JavaMailSender javaMailSender) {
        this.javaMailSender = javaMailSender; //MailSender 인터페이스를 상속받으며, MIME을 지원한다
    }

    @Override
    public void send(String[] to, String subject, String message) {
        // 보낸 사람, 받는 사람, 참조, 제목 및 텍스트를 포함하는 메시지를 만든다
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setTo(to); //받는 사람 주소
        mailMessage.setText(message); //보내는 사람 주소(호출하지 않으면 yml의 username으로 세팅)
        mailMessage.setSubject(subject); //제목
        mailMessage.setText(message); //메시지 내용
        javaMailSender.send(mailMessage); //메일 발송

        log.info("Sent simple email!");
    }
}

 

 

📚 Reference

 

대략적인 흐름은 파악했으나, EmailSendable 구현 클래스들 각각의 이해가 더 필요함

댓글