整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Node.js 應用篇 - 使用 Nodemailer 來發送 Email

前言
這一篇我將會記錄一下如何用 Nodemailer 來發送 Email,而這一篇將會記錄使用 Gmail 以及 OAuth2 跟帳號密碼(應用程式密碼)的兩種方式來發送 Email。
事前準備
首先這邊我會先提供事前的準備環境,你可以透過以下連結取用
這個環境相對單純一點,我只有安裝 nodemailer、googleapis、dotenv 套件,其餘都是 Express 產生器的東西。
如果你不想使用這個初始範本,你可以自己建立一個 Express 專案,然後安裝 nodemailer、googleapis、dotenv 套件即可。
1 | |
Nodemailer
雖然早期我有寫過關於 全端勇士之路 Node.js-OAuth 2.0 & nodemailer & Gmail,但我認為這一篇有點過於老舊,所以我決定重新寫一篇。
那麼 Nodemailer 是什麼神奇的東西呢?簡單來講它是一個 Node.js 的套件,可以讓我們在 Node.js 環境下發送 Email,而這個功能對於一個網站來說是非常重要的,因為我們可以透過 Email 來發送驗證碼、通知信、訂閱信等等,所以在實戰上可以說是非常常見的。
以官方文件來講底下就有提供一個算是滿完整的 Example:
1 | |
但是今天我們的目標是要使用 Gmail 來發送 Email,並且是搭配 OAuth2 的方式來發送,所以我們就來看看怎麼做吧。
所以我們必須要先了解 Gmail 的限制,那麼有哪些限制呢?這邊我就只列出比較需要注意的限制:
- 每日發送限制:500 封
- 單一電子郵件收件者超過 500 封
- 每封電子郵件大小上限:25 MB
其他部分舉凡…濫發垃圾郵件、濫發廣告郵件、濫發病毒郵件等等,都是不被允許的,如果被 Google 發現,你的帳號可能會被鎖定,所以請務必注意哩。
使用 OAuth 2.0 寄信
早期許多 Nodemailer 文章教學都是介紹使用帳號密碼的方式來介紹,但是後來 Google 開始限制使用這種方式,因為使用傳統帳號密碼來發送信件的方式並不是很安全,所以 Google 開始推出 OAuth2 的方式來取代傳統帳號密碼的方式,但這種方式其實比較複雜,因為你必須要先取得授權,所以前面一開始我也會先介紹比較複雜的部分。
建立專案
首先這邊我們要先到 「Google Cloud Platform」建立一個新專案,當然你也可以使用舊專案,但是我建議你還是建立一個新專案,因為這樣比較不會搞混。

專案名稱你可以自己取,這邊我取名為「nodemailer-example」

建立過程中稍微等它一下下…

建立成功後,你可以在通知或是剛剛選取專案的地方找到剛剛建立的專案,然後點選進去


啟用 API 和服務
接著請你點一下左邊漢堡選單,然後點選「已啟用的 API 和服務」

接著點一下上方「啟用 API 和服務」

接著搜尋「Gmail API」,然後點選「Gmail API」

接著點一下「啟用」

設定 OAuth 同意畫面
接著回到「API 和服務」,然後點選「憑證」

要「建立憑證」之前,如果你跟我一樣是第一次設定的話,你會看到一個提示,提示你要先設定 OAuth 同意畫面,所以請你點選「設定同意畫面」

接著請你選擇「外部」,然後點選「建立」

接下來會進入「編輯應用程式註冊申請」畫面,這邊要填寫一些資料,除了底下這幾個欄位是必填的,其餘都是選填的:
- 應用程式名稱:你可以自己取名,這邊我取名為「nodemailer-example」
- 使用者支援電子郵件:選你自己 Email
- 開發人員聯絡資訊:填寫你自己 Email
如果不確定,你可以依照我圖片這樣填寫就好

接下來會到達「範圍」的設定頁面,這邊直接繼續就好

