iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
0
Modern Web

30 天打造 MERN Stack Boilerplate系列 第 20

Day 20 - Infrastructure - Mail Service

無論是驗證信箱、重設密碼、寄送電子報、更新服務條款、...,即使再小的 Real World App 都必須要考量到寄信服務。如果自己架 Mail Server 明顯過於克難,現在通常都是直接採用第三方服務,例如:Sendgrid,但是小弟沒有 $$ 玩不起這樣的服務,所以在 Boilerplate 中使用的是折衷作法,搭配 Nodemailer 這個 Library 利用 Gmail 來發信。

Nodemailer

Nodemailer 是一個 Plugin-Based 的發信 Library,目前總共支援 36 種服務,包括 Gmail、Sendgrid、Amazon 的 SES。

在 Boilerplate 中我們把 Nodemailer 的原生寫法包裝成 nodemailerAPI,保留日後擴充的彈性,目前只有 sendMail 這個 Method,使用方式如同我們呼叫 API 的一慣作法,回傳值是一個 Promise:

import Errors from '../../common/constants/Errors';
import nodemailerAPI from '../api/nodemailer';

export default {
  // ...
  sendResetPasswordLink(req, res) {
    let { user } = req;
    let token = user.toResetPasswordToken();

    nodemailerAPI()
      .sendMail({ /* nodemailer options */ })
      .catch((err) => {
        res.errors([Errors.SEND_EMAIL_FAIL]);
        throw err;
      })
      .then((info) => {
        res.json({
          email: info.envelope,
        });
      });
  },
};

完整程式碼:src/server/controllers/mail.js

Gmail & Application Password

基於成本考量,我們目前是使用免費的 Gmail 服務,讀者可以依照自己喜好修改 nodemailerAPI,套用自己熟悉的服務。

另外,使用 Gmail 要記得申請應用程式專用的密碼,否則當你的 App 丟到 Travis 跑測試,或是部署到 Heroku 正式上線時,很可能被 Google 誤判為有人從美國入侵你的帳號。應用程式密碼的申請需要先啟用兩階段驗證,接著才能申請,完整教學請看 Boilerplate 的 README#Gmail

使用 Component 當作 View Templates

Nodemailer 的 Options 可以傳入 Html 作為信件內容,但是我們依然是運行在 MVC 的架構下,所以其實可以將 Html Option 抽取成獨立的元件,再呼叫 React-Dom 的 renderToString 產生 Html 即可:

import React from 'react';
import { renderToString } from 'react-dom/server';
import ResetPasswordMail from '../components/ResetPasswordMail';

nodemailerAPI()
  .sendMail({
    to: user.email.value,
    subject: 'Reset Password Request',
    html: renderToString(
      <ResetPasswordMail
        requestedAt={new Date()}
        token={token}
      />
    ),
  })

完整程式碼:src/server/controllers/mail.js


上一篇
Day 19 - Infrastructure - Pagination
下一篇
Day 21 - Testing - Technique Stack
系列文
30 天打造 MERN Stack Boilerplate30

尚未有邦友留言

立即登入留言