프로젝트에서 일반 회원가입에서 회원의 인증을 위해서 이메일 인증 기능을 넣게 되었다. 기능을 구현하면서 진행했던 절차들을 정리해보도록 하겠다.
google SMTP 서버, Naver SMTP 서버등 다양한 서버를 사용하여 메일을 전송할수 있는데 이번 프로젝트에서는 Naver SMTP 서버를 이용하여 메일 인증을 진행하였다. 하지만 Google SMTP 서버도 설정하여 사용해보았다. 절차나 단계는 거의 유사하다고 볼수 있다.
또한 스프링에서 기본적으로 제공해주는 API를 사용하여 어렵지 않게 구현할수 있었다.
❗ 나중에 정리할것
1. SMTP 프로토콜에 대해서
2. JavaMailSander는 동기? 비동기? 처리
추후 Spring에서 해당 SMTP 서버를 사용하기 전에 해당 Naver SMTP 서버를 활성화 시켜준다. 네이버 메일서버를 외부에서 사용하기 위해서는 pop3/SMTP 설정을 필수로 활성화 시켜주어야된다.
아이디, 패스워드, SMTP 포트, SSL등은 yml파일 설정에서 사용할 예정이다.
//spring email
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '2.6.3'
# Naver smtp server 사용
spring:
mail:
host: smtp.naver.com #smtp 서버 주소
port: 465 # 메일 인증서버 포트
username: xxxx #네이버 아이디
password: xxxx #네이버 비밀번호
properties:
mail:
smtp:
starttls:
enable: true
# required: true
auth: true
# connectiontimeout: 5000
# timeout: 5000
# writetimeout: 5000
ssl:
#trust: smtp.naver.com
enable: true #반드시 필요 -> SSL 필요로 되어있으면
Naver SMTP 계정 설정에 있는 값들로 설정한다.
spring:
mail:
# Google smtp server 사용
host: smtp.gmail.com
port: 587
username: xxxx #앱 비밀번호 발급받은 google 계정
password: xxxx #발급받은 앱 비밀번호
properties:
mail:
smtp:
starttls:
enable: true
auth: true
MailService
안에는 총 3가지 기능의 메서드가 존재한다.
1. createCode
: 인증번호 8자리를 무작위로 생성하는 기능을 한다.
2. createEmailForm
: email 전송에 필요한 정보들을 설정하는 기능을 하게 된다. 여기서 전송하고자하는 message의 context에 전송하고자하는 html
파일을 타임리프
를 이용하여 html와 java 코드가 분리되도록 구성하였다.
3. sendEmail
: 실제 메일을 전송하는 기능
@Service
@RequiredArgsConstructor
public class EmailService {
//의존성 주입을 통해서 필요한 객체를 가져온다.
private final JavaMailSender emailSender;
// 타임리프를사용하기 위한 객체를 의존성 주입으로 가져온다
private final SpringTemplateEngine templateEngine;
private String authNum; //랜덤 인증 코드
//랜덤 인증 코드 생성
public void createCode() {
Random random = new Random();
StringBuffer key = new StringBuffer();
for(int i=0;i<8;i++) {
int index = random.nextInt(3);
switch (index) {
case 0 :
key.append((char) ((int)random.nextInt(26) + 97));
break;
case 1:
key.append((char) ((int)random.nextInt(26) + 65));
break;
case 2:
key.append(random.nextInt(9));
break;
}
}
authNum = key.toString();
}
//메일 양식 작성
public MimeMessage createEmailForm(String email) throws MessagingException, UnsupportedEncodingException {
createCode(); //인증 코드 생성
String setFrom = "rnqhstlr2297@naver.com"; //email-config에 설정한 자신의 이메일 주소(보내는 사람)
String toEmail = email; //받는 사람
String title = "CODEBOX 회원가입 인증 번호"; //제목
MimeMessage message = emailSender.createMimeMessage();
message.addRecipients(MimeMessage.RecipientType.TO, email); //보낼 이메일 설정
message.setSubject(title); //제목 설정
message.setFrom(setFrom); //보내는 이메일
message.setText(setContext(authNum), "utf-8", "html");
return message;
}
//실제 메일 전송
public String sendEmail(String toEmail) throws MessagingException, UnsupportedEncodingException {
//메일전송에 필요한 정보 설정
MimeMessage emailForm = createEmailForm(toEmail);
//실제 메일 전송
emailSender.send(emailForm);
return authNum; //인증 코드 반환
}
//타임리프를 이용한 context 설정
public String setContext(String code) {
Context context = new Context();
context.setVariable("code", code);
return templateEngine.process("mail", context); //mail.html
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div style="margin:100px;">
<h1> 안녕하세요.</h1>
<h1> 알고리즘 관리 서비스 CODEBOX 입니다.</h1>
<br>
<p> 아래 코드를 회원가입 창으로 돌아가 입력해주세요.</p>
<br>
<div align="center" style="border:1px solid black; font-family:verdana;">
<h3 style="color:blue"> 회원가입 인증 코드 입니다. </h3>
<div style="font-size:130%" th:text="${code}"> </div>
</div>
<br/>
</div>
</body>
</html>
@RestController
@RequiredArgsConstructor
public class EmailController {
private final EmailService emailService;
@PostMapping("login/mailConfirm")
public String mailConfirm(@RequestBody EmailAuthRequestDto emailDto) throws MessagingException, UnsupportedEncodingException {
String authCode = emailService.sendEmail(emailDto.getEmail());
return authCode;
}
}
@Data
public class EmailAuthRequestDto {
@NotEmpty(message = "이메일을 입력해주세요")
public String email;
}
- 이메일(Request) 요청 -> 응답으로 랜덤 인증코드 반환
- 이메일 확인
혹시 EmailService 클래스에서 import는 어떤 것을 해야하나요?
도움 요청 드립니다~^^