使用 Docker 搭建適用於 HomeLab 的輕量郵件閘道器

soulteary發表於2022-03-16

本篇文章將介紹如何使用 Docker 快速搭建一個適用於 HomeLab 和開發階段使用的郵件閘道器,用來快速聚合各種軟體的通知訊息。當然,你也可以用它來快速驗證各種軟體中的郵件配置是否正確。

如果你熟悉 Docker 的話,大概十分鐘,你將會擁有一套完全屬於自己的郵件通知聚合服務,而這個服務,只需要 20MB 左右的記憶體消耗,非常輕量。

寫在前面

最近在整理家裡的部署的軟體和服務,這些服務多數都擁有“郵件通知”的能力,並會在必要的時候,使用“傳送郵件”的方式通知使用者一些必要的資訊,比如:任務執行完畢、敏感操作、根據計劃任務跑完的資料統計摘要等。

以往部署這些軟體的時候,在郵件通知功能配置上,我們的選擇無非是三種:註冊一個真實的郵箱,使用我們自己已經在用的郵箱賬號,關閉郵件通知功能。

當軟體比較少的時候,不論選擇哪種方案,都是可以的,因為我們的一次性操作和維護成本都比較低

但當我們部署了越來越多的軟體和服務之後,關閉郵件通知屬於“鴕鳥行為”,是不推薦的;在不能100%確定軟體可靠性的前提下,所有軟體共享一個郵箱賬號,顯然是不安全的;最可靠的方案,便是為為每一個軟體配置不同的郵箱賬號

而如果為每一個軟體都配置獨立的郵箱賬號,維護郵箱賬號的時間成本,將會變得不可忽視,因為你永遠不知道什麼時候、哪一個郵箱賬號會有問題,以及在什麼時候你會漏掉重要的應用訊息。

所以,我開始尋找一個適用於個人或者小團隊的、私有化部署的郵件閘道器方案,降低賬號的維護成本和經濟成本,以及儘可能減少不必要的公網資料交換。

軟體選型

為了解決上面的問題,一般可以選擇兩類軟體方案:郵局類軟體、郵件測試閘道器。

我們先來聊聊郵局類應用。

郵局類軟體應用

郵局類軟體,顧名思義,和我們日常使用的 GMail、Outlook、QQ 郵箱、163 郵箱等等。在 GitHub 上,我們也可以找到不少優秀的郵局軟體應用,比如下面這些:

上面的開源方案都可以作為我們日常使用的雲服務、知名郵件廠商的替代方案使用。

但是通常情況下,這類軟體會包含非常多的元件和能力,比如:Web 介面、多賬戶支援、多種郵局聚合、各種郵件協議支援、郵件推送、垃圾郵件審查、郵件防火牆、各種複雜的郵件相關的 DNS 支援等等。

隨著軟體功能的豐富完善,軟體執行過程中的資源消耗和使用中的功能複雜度自然也就上去了,加上這幾個頭部的專案,技術選型多是 Ruby、Python,資源使用自然更是“雪上加霜”。

考慮到我不需要多使用者支援,並且我希望我的應用始終是輕量可靠的。所以,我將目光轉向了:測試閘道器類應用。

郵件測試閘道器類應用

坦白說,能夠符合我前文中提到的大部分需求,並具備比較低的資源佔用的專案並不多。如果再限制能夠快速進行功能驗證(跑起來看效果)的專案,那就更屈指可數啦:

在簡單使用之後,我選擇了以第二個專案,將它作為程式碼基進行二次開發。畢竟基於在以往專案中的經驗,相比較 Ruby 的效能和效率,我對 Node 更有信心。

如果你等不及驗證效果,可以跳過下面的小節,直接閱讀文章的 “使用 Docker 進行快速體驗”部分。

基於 MailDev 進行二次開發

從專案當前出現的問題和社群裡的反饋裡,我們可以看到幾個比較明顯的問題:

  1. 軟體文件和官方映象似乎“對不上號”,一些程式碼中的依賴配置項也是有問題的,會導致軟體無法正常使用。 issue #376issue list
  2. 作者官宣棄坑,後來者做了 fork 版本,但僅僅是解決了一些基礎問題。issue #335
  3. 軟體依賴和執行時都過於陳舊,依賴的 lib 的版本缺乏有效管理,NPM 子依賴中不少依賴都已經被廢棄或者存在安全隱患。
  4. 使用更可靠的 Markdown 和 HTML 互相轉化方案,對內容進行安全的標籤過濾。

所以,我花了一些時間,針對原來的程式碼做了一些調整:

  • 升級了 Node Runtime 到 v16 TLS。
  • 將各種基礎依賴升級到可靠版本,解決各種安全問題。
  • 重新構建可用的 Docker 容器版本。

針對 MailDev 進行細節調整

如果你好奇到底改了哪些內容的話,可以看這裡的提交記錄: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,就能看到下圖一樣的收件箱介面了。

MailDev 的歡迎介面

如果我們需要測試郵件聚合功能是否能夠正常工作,只需要使用郵件客戶端、配置任意使用者名稱和密碼,向 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

在不進行額外的程式碼調整之前,我們多重複幾次上面的發信操作,就可以模擬出日常學習和工作中各種應用的郵件通知傳送場景。

此時,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...

相關文章