DEFAULTKAVY

Illustrator, Web Developer and VTuber

我搭建了一个自托管邮箱服务

Published on 11/7/25 · Updated on 11/7/25

每个网民在进入这个网络世界时,注册一个邮箱似乎是一个标准的入门程序。大家都会有自己的邮箱地址,但似乎从没想过电子邮箱究竟是个什么东西?毕竟它的概念是如此简单,填写收件人的地址,写上你的内容并发送,整个过程就像写信一样自然。

但其实仔细一想,又会发现电子邮箱有许多神奇之处:为什么我使用的是 gmail.com,收件人使用的是 hotmail.com?为什么能够在不同的域名服务之间进行通信?又是为什么能在 gmail 中查看 hotmail 的邮件?

其实我在开始搭建自己的邮箱服务时,并没有想过这些问题。但是我天真的认为邮箱如此简单的概念,实现起来应该没什么难度吧?

正好最近 MYViki 需要一个邮箱地址来接收大家对网站的建议投稿,我想直接搞个 myviki.com 的邮箱域名可能会更加正式些。就为了这个「更加正式」的感觉,我就付出了好几天的时间,最后才终于发送出第一封来自 myviki.com 的邮件……

现成的企业邮箱服务

其实市面上有非常多实现企业邮箱的方式,比如 Google Workspace、Microsoft Exchange 等。当然,这些都要钱。也有不需要付费的服务,比如 Zoho Mail 就能够免费提供有限的企业邮箱的功能。

Zoho Mail 确实是一个不错的选择,它能让开发者非常便利地拥有一个自己的企业邮箱。但前提是你不需要多个邮箱账号,因为免费的 Zoho Mail 并不提供 IMAP 服务,这是个能够让第三方邮箱软件能够登入邮箱的协议,比如我能够在 Windows Outlook 软件上同时登入多个 Hotmail 和 Gmail 的邮箱,其背后便是 IMAP 协议提供的便利。

我的设想是,未来我会为 myviki.com 开设多个不同功能的邮箱账号,比如 support@myviki.com、contact@myviki.com 之类的。那么同时在一个设备上登入这些账号,或者是让团队中的其他人能够用自己的邮箱软件查看邮件,这项需求就变得异常重要。

然而我实在不想花这个钱,最后把目标变成了搭建一个自托管的邮箱服务。

开始探索

我不知道从哪个讨论串中找到的一个工具:docker-mailserver。我似乎也没做什么研究功课,直接就决定使用这个工具作为我入门搭建邮箱服务的第一步。我相信现在的 Docker 技术相当成熟,很多服务都只需要简单写好配置文件就能够正常运行。

打开 docker-mailserver 的官网文档,一堆陌生的英文名词缩写直接扑面而来。LDAP、SMTP、MUA、MTA、MDA……我去这些都是神马?

这时候我才狠狠意识到一件事:邮箱是一个非常古老的技术,经过几十年的迭代已经成为一个相当复杂的标准体系。我怎么也不会想到,平时使用邮箱你来我往的发送邮件,其背后是有如此复杂的工作原理在运作。

但我也不是第一次从零开始理解一个复杂项目,更何况我已经使用现成的工具来搭建邮箱服务,我想应该也不会太难吧?

好在这个官网文档有好好地科普邮箱的运作方式,推荐想了解邮箱的大家可以读一读这一篇文章

插曲:第零个坑

在邮箱服务的标准协议中,需要开放 IMAP 接口(TCP 143/993)和 SMTP 接口(TCP 25/465/587)。然而我的伺服器其实由两个机器组成:一个是拥有公网 IP 的伺服器,另一个是放在我家的内网伺服器。由于我的 ISP 并没有提供公网 IP 给我,所以我只能在网上租了个小型伺服器作为一个 VPN,所有外网流量都必须经过这个机器转发到我家的伺服器。

我使用的是 WireGuard 的方案,构建了一个虚拟本地网络,并将所有需要链接的机器都加入了这个虚拟本地网络当中。但之前我实在不会设置 iptables 的规则,苦恼于要如何直接把所有流量都转发到内网伺服器,所以用了一个较为取巧的方式:在公网伺服器上使用 Caddy 将流量分别根据网址来反向代理到内网伺服器的 IP 地址以及对应的服务接口上。比如:

myviki.com -> 10.0.0.2:4040

虽然没那么方便且正确,但至少能让所有网站都正常工作。

但这次我要搭建的是邮箱服务,邮箱服务使用的全是 TCP 协议!这并不是 Caddy 能够处理的范围了,以往网站只需要处理 HTTP/HTTPS 协议所以可行,但现在我必须认真学习 iptables 的运作方式,使用正确的转发流量的方案。

由于这不是本篇的主题,我就不展开这些内容了,未来也许我会写一篇关于我如何利用 WireGuard 实现流量转发的功能。

为此,我第一天所花费的时间都用在了把流量正确转发到内网伺服器这件事情上……

第一个坑:SMTP 中继服务

当我把 docker-mailserver 正式运行起来后,其实就已经能够发送邮件了。但你能发出去,对方未必要收。这就是邮箱服务的第一个大坑:域名信誉!

