\n ),\n })\n```\n\n> 完整程式碼:[src/server/controllers/mail.js](https://github.com/gocreating/express-react-hmr-boilerplate/blob/dev/src/server/controllers/mail.js)\n","publisher":{"@type":"Organization","name":"BetterLog","url":"https://gocreating.lation.app","logo":{"@type":"ImageObject","url":"https://gocreating.lation.app/site/favicon.svg"}},"author":{"@type":"Person","name":"gocreating","url":"https://gocreating.lation.app"},"creator":{"@type":"Person","name":"gocreating"},"mainEntityOfPage":{"@type":"WebPage","@id":"https://gocreating.lation.app/blog/mern-stack-boilerplate"}}
無論是驗證信箱、重設密碼、寄送電子報、更新服務條款、...,即使再小的 Real World App 都必須要考量到寄信服務。如果自己架 Mail Server 明顯過於克難,現在通常都是直接採用第三方服務,例如:Sendgridopen_in_new,但是小弟沒有 $$ 玩不起這樣的服務,所以在 Boilerplate 中使用的是折衷作法,搭配 Nodemailer 這個 Library 利用 Gmail 來發信。
Nodemaileropen_in_new 是一個 Plugin-Based 的發信 Library,目前總共支援 36 種服務,包括 Gmail、Sendgrid、Amazon 的 SES。
在 Boilerplate 中我們把 Nodemailer 的原生寫法包裝成 open_in_new,保留日後擴充的彈性,目前只有 這個 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, }); }); },};
基於成本考量,我們目前是使用免費的 Gmail 服務,讀者可以依照自己喜好修改 open_in_new,套用自己熟悉的服務。
另外,使用 Gmail 要記得申請應用程式專用的密碼,否則當你的 App 丟到 Travis 跑測試,或是部署到 Heroku 正式上線時,很可能被 Google 誤判為有人從美國入侵你的帳號。應用程式密碼的申請需要先啟用兩階段驗證,接著才能申請,完整教學請看 Boilerplate 的 README#Gmailopen_in_new
Nodemailer 的 Options 可以傳入 Html 作為信件內容,但是我們依然是運行在 MVC 的架構下,所以其實可以將 Html Option 抽取成獨立的元件,再呼叫 React-Dom 的 產生 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} /> ), })
Day 20 - Infrastructure - Mail Service
Day 20 - Infrastructure - Mail Service