이메일 전송하기 -SMTP

정민·2023년 12월 2일
1
post-thumbnail

회원관리 기능구현을 위한 학습 두 번째로 이메일을 보내는 기능을 구현해 보자. 이를 위해 SMTP에 대한 개념을 알고 Gmail의 SMTP 서버와 스프링에서 제공하는 이메일 라이브러리를 사용해 보자.

1. SMTP(Simple Mail Transfer Protocol)는 무엇일까

SMTP는 TCP/IP에서 이메일을 주고받는 데 사용되는 통신 프로토콜이다. 일반적으로 POP3/IMAP과 같이 서버에 메시지를 저장하고 내려받을 수 있는 프로토콜을 함께 사용하여 메일 서버를 운영한다.

메일서버가 동작하는 순서

  • 사용자는 메일서버로 보낼 메일을 전송한다.
  • 메일서버는 어디로 메일을 보내야 하는지 DNS를 통해 IP를 조회하고 해당하는 메일서버로 메일을 전송한다.
  • 메일을 받은 서버는 메일박스에 메일을 저장해두었다가 메일을 수신받는 사용자가 POP3 또는 IMAP를 통해 메일을 요청하면 메일을 전송한다.

메일서버는 메일 전송 중 오류가 발생하면 메일 대기열에 보류시키고 메일 재전송을 시도한다. 최종적으로 이메일 전송이 실패하게 될 경우 보낸 사람의 이메일 주소로 반송 이유를 설명하는 반송 메일을 보낸다.

POP3(Post Office Protocol 3)

POP3는 원래 컴퓨터 한 대에서만 사용하도록 설계된 프로토콜로 한 방향으로 서버에서 클라이언트로 메일을 내려받는 것만 허용된다. 여러 기기를 사용할 경우 메일을 읽었는지 확인하기 위해서는 별도의 작업이 필요하다.

IMAP(Internet Message Access Protocol)

IMAP는 서버에서 메시지를 저장하는 방식으로 여러 기기에서 동일한 메일을 읽을 수 있다. 서버에서 메일을 관리하기 때문에 메일을 읽었는지 확인할 수 있으며 사용자가 메일을 삭제할 때까지 서버에 저장된다.

2. Gmail SMTP Server 사용

Gmail의 SMTP 서버에서는 2022년 5월 30일부터 사용자 이름과 비밀번호만으로 SMTP 서버를 사용할 수 없게 만들었다. SMTP 서버를 사용하려면 2단계 인증을 지원하지 않는 앱에서도 로그인 할 수 있는 앱 비밀번호를 생성해야 한다.

Gmail SMTP 서버를 사용하기 위한 설정

2단계 인증 활성화

구글 계정의 프로필에서 구글 계정관리 메뉴로 들어간다.

구글 계정관리 화면에서 보안메뉴를 선택하면 2단계 인증을 사용중인지 알 수 있는데 2단계 인증이 사용중지 상태라면 안내에 따라 2단계인증을 진행하도록 한다.

앱 비밀번호 생성

2단계 인증 메뉴로 들어오면 아래에 앱 비밀번호를 생성할 수 있다.

앱 비밀번호를 생성하고 SMTP 라이브러리를 사용할 때 비밀번호 대신 사용하면 된다.

3. 스프링 부트에서 SMTP 사용하기

회원 관리 기능 구현 시 스프링 부트 프로젝트 환경에서 구현할 예정이기 때문에 본 게시글은 스프링 부트가 관리해 주는 spring-boot-starter-mail을 통해 이메일을 보내는 데 필요한 라이브러리들을 사용한다.

gradle

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

Maven

<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 메서드로 이메일을 보내는 것으로 간단하게 이메일을 전송 할 수 있다.

MimeMessage

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를 통한 구현을 권장한다.

스프링에서 제공하는 클래스, 인터페이스 정리

MailSender

간단한 메일을 보내는데 설계된 인터페이스 이다. JavaMailSenderImpl로 구현되어 있다.

JavaMailSender

MailSender를 확장한 인터페이스로 MimeMessage를 보낼 수 있다. JavaMailSenderImpl로 구현되어 있다.

SimpleMailMessage

보낸 사람, 받는 사람, 제목, 내용 등을 포함하는 간단한 메일 메시지를 담는 데 사용되는 클래스이다.

MimeMessage

MIME 메세지로 파일을 텍스트로 변환하여 보내는 방식으로 메일을 구성하는 클래스이다.

MimeMessagePreparator

MimeMessage를 동적으로 만드는 prepare 메서드가 있는 콜백 인터페이스이다.

MimeMessageHelper

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/

https://support.microsoft.com/ko-kr/office/pop%EC%99%80-imap%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%94%EA%B0%80%EC%9A%94-85c0e47f-931d-4035-b409-af3318b194a8

https://kdevkr.github.io/gmail-smtp/

0개의 댓글