spring 으로 메일 인증 구현

wellbeing-dough·2023년 12월 6일
1

1. todo list

  • 회원은 자신의 이메일을 입력해서 해당 이메일로 인증 코드를 받는다
  • 인증 코드를 입력해서 인증코드가 맞으면 회원가입을 진행할 수 있게 한다

그러면 일단 이메일 인증 코드를 보내는 api 하나 만들어야 되고 유저가 인증 코드를 입력하면 인증 코드가 맞는지 확인하는 api 하나 만들어서 총 두개 만들어야겠다고 생각했다

2. 구글 계정

구글 계정을 새로 파서 2단계 인증을 설정해 준다

그리고 2단계 인증 탭에 들어가서

맨 밑에 앱 비밀번호에서 앱 비밀번호를 설정해 준다 앱 비밀번호는 유출되지 않게 잘 기억해 둔다

3. 스프링 부트

    // 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>

업로드중..

잘된다

0개의 댓글

관련 채용 정보