사이먼's 코딩노트

[SpringBoot] 이메일 발송 본문

Java/SpringBoot

[SpringBoot] 이메일 발송

simonpark817 2024. 5. 28. 21:38

[이메일 발송 적용]

  • 웹 페이지를 구현할 때 임시 비밀번호 발송이나 회원가입 완료 시 가입 환영 메일 등과 같이 프로그램에서 메일을 발송하는 기능이 필요할 때가 있을 것이다.
  • 이번에는 위와 같은 이메일 발송 중 구글 지메일을 이용한 방법을 알아봅시다.
  • 앞서 진행했던 SBB 프로그램이 아닌 임시로 만들어 둔 다른 프로젝트를 통해 구현할 예정이기 때문에 코드를 참고하고 싶으시다면 아래 깃허브 리포지터리 주소를 통해 참고 부탁드립니다.
  • 깃허브 리포지터리 주소 : https://github.com/psm817/sb_blog_2405
 

GitHub - psm817/sb_blog_2405

Contribute to psm817/sb_blog_2405 development by creating an account on GitHub.

github.com

 

[SMTP란?]

  • 이메일 발송을 실제로 적용해보기 전에 SMTP에 대한 정의를 간단하게 알아봅시다.
  • SMTP란 Simple Mail Transfer Protocol의 약어로 인터넷 연결을 통하여 이메일을 보낼 때 사용되는 프로토콜(통신규약)을 의미한다,
  • 발신자가 Gmail, Outlook, Express 등을 통해 발신한 이메일을 메일 서버에서 받아서 전달하는과정의 기술 표준으로서 현존하는 거의 모든 이메일 시스템은 SMTP 프로토콜을 사용한다고 생각해도 좋다.
  • SMTP 서버에도 당연히 포트가 존재하는데 예전에는 기본 포트인 25번을 많이 사용하지만 봇넷 스팸 공격에 악용되는 경우가 많아지고 있다보니 요즘은 대용으로 587번을 사용한다.
  • 587 포트는 TLS 연결을 지원하므로 이메일을 더욱 안전하게 보낼 수 있다는 장점을 가지고있다.

 

[라이브러리 추가]

  • 메일 발송을 위한 라이브러리를 먼저 추가해야한다.
  • 웹 브라우저에서 'maven repository'를 검색하여 해당 사이트에 진입한 후, 검색창에 'spring-boot-starter-mail'를 입력하고 가장 상단에 있는 라이브러리를 선택하여 최신버전의 주소를 복사한다.

maven repository에서 라이브러리 검색

 

  • 복사한 주소를 build.gradle 파일에 라이브러리 주소를 붙여넣기를 한 후, 반드시 Load Gradle Changes를 통해 라이브러리 활성화를 해줘야한다. 
// 이메일
implementation 'org.springframework.boot:spring-boot-starter-mail:3.3.0'

 

[Gmail 설정]

  • 이메일 발송을 구현하기 위해 발신자의 이메일 인증과 관련된 정보들을 application.yml 파일에 넣어줘야 한다.
  • 그러기 위해선 먼저 구글 Gmail에서 앱 비밀번호를 생성해야 한다.
  • 생성 방법은 먼저 발신자가 될 계정으로 구글에 로그인을 한 뒤, Google 계정 관리에 진입을 한다.
  • 앱 비밀번호를 받기 위해선 구글 계정의 2차 인증이 완료가 되어있어야 하고, 2차 인증을 확인하는 방법은 아래 사진과 같이 좌측 메뉴에서 '보안'을 선택하여 확인할 수 있다.

2단계 인증 확인하기

 

  • 2단계 인증이 완료됐다면 상단 검색창에 '앱 비밀번호' 를 검색하여 선택과 동시에 본인 인증을 진행한다.
  • 본인 인증이 끝나면 아래와 같이 앱 전용 비밀번호를 만들 수 있는 화면이 나타난다.

앱 비밀번호 진입

 

  • 앱 이름에 본인이 테스트하고자 하는 이름을 작성하고 '만들기' 버튼을 누름과 동시에 아래 사진과 같이 앱 비밀번호가 생성되는 창이 하나 나타난다.
  • 발급된 앱 비밀번호는 복사하여 저장해두고 절대 유출되지 않도록 주의해야 한다.

앱 비밀번호 생성

 

