[Spring Boot] EMail 보내기

2022. 2. 16. 16:44Spring Boot

반응형

기존 프로젝트를 베타 오픈하기 전에, 피드백을 받는 기능을 추가하면 좋겠다는 생각이 들었다.

일종의 고객센터 같은 느낌?

간단한 입력 form에 작성한 후 보내면, 관리자 계정으로 메일이 오도록 하는 방식을 만들어보자.

 

개발 환경
  • Intelij 2021.2.3
  • Java 17
  • SpringBoot 2.6.3
  • Gradle 1.0.11.RELEASE 

Dependencies는 spring-boot-starter-mail를 사용한다.

필자는 Gmail SMTP Server를 이용해볼 것이다.

(구글 계정만 있다면 무료로 발송할 수 있고, 관리자 계정이 구글이라 겸사겸사..)

 

 

 1. application.properties 설정

 

 

application.properties에 Gmail SMTP Server 설정에 필요한 값들을 추가해주자

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<내 구글 계정>
spring.mail.password=<내 구글 계정 패스워드>
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

해당 설정은 여기를 참고하여 작성하였다.

 

멈춰!

혹시 해당 파일을 그대로 깃헙에 올린다면 세상에 내 구글 계정을 공개 선포하는 것이니

반드시 application.properties 파일은 .gitingore에 추가해주는 것을 잊지 말자.
(이 경우가 아니더라도 해당 파일은 특정한 이유가 없다면 깃에 올리지 않아야 한다..)

 

 

 2. 메일 전송을 위한 기본 부분 구현

 

 

본격적 Mail 관련 서비스를 구현하기 전, 메일 작성을 위한 View, Controller, Dto를 생성해보자.

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Send Mail</title>
</head>
<body>
    <h1>메일 보내기</h1>

    <form th:action="@{/mail/send}" method="post">
        <table>
            <tr>
                <td>메일 주소</td>
                <td>
                    <input type="text" name="address" placeholder="이메일 주소를 입력하세요">
                </td>
            </tr>
            <tr>
                <td>제목</td>
                <td>
                    <input type="text" name="title" placeholder="제목을 입력하세요">
                </td>
            </tr>
            <tr>
                <td>내용</td>
                <td>
                    <textarea name="content" placeholder="보낼 내용을 입력하세요"> </textarea>
                </td>
            </tr>
        </table>
        <button>발송</button>
    </form>

</body>
</html>

SendMail.html

 

package com.jimin.SnsPractice.Controller;

import com.jimin.SnsPractice.Dto.MailDto;
import com.jimin.SnsPractice.Service.EmailService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class MainController {

    private final EmailService emailService;

    public MainController(EmailService emailService) {
        this.emailService = emailService;
    }

    @GetMapping("/mail/send")
    public String main() {
        return "SendMail.html";
    }

    @PostMapping("/mail/send")
    public String sendMail(MailDto mailDto) {
        emailService.sendSimpleMessage(mailDto);
        System.out.println("메일 전송 완료");
        return "AfterMail.html";
    }
}

MainController.java

 

package com.jimin.SnsPractice.Dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class MailDto {
    private String address;
    private String title;
    private String content;
}

MailDto.java

 

 

반응형

 

 

3. JavaMailSender 와  SimpleMailMessage 를 이용한 메일 발송

 

 

Mail Server 속성에 있는 두 녀석을 사용한 Service를 만들어 메일을 발송해보자.

package com.jimin.SnsPractice.Service;

import com.jimin.SnsPractice.Dto.MailDto;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
@AllArgsConstructor
public class EmailService {

    private JavaMailSender emailSender;

    public void sendSimpleMessage(MailDto mailDto) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("2kwon2lee@gmail.com");
        message.setTo(mailDto.getAddress());
        message.setSubject(mailDto.getTitle());
        message.setText(mailDto.getContent());
        emailSender.send(message);
    }
}

위 코드에서 사용한 것을 포함하여 Mail Server의 속성들에 대해 간단히 알아보고 가보자

