이메일로 회원가입하는 경우 해당 이메일에 인증번호를 보내 본인의 이메일이 맞는지 확인하는 과정을 거치게 된다. 프로젝트를 진행하며, 이메일 인증 구현한 내용을 정리해보았다.

나는 프로젝트 용으로 새 구글 계정을 하나 만들었다.
구글 계정에서 2단계 보안 설정을 한 후, 앱 비밀번호를 발급받는다.

앱 비밀번호를 사용하면 최신 보안 표준을 지원하지 않는 오래된 앱 및 서비스에서 Google 계정에 로그인할 수 있습니다.
-> 스프링에서 해당 이메일에 접근하여 인증코드를 보내야하기 때문에! 꼭 필요하다
저 화면에서 만들기를 누르면 팝업창에 16자리의 앱 비밀번호가 나오는데, 이걸 따로 복사해둔 후 사용한다.

POP, IMAP 사용을 하도록 다음과 같이 설정한다.
(다른 블로그는 <IMAP 사용하기> 항목도 선택해야하던데 나는 뜨지 않았다.
하지만 IMAP 액세스를 설정하는 것 자체가 IMAP를 사용가능한거 같다.)
implementation 'org.springframework.boot:spring-boot-starter-mail'
spring:
mail:
host: smtp.gmail.com
port: 587
username: ${mail.username}
password: ${mail.password}
properties:
mail:
smtp:
auth: true
timeout: 5000
starttls:
enable: true
import com.example.todayserver.domain.member.excpetion.AuthException;
import com.example.todayserver.domain.member.excpetion.code.AuthErrorCode;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring6.SpringTemplateEngine;
import java.util.Random;
@Service
@RequiredArgsConstructor
public class EmailService {
private final JavaMailSender javaMailSender;
private final SpringTemplateEngine templateEngine;
@Value("${spring.mail.username}")
private String fromEmail;
public String sendVerificationEmail(String emailTo) {
String code = generateVerificationCode();
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false, "UTF-8");
mimeMessageHelper.setTo(emailTo);
mimeMessageHelper.setSubject("[TO:DAY] 이메일 인증 코드 발송");
mimeMessageHelper.setText(createHtmlEmailBody(code),true);
mimeMessageHelper.setFrom(fromEmail);
javaMailSender.send(mimeMessage);
return code;
} catch (MessagingException e) {
throw new AuthException(AuthErrorCode.CODE_ERROR);
}
}
// 인증번호 생성
private String generateVerificationCode() {
return String.valueOf(100000 + new Random().nextInt(900000));
}
// 인증 이메일 뷰 생성
private String createHtmlEmailBody(String code) {
Context context = new Context();
context.setVariable("code", code);
return templateEngine.process("email_code", context);
}
}
setTO: 수신자 이메일 설정
setSubject: 메일 제목
setText: 메일 본문 (2번째 파라미터는 html로 보낼건지 여부 -> true로 표시)
setFrom: 발신자 이메일 설정 (앞서 환경변수 선언해둔 값을 사용)
Context: 뷰에 전달할 데이터 담음 (인증코드 주입)
return templateEngine.process("email_code", context); : 여기서 "email_code" = html 파일 이름이다.
build.gradle 의존성 추가
//thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
https://jsfiddle.net/
해당 사이트에 가면 HTML 코드의 실행화면을 보여줘서 수정하기 좋다.

html 코드는 resource/templates 하위에 생성했다.
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0"
style="background-color:#ffffff; margin:40px 0; padding:40px;
border-radius:8px; font-family:Arial, sans-serif;
box-shadow:0 4px 10px rgba(0,0,0,0.08);">
<tr>
<td align="center">
<h1 style="margin:0; color:#333;">안녕하세요 👋</h1>
<p style="margin-top:10px; font-size:16px; color:#555;">
올인원 할일 관리 서비스 <strong>TO:DAY</strong>입니다.
</p>
</td>
</tr>
<tr>
<td style="padding:30px 0; text-align:center;">
<p style="font-size:15px; color:#666;">
서비스로 돌아가 아래 <strong>인증 코드</strong>를 입력해주세요.
</p>
</td>
</tr>
<tr>
<td align="center">
<div style="border:1px solid #e0e0e0;
border-radius:6px;
padding:25px;
width:100%;
box-sizing:border-box;">
<p style="margin:0; font-size:14px; color:#888;">
회원가입 인증 코드
</p>
<p style="margin-top:15px;
font-size:28px;
letter-spacing:6px;
font-weight:bold;
color:#2f80ed;"
th:text="${code}">
123456
</p>
</div>
</td>
</tr>
<tr>
<td style="padding-top:30px; text-align:center;">
<p style="font-size:13px; color:#999;">
본 메일은 인증 요청에 의해 자동 발송되었습니다.<br>
인증을 요청하지 않으셨다면 이 메일을 무시해주세요.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
