ㅇㅅㅇ

[NODE.JS] 이벤트 일정을 이메일로 보내보자(Nodemailer & ics & Gmail) 본문

프로그래밍/NODE.JS

[NODE.JS] 이벤트 일정을 이메일로 보내보자(Nodemailer & ics & Gmail)

소 아 2022. 10. 9. 09:00

사이트를 이용하다보면 내가 예약한 일정 혹은 미팅 안내 등을 메일로 받아 캘린더에 저장한 적이 있을 것이다. 이 기능은 많이 사용되어 실무에서 요구하는 대표적인 기능 중 하나라고 한다. 그래서 이 기능을  Nodemailerics를 사용해 내 Gmail로 일정 안내 메일을 보내고 받아 캘린더에 저장해보고자 한다.

사용할 모듈 : Nodemailer, ics

  • Nodemailer : 쉽게 이메일을 보낼 수 있도록 하는 Node.js 애플리케이션용 모듈. 유니코드 지원, 파일첨부 가능, SMTP 연결을 위한 프록시 사용 가능 등의 특징이 있다.
  • ics : 아이캘린더(iCalendar), 인터넷 사용자들이 다른 인터넷 사용자들에게 전자 메일을 이용하여 미팅 요청과 할 일을 보내거나 .ics 확장자로 파일들을 공유할 수 있게 해 주는 파일형식을 생성해주는 모듈. 예약 안내, 일정을 이벤트로 담아서 메일로 보낼 때 많이 사용한다.

Gmail을 이용한 메일 전송 방법

0. Gmail 2단계 인증 활성화 및 앱 비밀번호 발급받기

Nodemailer는 2단계 인증을 사용하는 Gmail계정을 등록해 메일을 발송할 수 있도록 지원해준다. 해서 Gmail계정에 접속해 2단계 인증을 사용 설정을 해야한다.

  1. google 계정 접속(로그인 후 접속)
     

    Google 계정

    Google은 사용자마다 원하는 개인정보 보호 설정이 다르다는 사실을 인지하고 있습니다. 그래서 Google 계정에서는 사용이 간편한 컨트롤과 개인정보 보호 진단 같은 도구를 제공합니다. 이런 도구

    www.google.com

  2. 좌측 탭에서 '보안'메뉴 클릭
  3. '2단계 인증' 클릭
    구글계정 비밀번호 입력 후 2단계 인증 기기 인증 화면이 나오는데 화면에 따라 절차를 밟으면 된다. 인증 완료 후 2단계 인증 페이지가 나오고
    계정 > 보안 페이지로 돌아왔을 때 2단계 인증이 아래와 같이 나왔다면 인증은 정상적으로 완료된 것이다.
  4. '앱 비밀번호' 클릭
  5. 앱 선택 - 메일, 기기 선택 - 사용하는 기기 선택 : 나는 윈도우 컴퓨터에서 실행할거라 Windows 컴퓨터를 선택했다.
  6. 발급받은 앱 비밀번호 복사 : 가렸지만 노란부분에 비밀번호가 표시된다. 복사해서 사용하면 된다.

위 단계를 거치지 않으면 실행시 나중에 실행할 때 아래와 같은 오류가 발생한다.(해제한 걸 잊고서 테스트 하다 발생했다..ㅜㅠ)

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 생성,  이메일 서버 설정 및 발송을 위한 함수 작성

이메일 서버 설정 및 발송 준비를 위한 소스는 재사용하기 좋게 메일 발송 소스와 구분해 따로 만들었다.

  1. Nodemailer, ics 모듈 가져오기
    const nodemailer = require("nodemailer");
    const ics = require("ics");
  2. 메일 서버 기본정보 작성: Nodemailer공식문서에서 자세한정보를 확인할 수 있다.
    const config = {
        service: "gmail",
        host: "smtp.gmail.com",
        port: 587,
        secure: false,
        auth: {
          user: "2단계 인증 및 앱비밀번호를 발급한 Gmail",
          pass: "발급받은 앱 비밀번호",
        },
    };
  3. 이메일을 발송할 함수구현 생성
    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;
            }
        });
    };
  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); 
        }); 
    }

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서버 실행 및 메일 발송 함수 작성

  1. 앱 실행 및 이메일 전송을 위한 모듈 가져오기
    const express = require("express");
    const app = express();
    // 메일 서버 설정을 위해 작성한 파일 mail.transport.js 불러오기, .js는 생략이 가능하다.
    const nodemailer = require("./mail.transport");
  2. 앱 실행을 위한 함수구현
    app.use(express.json({
        limit: "50mb"
    }))
    
    app.listen(3000,() => {
        console.log("서버가 포트 3000번으로 시작 되었습니다.");
    });
  3. 메일에 받은 데이터와 함께 보낼 일정 이벤트 정보 추가 및 메일발송 함수구현
    변수로 추가한 event는 미팅, 예약, 할일 등을 이벤트로 정의가 가능하다, iCalendar 이메일을 사용해 보낼 수 있는 형식, 안의 내용은 ics공식문서를 참고해 작성 가능하다.
    app.post("/api/ics", async (req,res) => {
        const event = {
            start: [2022, 11, 11, 9, 30], // 시작지점 년, 월, 일, 시간, 분
            duration: { hours: 1, minutes: 30 },// 이벤트 소요시간
            title: "Node.js 프로젝트 미팅", // 제목
            description: "Node.js 프로젝트 10월 정기 미팅", // 설명
            location: "서울특별시 강남구 학동로", // 장소
            geo: { lat: 30.12, lon: 50.45 }, // lat: 위도, lon: 경도
            url: "https://adds9810.github.io",
            organizer: { name: "Soa", email: "ria9810@gmail.com" }, // 주최자
            attendees: [ // 참여자, 참여자들에게는 아래의 정보가 전달되지 않음
              {
                name: "눈누",
                email: "nun@gmail.com",
                rsvp: true, // 회신 여부
                role: "REQ-PARTICIPANT", // 필수 참석자
              },
              {
                name: "난나",
                email: "nan@gamil.com",
                role: "OPT-PARTICIPANT", // 선택 참석자
              },
            ],
        };
    
        const r = await nodemailer.sendWithIcs(req.body.param, event);
        res.send(r);
    });

