프로그래밍/Node.js

[nodejs] 구글 2FA 인증을 통한 SMTP 메일 발송 오류 해결기

채윤아빠 2022. 10. 19. 07:32
728x90
반응형

문제점 및 증상

꽤 오래된 라즈베리파이를 이용하여 서비스에서 구글 메일 발송시 다음과 같은 오류가 발생하는 상황을 해결해 나간 과정을 정리해 둡니다.

transporter.sendMail: Error:  { Error: certificate is not yet valid
    at Error (native)
    at TLSSocket. (_tls_wrap.js:1092:38)
    at emitNone (events.js:86:13)
    at TLSSocket.emit (events.js:185:7)
    at TLSSocket._finishInit (_tls_wrap.js:609:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:439:38) code: 'ECONNECTION', command: 'CONN' }

해결 과정

구글이 아닌 다른 일반 SMTP에서는 정상적인 발송이 가능하였지만, 구글에서 권고하는 2FA(2 Factor authentication) 설정이 된 계정으로는 메일 발송이 실패하였습니다.

구글의 2FA 로그인 방법에 대해서 자세히 알아보니, 계정 소유자 본인이 로그인하는 것이 맞는지 이메일 등으로 한 번 더 확인하는 과정을 거치게 되어 있었습니다.

문제는 SMTP와 같은 메일 발송 상황에서 메일을 보낼 때마다 본인이 로그인하는 것이라고 추가적으로 일일이 확인할 수는 없으므로, 이를 우회할 수 있도록 "App Password"라는 것을 발급하고, 새로 발급받은 "App Password"를 이용하여 SMTP에서 추가적인 본인 확인없이 바로 메일을 보낼 수 있습니다. ("App Password"를 발급 받는 과정은 참고자료를 살펴보시면 됩니다.)

새로 발급받은 "App Password"를 이용하여 구글을 통하여 메일을 발송하려고 했으나, 이번에는 다음과 같은 오류가 발송이 실패하였습니다.

Failed with errors: {"code":"CERT_NOT_YET_VALID"}

"CERT_NOT_YET_VALID" 관련 오류를 제대로 찾을 수가 없어서 주요 패키지에 대한 버전을 확인해 보았습니다.

라즈베리파이 내에 서비스가 이용하는 "nodemailer" 버전을 확인해 봤더니, 다음과 같이 정말 아주 예전 버전을 이용하고 있었습니다.

nodemailer ## 2.7.0 2016-12-08

npm 버전은 다음과 같았습니다.

pi@raspberrypi:~ $ npm -v
3.10.10

nodejs 버전 (6.x) 및 패키지들을 확인해 보니, 2017년 이전 버전들이었습니다. 너무 오래전 버전이라서 문제가 발생하는가 싶어서 백업 후, 여러 패키지들을 최신 버전으로 업그레이드를 진행하려고 하였으나, apt, pip 모두 지원이 불가능하였습니다.

라즈베리파이의 OS는 4.9.x 대로 "Jessi"였습니다. apt를 통한 패키지 관리 자체가 안되었습니다.

혹시나 싶어 TLS 암호화를 지원하는 "openssl" 버전을 확인해 보니 다음과 같았습니다.

pi@raspberrypi:~ $ dpkg -lgrep openssl
ii  libgnutls-openssl27:armhf             3.3.30-0+deb8u1                           armhf        GNU TLS library - OpenSSL wrapper
ii  openssl                               1.0.1t-1+deb8u12                          armhf        Secure Sockets Layer toolkit - cryptographic utility
ii  python-openssl                        0.14-1                                    all          Python 2 wrapper around the OpenSSL library

세상에... "1.0.1t"라니... 당연히 TLS v1.3 등이 지원되지 않는 라이브러리였습니다.

결론적으로 "openssl"을 비롯하여 관련 패키지의 업그레이드가 필요한 것이었는데, OS가 너무 예전 버전이라 "apt"를 통한 업그레이드가 불가능하였습니다.


OS 최신화 작업

기존 서비스 프로그램과 호환성을 확보하면서 OS 및 관련 패키지를 최신화를 해야만 했습니다.

여기서도 우여곡절이 많았습니다. nodejs를 상위 버전으로 업그레이드를 하면 소스 호환성을 보장받지 못하여 기존 서비스 프로그램이 정상적으로 구동되지 않았습니다.
또한 사용하는 nodejs 모듈도 최신화를 했을 경우, 소스 화환성을 보장하지 않는 경우가 많았습니다.

그래서 nodejs는 6.x 대의 가장 최신 버전을 받아 수동으로 설치하였고, nodejs 모듈은 기존에 "node_modules" 폴더에 있던 것들을 그대로 복사하여 이용하였습니다.

OS를 최신화하여 적용된 USB Memory의 openssl 버전을 확인해 보니 다음과 같았습니다.

pi@raspberrypi:~ $ dpkg -lgrep openssl
ii  openssl                              1.1.1n-0+deb10u3                        armhf        Secure Sockets Layer toolkit - cryptographic utility
ii  python-openssl                       19.0.0-1                                all          Python 2 wrapper around the OpenSSL library
ii  python3-openssl                      19.0.0-1                                all          Python 3 wrapper around the OpenSSL library

OS 및 관련 패키지를 최신화 이후 기존 서비스 프로그램에서 구글 SMTP로 메일 발송이 정상적으로 수행되었습니다.


참고자료

https://support.google.com/accounts/answer/185833?hl=en#
https://ahmadawais.com/generate-gmail-app-password-to-send-emails-with-2fa-two-factor-authenticated-accounts/