[NODE.JS] 이벤트 일정을 이메일로 보내보자(Nodemailer & ics & Gmail)
소 아
2022. 10. 9. 09:00
사이트를 이용하다보면 내가 예약한 일정 혹은 미팅 안내 등을 메일로 받아 캘린더에 저장한 적이 있을 것이다. 이 기능은 많이 사용되어 실무에서 요구하는 대표적인 기능 중 하나라고 한다. 그래서 이 기능을 Nodemailer와 ics를 사용해 내 Gmail로 일정 안내 메일을 보내고 받아 캘린더에 저장해보고자 한다.
사용할 모듈 : Nodemailer, ics
Nodemailer : 쉽게 이메일을 보낼 수 있도록 하는 Node.js 애플리케이션용 모듈. 유니코드 지원, 파일첨부 가능, SMTP 연결을 위한 프록시 사용 가능 등의 특징이 있다.
ics : 아이캘린더(iCalendar), 인터넷 사용자들이 다른 인터넷 사용자들에게 전자 메일을 이용하여 미팅 요청과 할 일을 보내거나 .ics 확장자로 파일들을 공유할 수 있게 해 주는 파일형식을 생성해주는 모듈. 예약 안내, 일정을 이벤트로 담아서 메일로 보낼 때 많이 사용한다.
Gmail을 이용한 메일 전송 방법
0. Gmail 2단계 인증 활성화 및 앱 비밀번호 발급받기
Nodemailer는 2단계 인증을 사용하는 Gmail계정을 등록해 메일을 발송할 수 있도록 지원해준다. 해서 Gmail계정에 접속해 2단계 인증을 사용 설정을 해야한다.
'2단계 인증' 클릭구글계정 비밀번호 입력 후 2단계 인증 기기 인증 화면이 나오는데 화면에 따라 절차를 밟으면 된다. 인증 완료 후 2단계 인증 페이지가 나오고계정 > 보안 페이지로 돌아왔을 때 2단계 인증이 아래와 같이 나왔다면 인증은 정상적으로 완료된 것이다.
'앱 비밀번호' 클릭
앱 선택 - 메일, 기기 선택 - 사용하는 기기 선택 : 나는 윈도우 컴퓨터에서 실행할거라 Windows 컴퓨터를 선택했다.
발급받은 앱 비밀번호 복사 : 가렸지만 노란부분에 비밀번호가 표시된다. 복사해서 사용하면 된다.
위 단계를 거치지 않으면 실행시 나중에 실행할 때 아래와 같은 오류가 발생한다.(해제한 걸 잊고서 테스트 하다 발생했다..ㅜㅠ)
Error: Invalid login: 535-5.7.8 Username and Password not accepted. Learn more at
535 5.7.8 https://support.google.com/mail/?p=BadCredentials b13-20020a1709027e0d00b00172973d3cd9sm3557970plm.55 - gsmtp
at SMTPConnection._formatError (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:790:19)
at SMTPConnection._actionAUTHComplete (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:1542:34)
at SMTPConnection.<anonymous> (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:546:26)
at SMTPConnection._processResponse (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:953:20)
at SMTPConnection._onData (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:755:14)
at TLSSocket.SMTPConnection._onSocketData (D:\github\resetStudy\nodeEx\node_modules\nodemailer\lib\smtp-connection\index.js:193:44)
at TLSSocket.emit (node:events:527:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at TLSSocket.Readable.push (node:internal/streams/readable:228:10) {
code: 'EAUTH',
response: '535-5.7.8 Username and Password not accepted. Learn more at\n' +
'535 5.7.8 https://support.google.com/mail/?p=BadCredentials b13-20020a1709027e0d00b00172973d3cd9sm3557970plm.55 - gsmtp',
responseCode: 535,
command: 'AUTH PLAIN'
}
1. 모듈 설치
프로젝트 터미널에서 Nodemailer, ics를 설치한다.
npm install nodemailer --save
npm install ics
2. mail.transport.js 생성, 이메일 서버 설정 및 발송을 위한 함수 작성
이메일 서버 설정 및 발송 준비를 위한 소스는 재사용하기 좋게 메일 발송 소스와 구분해 따로 만들었다.
const send = async (data) => {
// data : 통신으로 보낸사람, 받는사람, 참조, 제목, 내용, 첨부파일을 오브젝트 형태로 전달받으려고 함
// createTransport() : 2.에서 작성한 config의 정보를 가지고 기본 SMTP 전송을 사용하여 전송 개체 생성
const transporter = nodemailer.createTransport(config);
// 정의된 전송 개체로 메일 보내기
transporter.sendMail(data, (err, info) => {
if(err){
console.log(err);
}else{
return info.response;
}
});
};
.일정 이벤트를 추가한 ics파일 생성 및 ics파일과 전달받은 정보를 메일에 담기 위한 함수구현
const sendWithIcs = async (data, event) => {
ics.createEvent(event, async(err, value) => {// iCalendar 파일 생성
if(err){ // 오류 발생시 오류 내용 출력
console.log(err); return;
}
console.log(value);
// 생성된 ics파일과 함께 이메일에 담을 내용 정의
const message = {
...data, // 메일관련 전달받은 데이터를 data를 key:value로 순차적으로 받아줌
icalEvent: { // ics 이벤트 파일 정의
filename: "invitation.ics", // iCalendar 파일명
method: "REQUEST", // RESPONSE, REQUEST 중 하나
content: value,
},
}
// 3번의 transporter가 생성되어 있는 send 안에 message를 담아 전송
await send(message);
});
}
mail.transport.js 전체코드
// 1. Nodemailer, ics 모듈 가져오기
const nodemailer = require("nodemailer");
const ics = require("ics");
// 2. 메일 서버 기본정보 작성
const config = {
service: "gmail",
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: "2단계 인증 및 앱비밀번호를 발급한 Gmail",
pass: "발급받은 앱 비밀번호",
},
};
// 3. 이메일을 발송할 createTransport 생성
const send = async (data) => {
const transporter = nodemailer.createTransport(config);
// 정의된 전송 개체로 메일 보내기
transporter.sendMail(data, (err, info) => {
if(err){
console.log(err);
}else{
return info.response;
}
});
};
// 4. 일정 이벤트를 추가한 ics파일 생성 및 ics파일과 전달받은 정보를 메일에 담기 위한 함수구현
const sendWithIcs = async (data, event) => {
ics.createEvent(event, async(err, value) => {// iCalendar 파일 생성
if(err){ // 오류 발생시 오류 내용 출력
console.log(err); return;
}
console.log(value);
// 생성된 ics파일과 함께 이메일에 담을 내용 정의
const message = {
...data, // 메일관련 전달받은 데이터를 data를 key:value로 순차적으로 받아줌
icalEvent: { // ics 이벤트 파일 정의
filename: "invitation.ics", // iCalendar 파일명
method: "REQUEST", // RESPONSE, REQUEST 중 하나
content: value,
},
}
// 3번의 transporter가 생성되어 있는 send 안에 message를 담아 전송
await send(message);
});
}
3. users.route.js 생성, node서버 실행 및 메일 발송 함수 작성
앱 실행 및 이메일 전송을 위한 모듈 가져오기
const express = require("express");
const app = express();
// 메일 서버 설정을 위해 작성한 파일 mail.transport.js 불러오기, .js는 생략이 가능하다.
const nodemailer = require("./mail.transport");
앱 실행을 위한 함수구현
app.use(express.json({
limit: "50mb"
}))
app.listen(3000,() => {
console.log("서버가 포트 3000번으로 시작 되었습니다.");
});
메일에 받은 데이터와 함께 보낼 일정 이벤트 정보 추가 및 메일발송 함수구현 변수로 추가한 event는 미팅, 예약, 할일 등을 이벤트로 정의가 가능하다, iCalendar 이메일을 사용해 보낼 수 있는 형식, 안의 내용은 ics공식문서를 참고해 작성 가능하다.