본문 바로가기
Error 정리

Node.js + TypeScript + nodemailer + naver 메일 인증 발송 에러 정리

by 집돌이디벨로퍼 2025. 9. 24.

네이버 메일을 사용한 메일 인증 기능을 만들면서 일어난 에러들을 정리하기위한 게시물

 

TypeError: Cannot destructure property 'email' of 'req.body' as it is undefined.

 

1. 본인이 Thunder client 초심자이기 때문에 일어난 에러

 

 



이렇게 Header 부분에는 형식 Content-Type : application/json 이 들어가야하고 

Body 부분에는 이렇게 넣어줬어야 했는데 멍청하게 Query 부분에 저 위에 코드 둘다 몰아서 적어준것.. 배워야할게 참 많다

 


 

[Error: BC390000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:openssl\ssl\record\ssl3_record.c:355:
] {
  library: 'SSL routines',
  reason: 'wrong version number',
  code: 'ESOCKET',
  command: 'CONN'
}

+

[Error: 48600000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:openssl\ssl\record\ssl3_record.c:355:
] {
  library: 'SSL routines',
  reason: 'wrong version number',
  code: 'ESOCKET',
  command: 'CONN'
}

==> 이건 비슷하긴한데 왜 에러코드가 바뀌었던건지 모르겠음..

 

2. nodemailer의 transporter 부분에서 service 와 host 를 동시에 지정해줘서 나는 에러

 

nodemailer에서 service: "naver"를 쓰면 내부적으로 host/port/secure 값을 자동으로 셋업한다.
근데 지금은 service 와 host/port/secure 를 동시에 지정했기 때문에 충돌이 난것

import { Transporter } from "nodemailer";
import nodemailer from "nodemailer";
import dotenv from "dotenv";
import path from "path";
// 환경변수 절대경로
dotenv.config({ path: path.resolve(__dirname, "../../../.env") });


console.log("NAVER_USER:", process.env.NAVER_USER);
console.log("NAVER_PASS:", process.env.NAVER_PASS ? "******" : "NOT FOUND");

export const transporter: Transporter = nodemailer.createTransport({
  service: "naver",
  host: "smtp.naver.com", // SMTP 서버명
  port: 465,              // SMTP 포트
  secure: true,           // TLS 보안 연결 (465 포트에서는 true)
  auth: {
    user: process.env.NAVER_USER as string,  // 네이버 아이디
    pass: process.env.NAVER_PASS as string,  // 네이버 비밀번호/앱 비밀번호
  },
});


여기에서 service : "naver " 이부분을 삭제하니 해결됨

 


 

 Error: Mail command failed: 554 5.7.1 The sender address is unauthorized NKvxy7vhTQuZRQBRcJF+2A - nsmtp
    at SMTPConnection._formatError (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:809:19)
    at SMTPConnection._actionMAIL (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:1618:34)
    at SMTPConnection.<anonymous> (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:1087:18)
    at SMTPConnection._processResponse (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:993:20)
    at SMTPConnection._onData (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:774:14)
    at TLSSocket.SMTPConnection._onSocketData (C:\Users\mn846\OneDrive\Desktop\FishApp\server\node_modules\nodemailer\lib\smtp-connection\index.js:195:44)
    at TLSSocket.emit (node:events:507:28)
    at TLSSocket.emit (node:domain:489:12)
    at addChunk (node:internal/streams/readable:559:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:510:3) {
  code: 'EENVELOPE',
  response: '554 5.7.1 The sender address is unauthorized NKvxy7vhTQuZRQBRcJF+2A - nsmtp',
  responseCode: 554,
  command: 'MAIL FROM'

3. 네이버 메일 => 환경설정 => POP3/SMTP 설정과 IMAP/SMTP 설정이 "사용 안 함" 으로 세팅되어있어서 생긴 에러

(분명 어제 켜놨는데.. 아 아마 저장을 안누른듯하다)

 

 

두개 설정 이부분 세팅해주면 끝남


메일 설정 끝.. 이번 기능을 만들면서 중요하게 생각했던 것은 결합도가 낮은 깨끗한 코드가 목표였다 그래서 service 부분에 모든 로직을 짜려고 생각을 많이 했고 controller 부분은 service 에서 짜진 함수들을 가져다쓰는 방식으로 최대한 만들었다 그리고 문법교정 부분은 chatgpt 에게 도움을 많이 받았지만 코드들은 여러 블로그에 걸려있는 코드들로 '여기에 이게 필요하고 저기엔 저게 필요하겠다' 라는 생각을 하면서 만들었다. 만들면 만들수록 생각을 더 하게 되는 것 같다.. 이렇게 하면 실력이 늘지 않을까..? 늘었으면 좋겠다..ㅋㅋ  

에러글인데 그냥 컨트롤러만 추가..

// 메일 인증
export const mailAuth = async (req: Request, res: Response) => {
 const { email } = req.body;

 console.log('받은 이메일 :',email)

  // 1) 입력 검증
  if (!email || !/^\S+@\S+\.\S+$/.test(email)) {
    return res.status(400).json({
      success: false,
      code: "INVALID_EMAIL",
      message: "유효한 이메일을 입력하세요.",
    });
  }

  // 2) 레이트 리미트 (60초 동안 동일 이메일 재요청 불가)
  const allowed = await checkThrottle(email);
  if (!allowed) {
    return res.status(429).json({
      success: false,
      code: "RATE_LIMIT",
      message: "잠시 후 다시 시도하세요.",
    });
  }

  try {
    // 3) 메일 발송 (실패 시 throw 발생)
    await sendAuthNumber(email);

    return res.status(200).json({
      success: true,
      message: "인증 메일을 발송했습니다.",
    });
  } catch (err) {
    console.error("메일 발송 실패:", err);

    // SMTP/외부 메일 서버 문제 → 502
    return res.status(502).json({
      success: false,
      code: "SMTP_ERROR",
      message: "메일 서버 오류로 발송에 실패했습니다.",
    });
  }
};