Spring Boot 비동기 메일 전송 구현 (구글 메일)
잠든여우
2021. 10. 9. 20:37
 URL 복사

이전 글을 작성하다가 다른 사이트에서는

메일이 전송될때 지연시간이 없어요.

 

그런데 제가 구현한 메일 전송에서는 지연시간이 발생해서

이 문제를 수정하려고 합니다.

 

지연시간을 없애는 방법은 비동기 처리하여

눈으로 보기에는 지연시간이 없다고 느끼게 됩니다.

 

메일 전송에 대한 기본적인 내용은

이전 글에서 미리 보고오시면 좋아요!

Spring Boot 메일 전송 구현 (구글 메일)

 

비동기 처리를 위해 3개 파일에서 부분적으로 수정했어요.

MailauthApplication.java

MailauthController.java

MailService.java

 

이렇게 위에 세가지 부분을 수정했어요.

 

먼저 MailService.java 를 수정했어요.

 

src/main/java/com/mailauth/MailService.java

package com.mailauth;

import java.util.concurrent.ThreadLocalRandom;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Repository;

@Repository
public class MailService {

	@Autowired
	private JavaMailSender javaMailSender;

	@Async
	public void sendMail( String strTo ) {
		// 받는사람을 담을 변수 선언
		String to = strTo;
		
		try {
			// 텍스트로 구성된 메일을 생성할때
			SimpleMailMessage simpleMessage = new SimpleMailMessage();
			
			// 인증키 6자리 랜덤으로 생성 후 초기화
			String authKey = Integer.toString( ThreadLocalRandom.current().nextInt(100000, 1000000) );
			
			// 받는사람 설정
			simpleMessage.setTo( to );
			
			// 제목
			simpleMessage.setSubject("[메일 인증] ㅇㅇㅇㅇ에서 인증번호를 보냈습니다.");
			
			// 메일 내용
			simpleMessage.setText("인증번호는 " + authKey + " 입니다.\n정확하게 입력해주세요.");
			
			System.out.println(javaMailSender);
			// 메일 발송
			javaMailSender.send(simpleMessage);
		} catch (MailException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

수정된 부분은 public int였던것을 public void로 바꿔서

return 값을 제거해줬어요.

 

그리고 @Async를 추가해서 비동기 처리로 바꿨어요.

 

이제 MailauthController.java 를 수정할게요.

 

src/main/java/com/mailauth/MailauthController.java

package com.mailauth;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;


@Controller
public class MailauthController {	
	
	@Autowired
	MailService ms;
	
	/* main */
	@RequestMapping( {"/main.do", "/"} )
	public ModelAndView main() {
		System.out.println( "main() 호출" );
		
		ModelAndView modelAndView = new ModelAndView( "index" );
		return modelAndView;
	}
	/* mail_ok */
	@RequestMapping( "/mail_ok.do" )
	public ModelAndView mail_ok(HttpServletRequest req) {
		System.out.println( "mail_ok() 호출" );
	    ms.sendMail( req.getParameter( "email" ) );
		
		ModelAndView modelAndView = new ModelAndView( "mail_ok" );
		return modelAndView;
	}
}

 

컨트롤러에서는 mail_ok.do부분을 수정했어요.

return되는 값이 없으니

ms.sendMail( req.getParameter( "email" ) );로 수정

그리고 결과값을 mail_ok로 보내줬던 코드를 제거

 

이렇게 컨트롤러를 수정했어요.

 

그리고 마지막으로 Application을 수정할게요.

 

src/main/java/com/mailauth/MailauthApplication.java

package com.mailauth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@SpringBootApplication
public class MailauthApplication {

	public static void main(String[] args) {
		SpringApplication.run(MailauthApplication.class, args);
	}
}

 

Application에서는 어노테이션만 추가했어요.

@EnableAsync를 추가해서 비동기 처리를 가능하게 해줬어요.

 

마지막으로 views에 있는 mail_ok.jsp를 수정할게요.

src/main/webapp/WEB-INF/views/mail_ok.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<script type="text/javascript">
	alert('메일이 전송이 완료되었고\n메일이 오지않을경우 다시시도해주세요.');
	location.href="/main.do";
</script>

 

위에 코드로 짧게 수정되었습니다.

결과값을 받는 로직이 아닌 스크립트로 바로 처리 후

비동기 처리로 메일을 전송하는 방식을 택했어요.

 

결과는 아래와 같습니다.

이번 결과는 메일을 미리 적어놓았고

메일 전송 버튼을 누르면 alert창을 띄웁니다.

위 메시지가 뜨고 다서 메일 입력창으로 돌아갑니다.

 

제가 생각하는 메일 전송은 전송만 할수 있지만

데이터베이스를 연동하고, 메일 전송과

메일 인증까지 진행할 예정입니다.

 

이 글을 작성하는데 참고했던 글은 아래와 같아요.

메일 비동기 전송하는 법

 

이 글에서 작성했던 코드는 github에서 확인가능

코드저장소 ( github )

'Spring' 카테고리의 다른 글

Spring Boot 메일 전송 구현 (구글 메일)  (0) 2021.10.06
Spring Boot 메일 전송 구현 (구글 메일)
잠든여우
2021. 10. 6. 15:44
 URL 복사

학원에서 Spring Boot로 팀 프로젝트를 진행하면서 구현한

몇 가지 기능 중에 메일 전송을 구현해 보도록 할게요.

 

구글 메일을 사용하였고, 메일 설정, 보안 수준,

사용한 코드, 참고 문서 순서로 정리할게요.

 

구글 메일을 먼저 설정할게요.

(설정에 계정 정보를 적어서 새로운 계정 만들어서 진행)

 

오른쪽 상단에 설정에서 메일 설정을 진행할 테니

설정을 눌러주세요 (톱니바퀴)

 

펼쳐진 설정화면에서 "모든 설정 보기"를 눌러주세요.

 

기본 설정, 라벨 등등 여러 가지 설정들이 있는데

여기서 "전달 및 POP/IMAP"탭으로 이동하고,

모든 메일에서 POP 사용하기

IMAP 사용

 

아래에 사진을 보고 선택된 부분을 알맞게 바꿔주세요.

 

보안 수준이 낮은 앱 허용을 사용으로 변경 합니다.

보안 수준이 낮은 앱 변경하러가기

 

이렇게 보안 수준이 낮은 앱까지 허용하고 나면

구글 쪽 설정은 끝났고, 이제 코드를 작성하러 갑니다.

 

프로젝트를 생성 후 먼저 pom.xml에 추가해요.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

 

그리고 메일 설정과 tomcat 설정을 조금 해줄 거예요.

 

src/main/resources/application.properties

# tomcat setting
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

# mail setting
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=[방금 설정한 메일]
spring.mail.password=[방금 설정한 메일 비밀번호]
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.auth=true

 

application.properties에 코드를 추가한 후

jsp 파일을 만들어주세요.

 

만들 파일 리스트 :

index.jsp

mail_ok.jsp

 

src/main/webapp/WEB-INF/views/index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form method="get" action="/mail_ok.do" name="mailFrm">
		<input type="text" name="email" placeholder="받는사람" />
		<input type="submit" value="메일 전송" />
	</form>
</body>
</html>

 

src/main/webapp/WEB-INF/views/mail_ok.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	int flag = (Integer)request.getAttribute("auth");
	System.out.println( flag );
	out.println( "<script type='text/javascript'>" );
	if( flag == 0 ) {
		out.println("alert('메일 전송에 실패하였습니다.');");
		out.println("history.back();");
	} else if( flag == 1 ) {
		out.println("alert('메일이 전송되었습니다.');");
		out.println("location.href='/main.do';");
	}
	out.println( "</script>" );
%>

 

views 폴더 안에 jsp 파일을 추가하고

컨트롤러파일에서 매핑을 해줘요.

 

src/main/java/com/mailauth/MailauthController.java

package com.mailauth;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MailauthController {	
	
	@Autowired
	MailService ms;

	/* main */
	@RequestMapping( {"/main.do", "/"} )
	public ModelAndView main() {
		System.out.println( "main() 호출" );
		
		ModelAndView modelAndView = new ModelAndView( "index" );
		return modelAndView;
	}
	/* mail_ok */
	@RequestMapping( "/mail_ok.do" )
	public ModelAndView mail_ok(HttpServletRequest req) {
		System.out.println( "mail_ok() 호출" );
		int result = ms.sendMail( req.getParameter( "email" ) );

		ModelAndView modelAndView = new ModelAndView( "mail_ok" );
		modelAndView.addObject( "auth", result );
		return modelAndView;
	}
}

 

메일을 전송을 담당할 파일을 만들어야 해요.

MailService.java 파일을 생성해요.

 

src/main/java/MailService.java

package com.mailauth;

import java.util.concurrent.ThreadLocalRandom;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Repository;

@Repository
public class MailService {

	@Autowired
	private JavaMailSender javaMailSender;
	
	public int sendMail( String strTo ) {
		// 받는사람을 담을 변수 선언
		String to = strTo;
		/*
		 * flag = 0 실패
		 * flag = 1 성공
		 * */
		int flag = 0;
		
		try {
			// 텍스트로 구성된 메일을 생성할때
			SimpleMailMessage simpleMessage = new SimpleMailMessage();
			
			// 인증키 6자리 랜덤으로 생성 후 초기화
			String authKey = Integer.toString( ThreadLocalRandom.current().nextInt(100000, 1000000) );
			
			// 받는사람 설정
			simpleMessage.setTo( to );
			
			// 제목
			simpleMessage.setSubject("[메일 인증] ㅇㅇㅇㅇ에서 인증번호를 보냈습니다.");
			
			// 메일 내용
			simpleMessage.setText("인증번호는 " + authKey + " 입니다.\n정확하게 입력해주세요.");
			
			System.out.println(javaMailSender);
			// 메일 발송
			javaMailSender.send(simpleMessage);
			flag = 1;
		} catch (MailException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return flag;
	}
}

 

실행할땐 MailauthApplication.java를 실행 후

브라우저에서 localhost:8080/main.do로 접속하면

위에 화면처럼 뜨고 여기서 받는 사람을 입력하고

메일 전송 버튼을 누르면 메일이 전송됩니다.

 

그리고 입력한 메일에 로그인하여 메일을 확인하면

위에 사진처럼 메일이 도착하고

내용에 인증번호가 메일에 포함되어 있어요.

 

이러한 방법으로 메일 인증을 구현하려면

저는 이렇게 구현했습니다.

 

먼저 메일 인증에 필요한 DB 테이블을 생성하고

 

메일 전송을 하기 전에 이 테이블에 입력한 메일과,

생성된 인증번호를 넣고 메일 전송 준비를 합니다.

 

그리고 메일을 받은 사용자는 입력란에

인증번호를 입력하고 인증 확인을 누르면

인증 테이블로 가서 입력한 데이터로 조회하고

데이터가 있으면 인증 성공 조회된 데이터가 없다면

인증 실패로 구분되도록 구현했습니다.

 

글을 올리고 문제를 발견했습니다.

 

사이트에서 메일 인증을 할때

지연시간이 없었는데 구현했더니

지연시간이 생겼습니다.

 

이를 보완한 글을 다시 작성해서 링크걸었어요.

Spring Boot 비동기 메일 전송 구현 (구글 메일)

 

이 글을 작성하면서 참고한 사이트 및 코드 저장소

 

1. Spring Boot 메일 전송

 

2. JAVA 6자리 랜덤숫자 생성

 

코드 저장소 github (mailauth)

'Spring' 카테고리의 다른 글

Spring Boot 비동기 메일 전송 구현 (구글 메일)  (0) 2021.10.09

+ Recent posts