本篇文章將介紹如何使用 Docker 快速搭建一個適用於 HomeLab 和開發階段使用的郵件閘道器,用來快速聚合各種軟體的通知訊息。當然,你也可以用它來快速驗證各種軟體中的郵件配置是否正確。
如果你熟悉 Docker 的話,大概十分鐘,你將會擁有一套完全屬於自己的郵件通知聚合服務,而這個服務,只需要 20MB 左右的記憶體消耗,非常輕量。
寫在前面
最近在整理家裡的部署的軟體和服務,這些服務多數都擁有“郵件通知”的能力,並會在必要的時候,使用“傳送郵件”的方式通知使用者一些必要的資訊,比如:任務執行完畢、敏感操作、根據計劃任務跑完的資料統計摘要等。
以往部署這些軟體的時候,在郵件通知功能配置上,我們的選擇無非是三種:註冊一個真實的郵箱,使用我們自己已經在用的郵箱賬號,關閉郵件通知功能。
當軟體比較少的時候,不論選擇哪種方案,都是可以的,因為我們的一次性操作和維護成本都比較低。
但當我們部署了越來越多的軟體和服務之後,關閉郵件通知屬於“鴕鳥行為”,是不推薦的;在不能100%確定軟體可靠性的前提下,所有軟體共享一個郵箱賬號,顯然是不安全的;最可靠的方案,便是為為每一個軟體配置不同的郵箱賬號。
而如果為每一個軟體都配置獨立的郵箱賬號,維護郵箱賬號的時間成本,將會變得不可忽視,因為你永遠不知道什麼時候、哪一個郵箱賬號會有問題,以及在什麼時候你會漏掉重要的應用訊息。
所以,我開始尋找一個適用於個人或者小團隊的、私有化部署的郵件閘道器方案,降低賬號的維護成本和經濟成本,以及儘可能減少不必要的公網資料交換。
軟體選型
為了解決上面的問題,一般可以選擇兩類軟體方案:郵局類軟體、郵件測試閘道器。
我們先來聊聊郵局類應用。
郵局類軟體應用
郵局類軟體,顧名思義,和我們日常使用的 GMail、Outlook、QQ 郵箱、163 郵箱等等。在 GitHub 上,我們也可以找到不少優秀的郵局軟體應用,比如下面這些:
- (11.4k Stars)https://github.com/postalserver/postal
(10.9k Stars)https://github.com/mail-in-a-box/mailinabox
- 可以比較簡單的和 NextCloud Mail 一起使用(625 Stars)https://github.com/nextcloud/mail
- (8.7k Stars) https://github.com/docker-mailserver/docker-mailserver
- (4.9k Stars)https://github.com/mailcow/mailcow-dockerized
- (3.5k Stars)https://github.com/Mailu/Mailu
- (2.1k Stars)https://github.com/modoboa/modoboa
上面的開源方案都可以作為我們日常使用的雲服務、知名郵件廠商的替代方案使用。
但是通常情況下,這類軟體會包含非常多的元件和能力,比如:Web 介面、多賬戶支援、多種郵局聚合、各種郵件協議支援、郵件推送、垃圾郵件審查、郵件防火牆、各種複雜的郵件相關的 DNS 支援等等。
隨著軟體功能的豐富完善,軟體執行過程中的資源消耗和使用中的功能複雜度自然也就上去了,加上這幾個頭部的專案,技術選型多是 Ruby、Python,資源使用自然更是“雪上加霜”。
考慮到我不需要多使用者支援,並且我希望我的應用始終是輕量可靠的。所以,我將目光轉向了:測試閘道器類應用。
郵件測試閘道器類應用
坦白說,能夠符合我前文中提到的大部分需求,並具備比較低的資源佔用的專案並不多。如果再限制能夠快速進行功能驗證(跑起來看效果)的專案,那就更屈指可數啦:
- (5.6k Stars)https://github.com/sj26/mailcatcher
- (3.2k Stars)https://github.com/maildev/maildev
在簡單使用之後,我選擇了以第二個專案,將它作為程式碼基進行二次開發。畢竟基於在以往專案中的經驗,相比較 Ruby 的效能和效率,我對 Node 更有信心。
如果你等不及驗證效果,可以跳過下面的小節,直接閱讀文章的 “使用 Docker 進行快速體驗”部分。
基於 MailDev 進行二次開發
從專案當前出現的問題和社群裡的反饋裡,我們可以看到幾個比較明顯的問題:
- 軟體文件和官方映象似乎“對不上號”,一些程式碼中的依賴配置項也是有問題的,會導致軟體無法正常使用。 issue #376、issue list
- 作者官宣棄坑,後來者做了 fork 版本,但僅僅是解決了一些基礎問題。issue #335
- 軟體依賴和執行時都過於陳舊,依賴的 lib 的版本缺乏有效管理,NPM 子依賴中不少依賴都已經被廢棄或者存在安全隱患。
- 使用更可靠的 Markdown 和 HTML 互相轉化方案,對內容進行安全的標籤過濾。
所以,我花了一些時間,針對原來的程式碼做了一些調整:
- 升級了 Node Runtime 到 v16 TLS。
- 將各種基礎依賴升級到可靠版本,解決各種安全問題。
- 重新構建可用的 Docker 容器版本。
如果你好奇到底改了哪些內容的話,可以看這裡的提交記錄:https://github.com/maildev/maildev/compare/master...soulteary:master
接下來,我們來看看如何通過容器快速使用這個“郵件工具”吧。
使用 Docker 快速體驗郵件閘道器
如果我們想啟動一個“郵件閘道器”,可以直接使用“一句話”的容器命令來解決戰鬥:
docker run -p 1080:1080 -p 1025:1025 soulteary/maildev
當命令執行完畢,我們將能夠看到類似下面的日誌輸出:
MailDev using directory /tmp/maildev-1
MailDev webapp running at http://0.0.0.0:1080
MailDev SMTP Server running at 0.0.0.0:1025
接著在瀏覽器中開啟 http://0.0.0.0:1080
,就能看到下圖一樣的收件箱介面了。
如果我們需要測試郵件聚合功能是否能夠正常工作,只需要使用郵件客戶端、配置任意使用者名稱和密碼,向 0.0.0.0:1025
埠傳送郵件,就能夠看到效果啦。
還記得上文中需要配置不同賬號的問題嗎?是不是很輕鬆的就解決啦?甚至你還可以配置郵件轉發真實郵箱、限制只接收某些賬號的郵件訊息。
使用 Node.js 快速驗證服務功能
相比較使用客戶端,我更喜歡使用程式碼來做快速驗證。
這裡為了方便描述,我使用 Node.js 寫了一個非常簡單的發信指令碼:
'use strict'
const nodemailer = require('nodemailer')
async function main () {
const { user, pass } = await nodemailer.createTestAccount()
let transporter = nodemailer.createTransport({
host: '0.0.0.0',
port: 1025,
auth: { type: 'login', user, pass }
})
// send mail with defined transport object
let info = await transporter.sendMail({
from: '\'Fred Foo ?\' <foo@example.com>', // sender address
to: 'bar@example.com, baz@example.com', // list of receivers
subject: 'Hello ✔', // Subject line
text: 'Hello world?', // plain text body
html: '<b>Hello world?</b>' // html body
})
console.log('Message sent: %s', info.messageId)
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info))
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
}
main().catch(console.error)
將上面的程式碼儲存為 example-sendmail.js
,接著執行 node example-sendmail.js
,順利的話,我們將看到類似下面的日誌輸出:
Message sent: <c9867b60-8c5d-df8d-2476-39f5dd77f856@example.com>
Preview URL: false `
接著,在瀏覽器中開啟 http://0.0.0.0:1080
,我們將看到 MailDev 的介面中多了一份意料之中的“郵件”,郵件正文正是我們上面寫程式碼中的內容。
在不進行額外的程式碼調整之前,我們多重複幾次上面的發信操作,就可以模擬出日常學習和工作中各種應用的郵件通知傳送場景。
此時,MailDev 的列表中就會實時展示新到的“郵件”了。
使用 Docker-Compose 啟動服務
為了方便我的老讀者們,讓大家能夠一起偷懶,按照慣例,我提供一個簡單的容器編排配置檔案:
version: '3'
services:
maildev:
image: soulteary/maildev
restart: always
environment:
- TZ=Asia/Shanghai
- MAILDEV_WEB_PORT=1080
- MAILDEV_SMTP_PORT=1025
ports:
- "1080:1080"
- "1025:1025"
將上面的內容儲存為 docker-compose.yml
,接著使用 docker-compose up -d
啟動應用,和上文提到的一樣,我們就能夠在瀏覽器中訪問 http://localhost:1080
來瀏覽和管理“郵件內容”,並通過 1025
埠來進行郵件匯聚操作啦。
最後
和之前提到過的其他的專案一樣,接下來我將持續改進這個專案。短時間內,我希望它能夠更好的支援 WebHook、並和一些訊息推送軟體進行打通,更好的支援我的 HomeLab 場景。
如果你對這個專案感興趣、又比較“心急”的話,可以訪問專案原始碼:https://github.com/soulteary/maildev 進行 DIY。當然,也歡迎你在專案 issue 中留下你對這個專案的建議和想法。
--EOF
我們有一個小小的折騰群,裡面聚集了幾百位喜歡折騰的小夥伴。
在不發廣告的情況下,我們在裡面會一起聊聊軟硬體、HomeLab、程式設計上的一些問題,也會在群裡不定期的分享一些技術沙龍的資料。
喜歡折騰的小夥伴歡迎掃碼新增好友。(新增好友,請備註實名,註明來源和目的,否則不會通過稽核)
本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)
本文作者: 蘇洋
建立時間: 2022年03月15日
統計字數: 5362字
閱讀時間: 11分鐘閱讀
本文連結: https://soulteary.com/2022/03...