[application.yml 수정]

  • 위에서 앱 비밀번호를 성공적으로 발급받았다면 프로그램의 application.yml 파일에 가서 메일에 대한 설정 정보를 아래 코드와 같이 작성한다.
  • 이 때 username은 반드시 앱 비밀번호를 설정한 Gmail 계정을 작성해야 한다.
  • 한 가지 주의할 점은 application.yml 파일은 깃허브에 그대로 올라가기 때문에 앱 비밀번호가 유출될 수 있는 상황이 발생한다.
  • 그렇기 때문에 application.yml에서는 password를 비워놓고 application-secret.yml에서 메일 설정 코드를 그대로 붙여넣기한 후 거기에 앱 비밀번호를 입력해준다.
  • 앱 비밀번호를 입력할 때는 띄어쓰기가 중간에 들어가면 안된다는 것도 알아야 한다.
mail:
  host: smtp.gmail.com
  port: 587
  username: 5004pp@gmail.com
  password: NEED_TO_INPUT_ON_SECRET   # 지메일 앱 비밀번호
  properties:
    mail:
      smtp:
        auth: true
        starttls:
          enable: true

 

[EmailService.java 생성]

  • 이제는 실제로 이메일 발송 기능을 구현하기 위해 서비스 클래스를 하나 추가해봅시다.
  • 아래는 EmailService.java 클래스를 생성하여 작성한 코드이다.
package com.example.blog.domain.email;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class EmailService {
    private final JavaMailSender mailSender;

    public void send(String to, String subject, String body) {
        MimeMessage mimeMessage = mailSender.createMimeMessage();

        try {
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");

            mimeMessageHelper.setTo(to);                    // 메일 수신자
            mimeMessageHelper.setSubject(subject);          // 메일 제목
            mimeMessageHelper.setText(body, true);      // 메일 본문 내용, HTML 여부
            mailSender.send(mimeMessage);
        }
        catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}
  • send() 메서드는 메일 수신자인 to, 메일 제목인 subject, 메일 내용인 body가 매개변수로 포함되어 인자로부터 해당 정보를 받는다.
  • mail 라이브러리를 통해 내장된 JavaMailSender를 사용하여 mailSender라는 인스턴스를 생성하고, send() 메서드 안에서 새로운 Mimemessage 객체를 생성한다.
  • 예외처리를 위하여 try, catch 문법을 사용하고 try 안에서 MimeMessageHelper를 사용하여 MimeMessage 객체를 쉽게 설정할 수 있도록 돕는다.
  • 두 번째 인자 false는 멀티파트가 아님을, 세 번째 인자 "UTF-8"은 한글이 깨지지 않도록 적용하는 인코딩 방식을 의미한다.
  • mimeMessageHelper.setTo(to), mimeMessageHelper.setSubject(subject)와 같이 수신자와 제목을 설정하고 mimMessageHelper.setText(body, true)는 메일 내용을 설정하는데 해당 내용이 HTML 형식임을 나타내기 때문에 true를 함께 인자로 보낸다.
  • 각 정보들이 세팅되면 mailSender.send(mimeMessage)를 통해 이메일을 전송한다.

 

[MemberController.java 수정]

  • 실제로 프로그램 내에서 회원가입을 마치면 회원가입 때 작성했던 이메일 주소로 환영 메일을 전송하기 위해 컨트롤러를 수정해봅시다.
  • 아래는 MemberController.java 클래스에서 회원가입의 정보를 작성하고 POST 방식으로 요청될 때 메일을 전송하기 위해 추가된 코드이다.
@PostMapping("/signup")
public String signup(@Valid SignForm signForm) {
    memberService.signup(signForm.getUsername(), signForm.getPassword(), signForm.getNickname(), signForm.getEmail());
    emailService.send(signForm.getEmail(), "서비스 가입을 환영합니다!", "회원가입을 축하드립니다^^");

    return "redirect:/member/login";
}
  • 위에서 생성한 EmailService.java 클래스의 send() 메서드를 사용하기 위해 emailService라는 객체를 생성하여 send() 메서드를 호출한다.
  • 인자로 수신자, 제목, 내용을 전달하는데 수신자는 회원가입 때 작성한 메일 주소를 signForm.getEmail()을 통해 가져오고 환영 메일의 제목과 내용을 작성한다.
  • 실제로 회원가입을 진행하면 '회원가입' 버튼을 누름과 동시에 수신자에게 메일이 가는 것을 아래 사진처럼 확인할 수 있다.

이메일 발송 완료

 

반응형