使用 Docker 搭建适用于 HomeLab 的轻量邮件网关

本篇文章将介绍如何使用 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,资源使用自然更是“雪上加霜”。
【使用 Docker 搭建适用于 HomeLab 的轻量邮件网关】考虑到我不需要多用户支持,并且我希望我的应用始终是轻量可靠的。所以,我将目光转向了:测试网关类应用。
邮件测试网关类应用
坦白说,能够符合我前文中提到的大部分需求,并具备比较低的资源占用的项目并不多。如果再限制能够快速进行功能验证(跑起来看效果)的项目,那就更屈指可数啦:
  • (5.6k Stars)https://github.com/sj26/mailcatcher
  • (3.2k Stars)https://github.com/maildev/maildev
在简单使用之后,我选择了以第二个项目,将它作为代码基进行二次开发。毕竟基于在以往项目中的经验,相比较 Ruby 的性能和效率,我对 Node 更有信心。
如果你等不及验证效果,可以跳过下面的小节,直接阅读文章的 “使用 Docker 进行快速体验”部分。
基于 MailDev 进行二次开发 从项目当前出现的问题和社区里的反馈里,我们可以看到几个比较明显的问题:
  1. 软件文档和官方镜像似乎“对不上号”,一些代码中的依赖配置项也是有问题的,会导致软件无法正常使用。 issue #376、issue list
  2. 作者官宣弃坑,后来者做了 fork 版本,但仅仅是解决了一些基础问题。issue #335
  3. 软件依赖和运行时都过于陈旧,依赖的 lib 的版本缺乏有效管理,NPM 子依赖中不少依赖都已经被废弃或者存在安全隐患。
  4. 使用更可靠的 Markdown 和 HTML 互相转化方案,对内容进行安全的标签过滤。
所以,我花了一些时间,针对原来的代码做了一些调整:
  • 升级了 Node Runtime 到 v16 TLS。
  • 将各种基础依赖升级到可靠版本,解决各种安全问题。
  • 重新构建可用的 Docker 容器版本。
使用 Docker 搭建适用于 HomeLab 的轻量邮件网关
文章图片

如果你好奇到底改了哪些内容的话,可以看这里的提交记录: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,就能看到下图一样的收件箱界面了。
使用 Docker 搭建适用于 HomeLab 的轻量邮件网关
文章图片

如果我们需要测试邮件聚合功能是否能够正常工作,只需要使用邮件客户端、配置任意用户名和密码,向 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 \' ', // sender address to: 'bar@example.com, baz@example.com', // list of receivers subject: 'Hello ?', // Subject line text: 'Hello world?', // plain text body html: 'Hello world?' // html body })console.log('Message sent: %s', info.messageId) // Message sent: // 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: Preview URL: false `

接着,在浏览器中打开 http://0.0.0.0:1080,我们将看到 MailDev 的界面中多了一份意料之中的“邮件”,邮件正文正是我们上面写代码中的内容。
使用 Docker 搭建适用于 HomeLab 的轻量邮件网关
文章图片

在不进行额外的代码调整之前,我们多重复几次上面的发信操作,就可以模拟出日常学习和工作中各种应用的邮件通知发送场景。
此时,MailDev 的列表中就会实时展示新到的“邮件”了。
使用 Docker 搭建适用于 HomeLab 的轻量邮件网关
文章图片

使用 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...

    推荐阅读