NodeJS: Xây dựng API gửi mail với Nodemailer và OAuth2


1061

Lời giới thiệu

Không phải tất cả các hướng dẫn trực tuyến đều chỉ cho bạn một cấu trúc tốt để thiết lập hoặc xử lý NodeJS API gửi thư cho các trường hợp khác nhau như đăng ký, quên mật khẩu, xác minh email hoặc để thay đổi mẫu email. Tôi sẽ cố gắng hết sức để giúp bạn với hướng dẫn từng bước về cách thiết lập API gửi thư trong NodeJ với Nodemailer, Gmail, OAuth Client cho nhiều mục đích.

Yêu cầu

Kết quả mong đợi

Image for post

Setup Google Cloud Platform

Đầu tiên, hãy thiết lập ID Client OAuth cho ứng dụng NodeJS của bạn

  1. Truy cập Google Cloud và tạo một dự án mới.
  2. Tìm “APIs & Services”
  3. Click vào “Credentials” > Click “+ Create credentials” > “OAuth client ID”

4. Copy Client ID và Client Secret vào note.

Google OAuth Playground

  1. Đi tới Oauth Playground > Click vào Setting icon bên phải >Enable Use your own Oauth credentials > Enter Oauth Client ID & Oatuh Client Secret vào form bên trên > Close
  2. Trong Select & Authorize APIs, gõ https://mail.google.com > Authorize APIs > Login với account bạn muốn gửi từ.
  3. Click Exchange authorization code cho tokens > Copy Refresh Token

Bây giờ, bạn nên có 3 điều trong note của mình:

  1. Client ID
  2. Client Secret
  3. Oauth2 Refresh Token

Quan trọng: Không cần định cấu hình tài khoản Gmail

Trong khi nhiều hướng dẫn yêu cầu bạn BẬT “Quyền truy cập ứng dụng kém an toàn hơn” để cho phép Nodemailer có quyền truy cập để gửi email từ tài khoản của bạn.

  • Tôi KHÔNG thích vì chúng ta sử dụng Nodemailer mà không làm giảm bảo mật Gmail của bạn
  • Cách kiểm tra: Khởi chạy Gmail, sau đó nhấp vào hồ sơ của bạn ở góc trên cùng bên phải -> Quản lý tài khoản Google của bạn -> Bảo mật. Bạn sẽ thấy cài đặt sau:
nodejs

Vì vậy, có, hãy Tắt nó đi, nó an toàn hơn!

Setup Structure NodeJS

  1. Fork dự án này làm template để bắt đầu hoặc bạn có thể sử dụng dự án NodeJS phụ trợ của riêng mình.
  2. Tạo tệp .env.sh trong thư mục gốc để lưu trữ môi trường bí mật của bạn> thay thế các mục đánh dấu bằng những gì bạn có ở bước trước> chạy
 source .env.sh> Thêm tệp này vào .gitignore
# Mailing Serivce
export PROJECT_ID="<Your Project ID>"
export SENDER_EMAIL_ADDRESS="calvin.nvqc@gmail.com"
export MAILING_SERVICE_CLIENT_ID="<Enter your Client ID>"
export MAILING_SERVICE_CLIENT_SECRET="<Enter your Client Secret>"
export MAILING_SERVICE_REFRESH_TOKEN="<Refresh Token>"

3. Mở project và Tạo thư mục Mailing/ và các tệp liên quan:

mkdir store/Mailing store/Mailing/template
touch store/Mailing/index.js store/Mailing/template/subscribe.ejs 

4. Cài đặt nodemailer, googleapis, ejs: 

npm i nodemailer googleapis ejs

Setup Nodemailer

  1. Thêm code này vào index.js. Code này sẽ khởi tạo nodemailer với Google Oauth2.
import nodemailer from 'nodemailer';
import ejs from 'ejs';const { google } = require('googleapis');const { OAuth2 } = google.auth;const OAUTH_PLAYGROUND = 'https://developers.google.com/oauthplayground';const {
  MAILING_SERVICE_CLIENT_ID,
  MAILING_SERVICE_CLIENT_SECRET,
  MAILING_SERVICE_REFRESH_TOKEN,
  SENDER_EMAIL_ADDRESS,
} = process.env;const Mailing = {};const oauth2Client = new OAuth2(
  MAILING_SERVICE_CLIENT_ID,
  MAILING_SERVICE_CLIENT_SECRET,
  OAUTH_PLAYGROUND
);const TEMPLATES = {
  subscribe: {
    fileName: 'subscribe.ejs',
    subject: '[ABC Inc.] Welcome to ABC Inc.',
  },
};/**
 * Send Email
 */