接下來要設定「測試使用者」,基本上如果你這個應用程式發布狀態是「測試中」的話,你就必須設定一些可以使用這個應用程式的測試使用者,這邊你可以點一下 「Add Users」並輸入自己 Google 帳號,如果是正式環境的話則不用,那我這邊就先不設定直接點選「儲存並繼續」。
基本上你到達「摘要」時,就完成了「OAuth 同意畫面」的設定囉

建立憑證
接下來你就可以回到「憑證」的頁面,然後點選「建立憑證」,接著點選「OAuth 用戶端 ID」

接著在應用程式類型欄位選擇「網路應用程式」,然後輸入以下欄位:
- 名稱:你可以自己取名,這邊我取名為「nodemailer-example-web」
- 已授權的重新導向 URI:請輸入
http://localhost:3000/auth/google/callback

Note
在我先前的文章中,我有提到過這個欄位要填寫「https://developers.google.com/oauthplayground/」的網址,但這邊我們要換另一種方式。
接下來按下「建立」後就可以取得 Client ID 與 Client Secret,這兩個請不要外流,因為這兩個是用來驗證你的身份的,如果被人拿去亂用,你的帳號可能會被 Google 鎖定(你也可以直接下載 JSON 檔案,裡面就有這兩個資訊)
到這邊為止,我們的 Gmail OAuth 相關前置動作就終於準備好了,接下來就可以開始撰寫程式碼囉~
撰寫 Gmail OAuth 程式碼
那麼前面我已經有先提供基本的環境,所以我們就可以直接開始撰寫程式碼了。
Note
請務必確定你的專案內有無安裝nodemailer、googleapis、dotenv這幾個套件,否則稍後可能會出現錯誤無法往下練習。
建立 Env
首先這邊請你在專案底下建立一個 .env 檔案,內容如下:
1 | |
這幾個資訊都可以在剛剛建立憑證時取得,如果你有下載 JSON 檔案的話,你可以直接打開 JSON 檔案,裡面就有這些資訊

建立 Google OAuth2 Client
接下來請你在根目錄下建立一個資料夾,名稱為 config,然後在裡面建立一個檔案,名稱為 googleOAuth2Client.js,內容如下:
1 | |
這邊我們使用 googleapis 套件來建立 Google OAuth2 Client,這邊我們使用 google.auth.OAuth2 來建立,並且傳入三個參數:
- CLIENT_ID:你的 Client ID
- CLIENT_SECRET:你的 Client Secret
- REDIRECT_URI:你的 Redirect URI
建立 Google OAuth2 URL
接下來請你在根目錄下建立一個資料夾,名稱為 routes,然後在裡面建立一個檔案,名稱為 auth.js,內容如下:
1 | |
接著到 app.js 加入以下
1 | |
接下來你就可以透過網址 http://localhost:3000/auth/login 來取得 Google OAuth2 URL,這時候你會被導向到 Google 登入頁面

點選你要登入的帳號,接下來會出現一個警告畫面,這邊不用太擔心畢竟是你的應用程式,只需要點開「進階」,然後點選「前往 nodemailer-example(不安全)」即可

接下來這邊按下「允許」

