본문 바로가기
IT/Spring boot

[Spring boot] 이메일 전송 구현

by kyu-nahc 2024. 8. 7.
반응형

개발 환경

  • Spring boot 3.1.9
  • Java 17
  • IntelliJ
  • Maven

 

Dependency 추가

- pom.xml 수정

Spring boot를 통해 이메일 인증을 구현하기 위해서는 메일 서버와 연결하기 위한
라이브러리 추가 및 SMTP(프로토콜)에 대한 이해가 필요하다.

  • SMTP 프로토콜 : 네트워크를 통해 전자우편을 전송하는 기술 표준이다.
  • SMTP 서버 : SMTP 프로토콜을 이용해 이메일을 전송하고 수신할 수 있는 메일 서버
  • Spring boot mail starter : 메일 서버와 연결하기 위해 필요한 라이브러리
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

 

pom.xml에 해당 의존성을 추가한다.
의존성 추가 후 Maven Build를 누르면 정상적으로 Build가 된다.

 

Provides transitive vulnerable dependency maven:ch.qos.logback:logback-classic:1.4.11
위와 같은 경고문이 뜬다면 라이브러리 버전이 중첩되는 경우로
의존성을 추가하면 해당 의존성이 가진 의존성도 함께 포함되어서 가져오게 된다.
그렇게 같이 포함되어서 가져오게 된 의존성을
Transitive Dependecy라고 하고 위와 같은 경고문이 뜬다.

경고문이 있는 경우에도 Maven Build를 할 경우 정상적으로 Build가 가능하며
dependencyManagement를 통해 추가적으로 관리를 해주면 된다.

 

Gmail를 통한 application.properties 작성

- application.properties 작성 

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your_email
spring.mail.password=your_password
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true

 

  • host : SMTP 서버 호스트 (Gmail 사용 시 stmp.gmail.com으로 작성)
  • port : SMTP 서버 포트 (Gmail 사용 시 587로 고정)
  • username : Gmail 로그인 아이디
  • password : Gmail 로그인 비밀번호
  • properties.mail.smtp.starttls.enable : true로 설정
  • properties.mail.smtp.starttls.required : true로 설정
  • properties.mail.smtp.auth : true로 설정

만약 application.properties에 하드 코딩하는 것이 아닌 환경변수를 통해 관리하고 싶다면?
아래와 같이 환경변수로 설정하면 된다.

 

환경변수 설정

- Edit Configuration

 

Intellij 우측 상단에 존재하는 Run 왼쪽에 있는 Bar를 클릭한다.
이름은 Server가 아닐수도 있으며 이름 변경을 하지 않았다면 unnamed라 되어있을 것이다.
Bar를 클릭 후 Edit Configuration을 클릭해 준다.

 

- Environment variables 

- 환경 변수 등록 

 

Note 버튼을 클릭 후 + 버튼이 존재한다.
+버튼을 클릭한 후 Name에는 변수명 Value에는 변숫값을 넣어주면 된다.
여러 개도 등록 가능하며 등록 후에는 Ok 버튼을 클릭해 주면 된다.

- 환경변수를 application.properties에서 사용하는 경우 

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=${admin_email}
spring.mail.password=${admin_password}
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true

 

위와 같이 ${} 안에 환경변수의 Name 값을 넣어주면 해당 Value값을 사용할 수 있다.

 

- 환경변수를 Java Class에서 사용하는 경우 

  Map<String,String> env = getenv();
  String password = env.get("password");

 

getenv() 메소드를 통해 환경변수의 key와 value값들을 Map 객체를 통해 받아온다.
환경변수의 Key와 Value는 모두 문자열이다.
get() 메소드를 통해 해당 Key값을 넣어주면 Value 값을 String 객체로 받을 수 있다.

 

 

Controller 및 Service Class 작성

해당 이메일 전송의 코드는 이메일 인증의 기반을 두고 작성하였다.

해당 코드의 계층과 개요는 다음과 같다.

  1. Client(사용자) 쪽에서는 email 인증을 받기 위해 Parameter로 email을 보낸다.
  2. RestController에서는 email을 parameter로 받고 MailService의 메소드를 호출한다.
  3. MailService에서 인증번호를 생성하여 사용자에게 메일로 보낸다.
  4. RestController에서 MailService에서 생성한 인증번호를 Data로 return 한다.
  5. Client(사용자)는 인증번호를 메일로 받고 인증번호를 입력할 것이다.
  6. Client 코드를 통해 사용자가 입력한 인증번호와 Controller에서
    Data로 받은 인증번호를 비교하여 인증을 진행한다.

- MailController

@RestController
@RequestMapping("/mail")
public class MailController {

    private MailService mailService;

    public MailController(MailService mailService){
        this.mailService = mailService;
    }

    @GetMapping("/authenticate")
    public ResponseEntity<String> mailTest(@RequestParam("email") String email){
        return ResponseEntity.ok(mailService.sendMailToUser(email));
    }
}

- MailService

@Service
public class MailService {

    private final JavaMailSender javaMailSender;

    @Value("${admin.send.email}")
    private String ADMIN_SEND_EMAIL;

    public MailService(JavaMailSender javaMailSender){
        this.javaMailSender = javaMailSender;
    }

    public String sendMailToUser(String email){

        String generatedString = RandomStringUtils.randomAlphanumeric(10);
        
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(ADMIN_SEND_EMAIL); // 이메일을 보낼 송신자
        message.setTo(email); // 이메일을 받을 수신자
        message.setSubject("Mail Test"); // 이메일 제목
        message.setText("Authentication String : " + generatedString); // 이메일 본문
        try{
            javaMailSender.send(message);
        }catch(MailException e){
            return null;
        }
        return generatedString;
    }
}

 

 

@Value Annotation
@Value Annotation을 통해 application.properties에 입력한 변수를 사용할 수 있다.
Java Class에 이메일을 하드코딩하는 것은 좋지 않기 때문에
application.properties를 이용하는 것이 좋다.
주의할 점은 아래에 작성한 이메일은

위에서 smtp에서 설정한 이메일과 동일해야 한다는 것이다.

 

 

Mail Test

 

- Controller의 Mapping에 따라 Get 요청으로 보낸다.

 

- MailService에서 생성한 난수가 Data로 return 된다.

 

- 실제 네이버 메일로 들어갔을 때 동일한 난수로 Mail이 오는 것을 알 수 있다.

 

 

 

Exception 처리

- 이메일이 존재하지 않는 경우 

 

만약 보내는 메일이 실제로 존재하지 않는다면 어떻게 될까?
Test를 진행하였을 때 서버에서 난수를 생성하고 메일을 보내는 것은 진된다.
따라서 Exception은 발생하지 않는다.
단 이메일을 보낸 Gmail 계정으로 해당 이메일 주소를 찾을 수 없다고 메일이 온다.
따라서 이메일이 오지 않는다면 다시 재전송할 수 있도록 Front 쪽에서 구현할 필요가 있다.

 

- Try catch / MailException

JavaMailSender 객체의 send() 메소드를 사용 시

이메일 전송과정에서 MailException이 발생할 수 있다.
이는 port번호를 잘못설정하거나 application.properties에서 작성한 이메일 정보가
잘못되었을 경우가 크다. 따라서 해당 MailException에 대해 log를 출력하고 확인할 필요가 있다.
또한 난수를 return 하는 것이 아닌 null을 return 하여 Client 쪽에서 null이 return 되었을 때에는
Error Message를 보여주는 등의 처리가 추가로 필요하다.

 

반응형

loading