본문 바로가기

spring

Spring 메일 전송기능 구현하기

들어가면서

회원가입 시에 이메일 인증 코드를 입력하는 요구사항을 구현하게 되었다. 메일 서비스는 오래전부터 제공하는 서비스이기 때문에 구현된 라이브러리가 있고 테스트를 위한 메일 서버 프로그램 역시 있다. 구현하는 방법을 알아보자!

구현순서

구현에 필요한 순서는 다음과 같다.

  1. 테스트를 위한 메일 서버 가동하기
  2. 라이브러리를 이용한 메일 로직 작성하기

테스트 메일 서버 가동하기

메일을 보내기 위해서는 메일 서버가 필요하지만 실제 서비스되는 메일 서버를 이용하여 개발하거나 테스트를 진행하면 불필요한 메일이 쌓여서 불편하다. 그렇다고 메일 전송 과정을 생략하고 메일 관련 로직을 테스트하기에는 전송 시에 예외가 발생하는 경우를 실행하여 테스트를 할 수 없어서 수동으로 메일이 전송되는지를 확인해야 해서 그리 탐탁지는 않다. 이러한 이유로 로컬 환경에서 가볍게 실행하는 메일 서버가 필요하다.

MailHog : 로컬 시스템용 SMTP 서버로 개발이나 테스트 환경에서 사용하기 좋은 도구

설치 방법

1. 다운받아 설치하기

시스템에서 설치 방법은 다음 링크를 참고해서 설치할 수 있다.

 

MailHog 로 개발/테스트 메일 서버(SMTP EMail Server) 구성하기

 

www.lesstif.com

2. 도커를 통한 설치

도커를 이용해서 다른 리소스를 관리하는 것을 좋아하기 때문에 이 방법을 선택했다.

services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"  # SMTP 포트
      - "8025:8025"  # 웹 인터페이스 포트

메일을 위한 포트는 1025이고 8025는 메일 서버에 접속해서 수신된 이메일을 조회할 수 있다!

메일 로직 작성하기

의존성 추가

스프링에서 제공하는 메일 관련 라이브러리를 추가해 준다.

implementation 'org.springframework:spring-context-support'
implementation 'org.springframework.boot:spring-boot-starter-mail'

Gmail 계정을 이용한 메일 작성

Gmail 계정을 이용하면 Gmail 메일 서버를 통해서 메일을 전송할 수 있다. 이를 구현하는 코드는 다음 링크에서 자세히 설명해서 이 블로그를 참고하는 것이 좋다.

https://www.baeldung.com/spring-email
참고로 여기에서 비밀번호는 구글 계정의 비밀번호가 아니라 새롭게 구글 계정에서 앱을 등록해서 얻을 수 있는 비밀번호이다. 이 관련 설정은 다음 구글 문서를 참고해서 설정해주어야 한다.

 

Sign in with app passwords - Gmail Help

Tip: App passwords aren’t recommended and are unnecessary in most cases. To help keep your account secure, use "Sign in with Google" to connect apps to your Google Account. An app password is a 16-digit passcode that gives a less secure app or device per

support.google.com

Mailhog 테스트 메일 서버를 이용한 메일 작성

메일 서버 관련 설정

메일 서버와 관련된 설정을 해주는 코드를 작성해야 한다. Mailhog와 관련된 설정을 JavaMailSender에 입력해 주는 과정이다.

@Configuration
public class MailConfig {

    @Value("${spring.mail.host}")
    private String host;
    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;
    @Value("${spring.mail.port}")
    private int port;

    @Bean
    public JavaMailSender getJavaMailSender() {
        var mailSender = new JavaMailSenderImpl();

        mailSender.setUsername(username);
        mailSender.setHost(host);
        mailSender.setPort(port);
        mailSender.setPassword(password);

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "localhost");
        props.put("mail.smtp.port", "1025");

        return mailSender;
    }
}

Mailhog에서 호스트는 localhost이고 초기 비밀번호는 없다. 포트는 1025번으로 도커 설정에서 노출한 포트를 적어주었다.

spring:
  mail:
    host: localhost
    username: 반려독
    password:
    port: 1025

메일 전송 서비스 구현

설정한 메일 전송 객체 JavaMailSender를 이용해서 메일을 전송한다. 여기에서 메시지의 이름이 특이하고 Mime는 뭐지 하고 찾아보았다.

MIME(Multipurpose Internet Mail Extensions)란 ?
MIME은 이메일과 함께 동봉할 파일을 텍스트 문자로 전환해서 이메일 시스템을 통해 전달하기 위해 개발되었기 때문에 이름에 Internet Mail Extension가 포함됩니다. 현재는 웹을 통해서 여러 형태의 파일을 전달하는 데 쓰이고 있습니다.

이런 것이구나 하고 알고 코드를 보면 보낸 사람, 목적지, 제목, 내용을 메시지 객체에 입력해 준다.
내용에 html 메시지 형식의 text를 입력하면 메일 서버에서 메시지를 볼 때, html를 통해서 레이아웃을 만들어줄 수도 있다.

@Component
@RequiredArgsConstructor
public class MailService {

    private final JavaMailSender emailSender;

    public void sendEmailAuthCode(String toEmail, String subject) throws MessagingException {

        MimeMessage message = emailSender.createMimeMessage();
        message.setFrom("noreply@gmail.com"); // 보낸 사람
        message.addRecipients(MimeMessage.RecipientType.TO, toEmail); //보낼 이메일 설정
        message.setSubject(subject); //제목 설정
        message.setText("hello", "UTF-8", "html"); // 내용

        emailSender.send(message);
    }
}

 

이렇게 구현하고 테스트를 작성해서 실행을 해본 결과 Mailhog에서 생성한 메일을 수신받을 수 있었다!

예제의 코드에서 타임리프 엔진을 이용해서 html을 랜더링하고 그 문서를 메일 메시지의 text로 입력해서 커스텀하였다.

Reference

https://www.baeldung.com/spring-email

 

Sign in with app passwords - Gmail Help

Tip: App passwords aren’t recommended and are unnecessary in most cases. To help keep your account secure, use "Sign in with Google" to connect apps to your Google Account. An app password is a 16-digit passcode that gives a less secure app or device per

support.google.com

 

Email :: Spring Framework

A class that comes in pretty handy when dealing with JavaMail messages is org.springframework.mail.javamail.MimeMessageHelper, which shields you from having to use the verbose JavaMail API. Using the MimeMessageHelper, it is pretty easy to create a MimeMes

docs.spring.io

 

IO

The Spring Framework provides support for transparently adding caching to an application. At its core, the abstraction applies caching to methods, thus reducing the number of executions based on the information available in the cache. The caching logic is

docs.spring.io

 

GitHub - mailhog/MailHog: Web and API based SMTP testing

Web and API based SMTP testing. Contribute to mailhog/MailHog development by creating an account on GitHub.

github.com