完成後就會重新導向回 http://localhost:3000/auth/google/callback 這個網址,並且取得 code,這個 code 就是用來取得 tokens 的,而 tokens 就是用來驗證你的身份的。
而這邊我們也將 tokens 儲存在 session 中,這樣我們就可以在後續的程式碼中使用 tokens 來驗證身份。
但是這邊你應該會發生一個錯,也就是以下
1 | |
這個原因是預設 Express 產生器並沒有啟用 session 功能,所以我們必須要自己啟用 session 功能,這邊我們使用 express-session 來啟用 session 功能,所以請你在根目錄下執行以下指令:
1 | |
接著到 app.js 加入以下
1 | |
這樣你才不會發生「TypeError: Cannot set properties of undefined」的錯誤唷。
Note
express-session有一個小雷點要注意一下,官方所提供的範例secure屬性是true,這就代表著你本地開發時,你的 session 會沒有辦法儲存下來,只要一換頁面就會被清除,所以這邊我將secure屬性改為false,這樣你就可以在本地開發時使用session功能了。
建立 Nodemailer OAuth2
接下來請你到 routes 資料夾的 index.js,我們要在這邊建立 Nodemailer,內容如下:
1 | |
基本上到這邊為止,你就完成了 Nodemailer 的設定,接下來你可以透過網頁來發送出信件囉~
使用帳號密碼(應用程式密碼)來發送 Email
接下來我想介紹另一種方式發送信箱,為什麼呢?
因為前面的做法是使用了 OAuth 的方式來發送信件,那麼使用 OAuth 的問題在於,如果我今天登入的使用者不是 A 而是 B 的話,那麼就無法寄出,因為我們使用的 Token 與 Refresh Token 都是 A 的,所以這邊我想介紹另一種方式,那就是使用帳號密碼直接寫死並登入,這樣就不會有上述的問題了。
那麼這邊有些人應該有嘗試過使用帳號密碼方式寄送 Gmail,應該大多都有遇過以下錯誤訊息
1 | |
這個錯誤訊息是因為 Google 開始限制使用帳號密碼的方式來寄送信件,早期我們可以到 Google 設定中開啟「低安全性應用程式存取權」,這樣就可以使用帳號密碼的方式來寄送信件,但是後來 Google 也開始限制這個功能,所以我們就無法使用這個方式來寄送信件了。
所以這邊我要教另一種方式哩~
撰寫 Env
接下來請你在原本的 .env 補充以下:
1 | |
接下來準備來也是要去設定一下 Google 的部分,但不會像剛剛那樣複雜。
啟用 Google 設定
首先請你到 Google 設定中心,然後點選「安全性」

如果你沒有啟用二次驗證的話,這邊會建議你啟用後再繼續,避免你無法往後操作唷

Note
後來我建立新帳號實測,Google 是強制你一定要開啟二次驗證的唷。
如果你本身已經有啟用的話,那麼你就可以點一下兩步驟驗證,然後輸入密碼後滾到最下方找到「應用程式密碼」

點進去後,你選擇一下應用程式和裝置
- 應用程式:選擇「郵件」
- 裝置:選擇「其他(自訂名稱)」

接著會跳出要你命名,你可以依照自己需求命名,所以你可以命名為「nodemailer-example」,然後點選「產生」

點下產生後,你就會取得一組 16 字元的密碼,請好好保存不要外流,這會是我們後續使用的密碼

Note
Google 幾乎時常在更新這個介面,所以我往往文章會來不及更新,若又更新的話再麻煩告知我一聲,我會再更新文章內容。
底下是 2023 年 10 月 20 日補上的畫面,如果你發現你找不到「應用程式密碼」的話也不用擔心,你可以在上方搜尋搜尋「應用程式密碼」

接著你就可以在下方 App Name 輸入「nodemail」,然後點選「建立」

建立後,你就會跳出一組類似亂碼的密碼,這就是我們要使用的密碼,請好好保存不要外流唷~

撰寫程式碼
接下來就是撰寫程式碼了,你只需要將你要用來發信的 Email 帳號跟剛剛生成的應用程式密碼填入到 Env
1 | |
Note
系統產生的應用程式密碼看起來會有空格,請去除不要複製空格;GMAIL_USER就是你的 Gmail 帳號,而GMAIL_PASS就是你的應用程式密碼。
接下來請你到 routes 資料夾的 email.js,貼入以下內容
1 | |
恭喜你,到這邊為止你就可以正常發信了,而且不是透過 OAuth2 的方式,而是透過帳號密碼的方式,這樣就不會有上述的問題了~
完整範例程式碼
最後這邊我也附上完整的程式碼,你可以參考一下
這一份程式碼你可以直接在畫面上點擊按鈕觸發發送信件的,當然,如果你要作為實戰使用還是需要做調整一下哩。
結語
不得不說這一塊真的是有點複雜且混亂,而且目前網路上的資源滿零散的,自己 Try 了不少次才弄出來,所以這邊我就整理一下,希望對你有幫助。
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