그러면 일단 이메일 인증 코드를 보내는 api 하나 만들어야 되고 유저가 인증 코드를 입력하면 인증 코드가 맞는지 확인하는 api 하나 만들어서 총 두개 만들어야겠다고 생각했다
구글 계정을 새로 파서 2단계 인증을 설정해 준다
그리고 2단계 인증 탭에 들어가서
맨 밑에 앱 비밀번호에서 앱 비밀번호를 설정해 준다 앱 비밀번호는 유출되지 않게 잘 기억해 둔다
// mail
implementation 'org.springframework.boot:spring-boot-starter-mail'
이메일에 관련된 의존성 build.gralde 추가해주고
mail:
host: smtp.gmail.com
port: 587
username: ${email.username}
password: ${email.password}
properties:
mail:
smtp:
auth: true
starttls:
enable: true
application.yml에 host 는 smtp.gmail.com 으로 넣어주고 포트는 587번으로 해준다
그리고 구글 계정의 이메일과 아까 발급받은 앱 비밀번호 넣어준다
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class EmailController {
private final EmailService emailService;
@Operation(summary = "이메일 인증코드 전송", description = "바디에 {email} json 형식으로 보내주시면 됩니다. ")
@PostMapping("/v1/email")
public ResponseEntity<Void> sendEmail(@Valid @RequestBody MailSendRequest request) throws MessagingException {
emailService.sendEmail(request.toService());
return ResponseEntity.ok().build();
}
@Operation(summary = "이메일 인증코드 검증", description = "")
@PostMapping("/v1/email/verify")
public ResponseEntity<ValidEmailResponse> validEmail(@Valid @RequestBody MailValidRequest request) {
boolean auth = emailService.validEmail(request.toService());
return ResponseEntity.ok(new ValidEmailResponse(auth));
}
@Operation(summary = "이메일 중복 검사", description = "")
@PostMapping("/v1/email/duplication")
public ResponseEntity<Void> validDuplication(@Valid @RequestBody MailValidDuplicationRequest request) {
emailService.validDuplication(request.toService());
return ResponseEntity.ok().build();
}
}
인증코드 전송의 요청 dto 에는 email이 들어있고
인증 코드 검증의 요청 dto 에는 email이랑 인증코드가 들어있다
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional
public class EmailService {
private final JavaMailSender emailSender;
private final SpringTemplateEngine templateEngine;
private final UserRepository userRepository;
private final EmailRepository emailRepository
@Value("${spring.mail.username}")
private String emailAddress;
//이메일 보낼 양식
public MimeMessage createEmailForm(String email) throws MessagingException {
String authCode = getAndStoreAuthCode(email);
String setFrom = emailAddress; //yml 에 설정한 자신의 이메일 주소(보내는 사람)
String toEmail = email; //받는 사람
String title = "스터디허브 이메일 인증 번호"; //제목
MimeMessage message = emailSender.createMimeMessage();
message.addRecipients(MimeMessage.RecipientType.TO, email); //보낼 이메일 설정
message.setSubject(title); //제목 설정
message.setFrom(setFrom); //보내는 이메일
message.setText(setContext(authCode), "utf-8", "html"); //본문 내용 설정
return message;
}
public void sendEmail(MailInfo info) throws MessagingException {
String email = info.getEmail();
MimeMessage emailForm = createEmailForm(email);
emailSender.send(emailForm);
}
public String setContext(String code) {
Context context = new Context();
context.setVariable("code", code);
return templateEngine.process("mail", context); //mail.html
}
public boolean validEmail(ValidMailInfo info) {
String storedAuthCode = emailRepository.findByEmail(info.getEmail());
return storedAuthCode != null && storedAuthCode.equals(info.getAuthCode());
}
public void validDuplication(ValidDuplicationInfo info) {
if (userRepository.existsByEmail(info.getEmail())) {
throw new AlreadyExistUserException();
}
}
public String getAndStoreAuthCode(String email) {
Random random = new Random();
StringBuilder key = new StringBuilder();
for(int i=0;i<8;i++) {
key.append(random.nextInt(10));
}
Email email = new Email(email, key.toString());
emailRepository.save(email);
return key.toString();
}
}
코드는 더럽지만 일단 구현을 위주로 해보았다
JavaMailSender를 이용해서 메일을 전송했다 메일 폼을 만들고 디비에 저장하고 거기에 랜덤으로 만든 값을 인증코드에 넣어서 폼에 넣어준다 나머지는 주석에 설명대로
html은 이렇게 만들어줬다
resources/template/mail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div style="margin:100px;">
<h1> 안녕하세요.</h1>
<h1> 스터디 매칭 어플 스터디허브 입니다.</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>
잘된다