Mail Server Properties
  • MailSenderinterface
    간단한 전자 메일을 보낼 수 있는 기본 기능을 제공하는 최상위 인터페이스
  • JavaMailSenderinterface
    위의 MailSender의 하위 인터페이스.
    MIME 메시지를 지원하며 대부분 MIMEMessage와 함께 사용.
    MimeMessage를 만들기 위한 도우미 클래스

  • JavaMailSenderImplclass
    JavaMailSender 인터페이스의 구현을 제공
    MimeMessage 및 SimpleMailMessage를 지원

  • SimpleMailMessageclass
    발신인, 수신인, 참조인, 제목 및 텍스트 필드를 포함한 간단한 메일 메시지를 작성하는 데 사용
  • MimeMessagePreparatorinterface
    MIME 메시지를 준비하기 위한 콜백 인터페이스를 제공
  • MimeMessageHelperclass
    MIME 메시지를 만들기 위한 클래스
    HTML 레이아웃에서 이미지, 일반적인 메일 첨부 파일 및 텍스트 내용을 지원
MIME이란?
Multipurpose Internet Mail Extensions의 약자이다.
기존 UUEncoding 방식은 ASCII(텍스트) 파일만 지원하여 음악, 워드 파일 등의 바이너리 파일을 전송할 수 없음
이러한 방식을 보안하여 나온 인코딩 방식이다.

 

 

 4. 메일 전송 TEST

 

 

자 이제 프로젝트를 실행해서 메일이 보내지는지 테스트할 차례다...! 두근두근

http://localhost:8080/mail/send

과연..?

.

.

.

응 어림도없지~

얼핏 읽어보면 유저와 유저 비번이 일치하지 않는다는 글이 보인다.

헌데 나는 제대로 기입했는데? 무슨일이지? 하고 찾아봤더니

구글에서 "보안수준이 낮은 앱의 액세스"에 대해 기본적으로 막아두고 있었기 때문이었다.

 

 

구글 계정관리 보안 탭을 클릭한 후

 

해당 액세스를 허용해주고 다시 보낸다면?

 

 

 

 

내가 지정한 이메일로 메일이 온 것을 확인할 수 있다!

 

 

불편....

다만, 구글에서도 기본 값으로 권장하고 있는 앱의 액세스를 계속 허용해두고 있는 점이 상당히 거슬린다.

개인 프로젝트에서 경험상 해보는 것이라면 여기서 끝내는 것도 좋지만,

필자는 배포될 프로젝트에 "위험을 감수하고 사용"하고 싶진 않기 때문에 다른 방법을 찾아보았다.

 

 

 5. 앱 비밀번호를 통한 로그인 설정

 

 

Spring boot 실행창에 오류 로그에 있는 링크를 클릭하면 나온다.

https://support.google.com/mail/?p=BadCredentials 

 

다른 이메일 플랫폼을 통해 Gmail 확인하기 - Gmail 고객센터

도움이 되었나요? 어떻게 하면 개선할 수 있을까요? 예아니요

support.google.com

아까 콘솔에 뜬 링크를 눌러보면 "앱 비밀번호"로 로그인하라며 해결 방안을 친절하게 제시해준다.

이 방식을 사용해보자.

 

앱 비밀번호를 사용하기 위해선 2단계 인증이 필요하다.

보안 탭에서 2단계 인증을 사용하도록 하자. 메시지 인증코드만 하면 간단하니 방법은 패스~

 

인증이 완료됐다면 이제 드디어 앱 비밀번호를 설정할 수 있다..!

현재 Windows 컴퓨터를 사용하고 있으므로 해당 탭을 선택하면

부여받은 앱 비밀번호를 application.propertiesspring.mail.password에 기입하면 끝!

 

 

생각보다 쉽고 간편하니 많이 애용할 수 있겠다 :)

 

 

++) 두 번째 시리드 업로드 했습니다!

https://born2bedeveloper.tistory.com/68

 

[Spring Boot] 이메일 보내기 (2) - 참조(cc), 첨부 파일

꽤 오래전에 구글 SMTP 서버를 이용한 Email 전송에 관한 내용을 다룬 적이 있었는데, 생각보다 조회수가 매우 높았다. 아마 이메일 전송이 부가적인 기능으로 다양하게 사용되기 떄문이겠지? 새로

born2bedeveloper.tistory.com

 

 

 

 

[참고 사이트]

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

https://victorydntmd.tistory.com/342