试想想,如果谁都能搭建自己的邮箱服务,能够发送的邮件没有上限……那么你的 Gmail 或 Hotmail 邮箱估计会塞满各种钓鱼和垃圾邮件吧!所以一般上 Gmail 或 Hotmail 这种大型邮箱服务提供商都只会接收拥有良好域名信誉的邮件,来确保用户接收到的邮件至少不会是从乱七八糟的域名发来的。

那我怎么办?我的域名没有任何信誉基础,我要如何才能够得到 Gmail/Hotmail 的信任?这时候资本就狠狠地闻到了有利可图的商机:SMTP 中继服务

当我还在暗暗窃喜自己零成本(除了时间)搭建了邮箱服务,正要舒舒服服使用它的时候,没想到又冒出来了这个从没听过的东西,又花了不少时间翻阅文档和咨询AI。

简单来说,SMTP 是一个发送邮件的服务协议,虽然 docker-mailserver 自带了 SMTP,但是基于你的域名并不受信任,你能做的事情是将这个发送工作交给 SMTP 中继服务提供商帮你发送。这些中继服务提供商的域名拥有良好的域名信誉,能够通过 Gmail/Hotmail 的检测并把你的邮件落地到收件人的邮箱中。

一开始我用的是 Mailgun,因为我看中的是它一天能够免费为你发送100封邮件。但后来我发现它虽然能把邮件发到 Gmail,却无法发送到 Hotmail。根据网络上的说法,Mailgun 有时会把你分配到 IP 信誉没那么好的组别中,造成这种情况发生。似乎这种问题只能联络他们的团队帮你调整,但我这个 I 人是坚决不可能开口寻求帮助的。后来我在论坛中找到有人推荐并切换到 SMTP2GO 这家中继服务提供商,送件问题顺利得到了解决。

这里我想吐个槽,docker-mailserver 的配置文件变量的设置方式实在是有些混乱,官网文档没有写清楚,网上也没给个准确的说法。我在设置 SMTP Relays 的域名和用户名时总是没法设置正确,最后才发现不是在 compose.yml 设置变量,而是在 mailserver.env 中设置才对,差点没把我整崩溃。

第二个坑:AutoDiscover

上面提到了邮箱服务需要开放各种接口(IMAP、SMTP),其中又参杂了 SSL/TLS 和 STARTTLS 协议接口,第一眼看上去真的很混乱,其实对邮箱客户端软件来说也同样非常混乱……

邮箱客户端需要找到这些对应的协议地址以及接口,比如我为 myviki.com 设置了 imap.myviki.com 和 smtp.myviki.com 作为这些协议的地址(虽然他们最终都导向了 mail.myviki.com),并使用了符合标准的 993 以及 465 接口,理论上邮箱客户端应该要以这些标准协议的地址接口作为预设的设定值,让用户在添加邮箱地址账号的时候能免去调整设定的麻烦。

然而我在 Outlook(Windows) 和 Gmail(Android)邮箱客户端中添加邮箱账号时,得到了两个完全不一样的预设,并且都是错误的。

其实我在一开始使用 Outlook 添加账号时,它提供的预设其实非常正确,但后来莫名奇妙变成了其它的值,完全错乱,而我始终找不到其原因。另一方面 Gmail 则是提供了错误的 IMAP 和 SMTP 预设地址,全都指向了 myviki.com。

后来我知道了大部分邮箱客户端都支持 AutoDiscover,能够向你的伺服器获取正确的配置信息。但这个东西我始终没有完成,网上能查到的资讯并不多。目前只能让团队的大家自己手动更改地址接口了。

为了用户界面

docker-mailserver 实在是过于精简,它没有提供给邮箱用户的界面,也没有 Admin GUI,甚至连个 API 都没有。考虑到未来我需要更加灵活的开设账号和让用户拥有更改邮箱账号基本资讯的能力,我觉得我需要换一个邮箱服务工具。

问了问 AI,它给出了几个工具方案。对比了之后,我认为 Poste.io 更加吸引我。

Poste.io 不止有方便进行配置的 Admin 界面,也有让用户查看邮箱、更改邮箱账号密码功能的 Webmail 界面,功能可说是相当地完善。

Poste.io 的后台界面简单明了,而且许多在 docker-mailserver 麻烦的配置到了这里简直轻松无比(也可能是我已经爬过的坑所以相对轻松了)。

部署成功

基本上到这里已经告一段落,这个邮箱服务能够正常的发送与接收邮件,能够在第三方邮箱软件登入,该有的功能都已经实现了。

心得

在一切尘埃落定后,我回顾这几天所遇到的难题,以及整个邮箱协议体系的种种知识点,我发现整个邮箱史几乎都是在为对抗垃圾钓鱼邮件所演绎的进化史。邮箱本身真正带来革命变化的功能其实并不多,我们甚至都没法为自己的邮箱地址设置一个能够在其它邮箱软体正常显示的头像……

我现在偶尔会思考这么一件事,如果今天我们要重新定义邮箱这个协议标准,是否能够构思出堪比现代即时通讯软体的运作协议呢?

但我现在只想把这个邮箱服务放在一边,完全不想再动它了。