triplus) NodeMailer 를 이용한 이메일인증

하쿄이_hakyoiii·2021년 12월 27일

프로젝트일지

목록 보기
3/12

이번에 우리가 구현하는 프로젝트에서 중요한게 바로 사용자 인증이다. 왜냐면 비대면으로 만나는 서비스를 제공하는데, 인증이 안된 사용자가 글을 올리면 문제가 발생할 수 있기 때문이다.

그래서 우리는 이메일을 통한 본인인증 절차를 넣어주기로 했다.

서버에서 메일전송기능을 구현할 때 쓰는 모듈이 바로 nodeMailer이다.

사용방법은 아래와 같다.

  1. nodemailer와 smtp서버를 위한 nodemailer-smtp-transport 모듈을 설치해준다.
npm install nodemailer
npm install nodemailer-smtp-transport

nodemailer에 따르면 공식적인 사용방법을 알 수 있다.

"use strict";
const nodemailer = require("nodemailer");

// async..await is not allowed in global scope, must use a wrapper
async function main() {
  // Generate test SMTP service account from ethereal.email
  // Only needed if you don't have a real mail account for testing
  let testAccount = await nodemailer.createTestAccount();

  // create reusable transporter object using the default SMTP transport
  let transporter = nodemailer.createTransport({
    host: "smtp.ethereal.email",
    port: 587,
    secure: false, // true for 465, false for other ports
    auth: {
      user: testAccount.user, // generated ethereal user
      pass: testAccount.pass, // generated ethereal password
    },
  });

  // send mail with defined transport object
  let info = await transporter.sendMail({
    from: '"Fred Foo 👻" <foo@example.com>', // sender address
    to: "bar@example.com, baz@example.com", // list of receivers
    subject: "Hello ✔", // Subject line
    text: "Hello world?", // plain text body
    html: "<b>Hello world?</b>", // html body
  });

  console.log("Message sent: %s", info.messageId);
  // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>

  // Preview only available when sending through an Ethereal account
  console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
  // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
}

main().catch(console.error);

이메일 인증을 완료하기까지 많은 방법이 있을 수 있겠지만, 더 나은 사용자 경험을 고려해 이메일에 포함된 링크를 클릭하면 인증이 완료되는 로직을 구현했다.

우선 네이버에서 SMTP메일을 보내기 위한 설정을 해주었다.

그 후의 로직은 아래와 같다.

  1. SMTP 전송에 사용될 나의 이메일 정보를 적어둔 객체를 만든다.
  2. 메일에 넣어줄 url에 넣을 key를 생성해준다.
  3. verify 여부와 key를 데이터베이스에 저장한다. (userId도 함께)
  4. 생성한 키를 url파라미터로 넣어서 보내준다.
  5. 사용자가 url을 클릭하면 데이터베이스에서 key값이 있는 지 찾고 key값이 일치하는지 여부를 검사한다.
  6. 일치한다면 verify를 0(false)에서 1(true)로 바꿔준다.
  7. 이후 로그인할 때 verify여부까지 검사해서 verify가 0이라면 이메일 인증이 필요하다는 메시지를 클라이언트에 보내준다.

로직을 구현할 때 마주친 에러

  1. key를 생성할 때, crypto를 사용하려고 했는데, radmomBytes가 생성이 안되는 에러가 있었다. 오타의 문제여서 오타를 수정해 주었다.
  2. 사용자가 url을 클릭했을 때, 연결이 제대로 안되는 것을 확인했다. url을 잘못 입력해주었기 때문이었다. 사용자가 url을 클릭하면 서버에 get /confirmEmail 요청을 하게 설정해두었는데, http로 통신할 것을 https로 잘못적어주어 생긴 문제였다.
  3. 마지막으로 vefiry여부를 검사할 때 조건문을 잘못 적어줘서
TypeError: Cannot read properties of null (reading 'dataValues')
  에러가나는 것을 확인했다.

조건문의 위치수정으로 해결해주었다.

profile
Hello I'm front-end engineer hakyoung song!

0개의 댓글