Mailing.sendEmail = data => {
  oauth2Client.setCredentials({
    refresh_token: MAILING_SERVICE_REFRESH_TOKEN,
  });  const accessToken = oauth2Client.getAccessToken();const smtpTransport = nodemailer.createTransport({
    service: 'gmail',
    auth: {
      type: 'OAuth2',
      user: SENDER_EMAIL_ADDRESS,
      clientId: MAILING_SERVICE_CLIENT_ID,
      clientSecret: MAILING_SERVICE_CLIENT_SECRET,
      refreshToken: MAILING_SERVICE_REFRESH_TOKEN,
      accessToken,
    },
  });
  const filePath = `${__dirname}/templates/${TEMPLATES[data.template].fileName}`;  ejs.renderFile(filePath, data, {}, (e, content) => {
    if (e) return e;
    const mailOptions = {
      from: SENDER_EMAIL_ADDRESS,
      to: data.email,
      subject: TEMPLATES[data.template].subject,
      html: content,
    };  smtpTransport.sendMail(mailOptions, (err, info) => {
      if (err) return err;
      return info;
    });
  });
};export default Mailing;

2. Thêm template subsribe.ejs này

<p>Welcome <%= email %></p><p>
  Thank you for subscribing to ABC Inc. Stay tune for more updates from us!
  <br />
</p>

Tạo API mailing

  • Tạo Mailing POST/ API cho app NodeJS : 
touch controller/mailing.controller.js
import express from 'express';
import Mailing from '../store/Mailing';
import { SOME_THING_WENT_WRONG } from '../store/constant';
import { generateServerErrorCode } from '../store/utils';const mailingController = express.Router();/**
 * POST/ User subscribe to App
 */
mailingController.post('/', (req, res) => {
  try {
    Mailing.sendEmail(req.query);
    res.status(200).json({ message: 'email sent successfully' });
  } catch (e) {
    generateServerErrorCode(res, 500, e, SOME_THING_WENT_WRONG);
  }
});export default mailingController;

2. Sửa đổi controller / index.js:

import userController from './user.controller';
import mailingController from './mailing.controller';export { userController, mailingController };

3. Thêm Mailing Controller vào file app.js:

import express from 'express';
import logger from 'winston';
import bodyParser from 'body-parser';
import cors from 'cors';
import passport from 'passport';
import mongoose from 'mongoose';import { config } from './store/config';
import { applyPassportStrategy } from './store/passport';
import { userController, mailingController } from './controller';const app = express();// Apply strategy to passport
applyPassportStrategy(passport);app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());// API
app.use('/', userController);
app.use('/mailing', mailingController);/**
 * Get port from environment and store in Express.
 */
const { port, mongoDBUri, mongoHostName } = config.env;
app.listen(port, () => {
  logger.info(`Started successfully server at port ${port}`);
  mongoose
    .connect(mongoDBUri, { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => {
      logger.info(`Conneted to mongoDB at ${mongoHostName}`);
    });
});

Testing app với Postman NodeJS

Sử dụng phương thức POST / và nhập URL này > click Send

localhost:8080/mailing?email=calvin.nvqc@gmail.com&template=subscribe

Sau khi request thành công, bạn sẽ nhận được thông báo này.

nodejs

Bây giờ, hãy kiểm tra email của bạn và xin chúc mừng!

Image for post

Kết luận

Với bài viết này, bạn có thể dễ dàng thay đổi nội dung cho email của mình và bạn có thể gửi không chỉ email đăng ký mà còn đăng ký xác minh, quên mật khẩu, v.v..

Tham khảo thêm về NodeJS tại đây: Log NodeJS là gì ? Và tại sao nên dùng

Tham khảo thêm về React tại đây: Build app chat real tiem với React


Like it? Share with your friends!

1061