users.route.js 전체코드

// 1. 앱 실행 및 이메일 전송을 위한 모듈 가져오기
const express = require("express");
const app = express();
// 메일 서버 설정을 위해 작성한 파일 불러오기, .js는 생략이 가능하다.
const nodemailer = require("./mail.transport");

// 2. 앱 실행을 위한 함수구현
app.use(express.json({
    limit: "50mb"
}))

app.listen(3000,() => {
    console.log("서버가 포트 3000번으로 시작 되었습니다.");
});

// 3. 메일에 받은 데이터와 함께 보낼 일정 이벤트 정보 추가 및 메일발송 함수구현
app.post("/api/ics", async (req,res) => {
    const event = {
        start: [2022, 11, 11, 9, 30], // 시작지점 년, 월, 일, 시간, 분
        duration: { hours: 1, minutes: 30 },// 이벤트 소요시간
        title: "Node.js 프로젝트 미팅", // 제목
        description: "Node.js 프로젝트 10월 정기 미팅", // 설명
        location: "서울특별시 강남구 학동로", // 장소
        geo: { lat: 30.12, lon: 50.45 }, // lat: 위도, lon: 경도
        url: "https://adds9810.github.io",
        organizer: { name: "Soa", email: "ria9810@gmail.com" }, // 주최자
        attendees: [ // 참여자, 참여자들에게는 아래의 정보가 전달되지 않음
          {
            name: "눈누",
            email: "nun@gmail.com",
            rsvp: true, // 회신 여부
            role: "REQ-PARTICIPANT", // 필수 참석자
          },
          {
            name: "난나",
            email: "nan@gamil.com",
            role: "OPT-PARTICIPANT", // 선택 참석자
          },
        ],
    };

    const r = await nodemailer.sendWithIcs(req.body.param, event);
    res.send(r);
});

4. 서버실행

5. 테스트를 위한 postman 세팅

실행한 서버에 받는사람, 보내는사람, 제목, 내용을 보내고 일정을 메일로 받아보려고 한다.

postman은 설치는 다루지 않는다. 혹 필요한 사람이 있을까, 링크를 걸어둔다.

 

Postman API Platform | Sign Up for Free

Postman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster.

www.postman.com

  1. workspace > collections에서 생성한 collection 위쪽의 더보기 버튼 클릭 시 나오는 항 목 중 'Add Request' 클릭
  2. 'method' - post 선택, 'Enter request URL' - http://localhost:3000/설정한 url 추가
  3. 'body', 'raw', 'json' 선택 및 받는사람, 보내는사람, 제목, 내용 추가
  4. 'Send' 클릭

결과

크롬 브라우저에서 Gmail로 접속하면 다운로드할 수 있는 파일이 나와 클릭했더니

아웃룻으로 연결되길래 계정을 연결해서 확인해 봤다.

아웃룩에서는 첨부파일을 열고, "내 일정에 복사"를 클릭하면 일정에 저장되는 것을 확인할 수 있다.

 

잘 정리해 두었다가 유용하게 활용하자!

블로그에 게시된 글 외에서 실무에서 사용하는 여러가지 모듈 설치 및 활용법을 배우는 중인데 안정적이고 쉽게 유용한 기능들을 만들 수 있구나 생각이 든다.

출처

개발자의 품격 강의자료

 

Nodemailer :: Nodemailer

Nodemailer Nodemailer is a module for Node.js applications to allow easy as cake email sending. The project got started back in 2010 when there was no sane option to send email messages, today it is the solution most Node.js users turn to by default. npm i

nodemailer.com

 

'프로그래밍 > NODE.JS' 카테고리의 다른 글

[NODE.JS] winston 사용하여 로그를 기록해보기  (0) 2022.10.02
Comments