简介:Mailcow 是一套基于 Docker 容器化技术构建的开源邮件服务器解决方案,面向需要自建企业邮箱、搭建邮件系统的运维人员与开发者,帮助解决邮件收发、反垃圾、反病毒及域名认证等一体化部署难题。资源包共约 2000 个文件,整体约 10.98MB,以 1515 个 PHP 文件为核心业务代码,辅以 78 个 Markdown 说明文档、61 个 JSON 配置、54 个 Shell 脚本、42 个 XML 与 36 个 JavaScript 文件,并包含 Dockerfile、yml、conf 等容器编排与配置模板,以及少量 Python、Lua、Sieve 脚本用于扩展与过滤逻辑。已有 202 人学习下载。通过该资源可获取完整的邮件服务组件结构,涵盖 SMTP、IMAP、POP3、Webmail 及 Antispam、Antivirus、DKIM、DMARC、SPF 等安全机制,便于理解容器化邮件系统的目录组织、配置方式与升级维护思路,适合作为自建邮件服务的参考实现。
1. Mailcow 邮件服务器:从零搭建一套能收能发的自托管邮件系统
公司邮箱续费又涨了,三个域名二十个账号一年要小一万,而且附件存储还另算钱。去年我把整套邮件系统迁到了 Mailcow 上,一台 4G 内存的 VPS 跑了大半年,日常收发、反垃圾、多域名别名、客户端同步全部正常。Mailcow 是一个基于 Docker 的开源邮件服务器解决方案,把 Postfix、Dovecot、Rspamd、ClamAV、SOGo 等一堆组件打包成开箱即用的容器编排,自带 Web 管理后台。它解决的核心问题是:让没有专职运维的团队也能自建一套功能完整的邮件系统,而不是花几周去啃 Postfix 配置。适合谁?中小团队运维、独立开发者、需要多域名邮箱又不想被 SaaS 按人头收费的人。但前提是你得有一台能开 25 端口的机器,并且愿意花一个下午把 DNS 记录配明白。
2. 部署前的硬性条件:端口、DNS 与主机名怎么定
2.1 为什么 25 端口和 PTR 记录是绕不过去的坎
自建邮件服务器最大的翻车点不在软件本身,而在网络层。绝大多数云厂商默认封禁 25 端口出站,你装完 Mailcow 发现能收不能发,日志里全是 Connection timed out,这就是典型症状。常见做法是开工单申请解封,或者直接选那些明确允许邮件服务的厂商。除了端口,反向解析(PTR)必须由 IP 所属方设置成你的邮件域名,否则 Gmail、Outlook 基本会把你的邮件判为垃圾。PTR 不是你在自己 DNS 面板里加的,得在 VPS 控制台提交。主机名建议用mail.example.com这种独立子域,不要用根域,A 记录指向服务器 IP,同时把mail.example.com设成 PTR 的值,三者一致才过得了基础信誉检查。
2.2 最小 DNS 记录清单与填写示例
下面这张表是我每次新部署都会照着填的记录,缺一条都可能导致收不到信或进垃圾箱。MX 记录指向主机名,SPF 用 TXT 记录声明允许发信的 IP,DKIM 和 DMARC 在 Mailcow 后台生成后再回填。
| 记录类型 | 主机名 | 值 | 说明 |
|---|---|---|---|
| A | mail.example.com | 你的服务器 IP | 邮件主机地址 |
| MX | example.com | mail.example.com (优先级 10) | 收信路由 |
| TXT | example.com | v=spf1 mx ~all | SPF 声明 |
| TXT | _dmarc.example.com | v=DMARC1; p=quarantine; rua=mailto:admin@example.com | DMARC 策略 |
| CNAME | autodiscover.example.com | mail.example.com | 客户端自动发现 |
| CNAME | autoconfig.example.com | mail.example.com | 同上 |
DKIM 记录不在这张表里,因为它的公钥要在 Mailcow 装好之后由系统生成,你再去域名 DNS 面板加一条dkim._domainkey.example.com的 TXT。顺序不能反,先生成后添加,添加完在后台点验证。
注意:DNS 生效有延迟,改完记录别急着测,等 TTL 过了再排查,否则你会对着一个还没生效的解析怀疑人生。
2.3 服务器规格与系统选择
官方推荐最低 2 核 4G 内存、20G 磁盘。我实际跑下来,4G 内存是底线,Rspamd 和 ClamAV 比较吃内存,2G 的机器会在收信高峰时 OOM。系统选 Debian 12 或 Ubuntu 22.04,干净系统,不要预装 Nginx 或 Postfix,否则端口冲突。磁盘建议 SSD,邮件附件多了之后 IO 会成为瓶颈。如果你打算跑多个域名、几百个账号,直接上 8G 内存,别省这个钱。
3. 用 Docker Compose 把 Mailcow 跑起来:命令与参数逐条拆
3.1 获取源码与首次配置生成
Mailcow 的部署入口是generate_config.sh,它会问你主机名和时区,然后生成mailcow.conf。这个文件是整个系统的配置中心,后面所有端口、路径、数据库密码都在里面。
# 克隆仓库到 /opt 下,这是官方推荐路径 cd /opt git clone https://github.com/mailcow/mailcow-dockerized cd mailcow-dockerized # 运行配置生成脚本,交互式输入主机名 # 主机名填 mail.example.com,时区填 Asia/Shanghai ./generate_config.sh脚本执行完会生成mailcow.conf。逻辑说明:这个脚本做了三件事——检测系统环境、根据你输入的主机名写入配置、生成随机数据库密码。参数说明:主机名必须和你的 PTR、A 记录完全一致,时区影响日志和邮件时间戳。如果你输错了主机名,直接删掉mailcow.conf重新跑脚本,不要手动改,容易漏字段。
3.2 拉镜像并启动全部容器
配置生成后,一条命令拉起整套服务。首次执行会拉取十几个镜像,视网络情况需要几分钟到十几分钟。
# 拉取镜像并后台启动所有容器 docker compose pull docker compose up -d # 查看容器状态,确认全部是 running 或 healthy docker compose ps逻辑说明:docker compose pull先把所有镜像拉到本地,避免启动时超时;up -d按依赖顺序启动。参数说明:-d是后台运行,调试阶段可以去掉它看实时日志。启动完成后,用docker compose ps检查,正常情况下应该有二十个左右的容器在跑,包括postfix-mailcow、dovecot-mailcow、rspamd-mailcow、nginx-mailcow、mysql-mailcow等。如果有容器反复重启,先看它的日志:docker compose logs <服务名>,八成是端口被占或内存不足。
3.3 首次登录后台与管理员账号
浏览器打开https://mail.example.com,首次访问会提示证书不受信任,这是因为 Mailcow 自签了证书,接受后进入登录页。默认管理员账号是admin,密码是moohoo。
# 如果你忘了改默认密码,可以用命令行重置 docker compose exec mysql-mailcow mysql -u root -p mailcow -e \ "UPDATE admin SET password = SHA2('新密码', 256) WHERE username = 'admin';"逻辑说明:这条 SQL 直接改数据库里的管理员密码哈希。参数说明:SHA2('新密码', 256)是 Mailcow 存储密码的方式,别用明文。改完刷新后台即可。登录后第一件事是改密码,第二件事是进「系统配置」把主机名、时区、管理员邮箱核对一遍。
3.4 添加域名、邮箱账号与 DKIM 密钥
后台左侧「邮件设置」→「域名」→「添加域名」,填入example.com。保存后进入该域名详情页,找到 DKIM 部分,点击生成密钥。系统会给你一段公钥,复制到 DNS 面板添加 TXT 记录,主机名是dkim._domainkey。
# 生成后可以用 dig 验证 DKIM 记录是否生效 dig TXT dkim._domainkey.example.com +short逻辑说明:DKIM 用私钥签名外发邮件,收件方用 DNS 里的公钥验签,验签通过才认为邮件未被篡改。参数说明:+short只输出结果值,方便肉眼比对。如果返回为空,说明 DNS 还没生效或记录填错。域名配好后,进「邮箱」→「添加邮箱」,填账号名、密码、配额。配额按需设,默认 3072MB,小团队够用。
4. 收发链路调通:从发一封测试邮件到看日志定位
4.1 用 swaks 做端到端发信测试
装好账号后,别急着用 Outlook 连,先用命令行工具swaks测发信链路,它能直接告诉你卡在哪一步。
# 安装 swaks apt install swaks -y # 用刚创建的账号发一封测试邮件到 Gmail swaks --to yourtest@gmail.com \ --from user@example.com \ --server mail.example.com \ --auth LOGIN \ --auth-user user@example.com \ --auth-password '你的密码' \ --tls逻辑说明:--server指定发信服务器,--auth走认证,--tls强制加密。参数说明:如果返回250 OK说明投递成功;如果卡在认证阶段,检查密码和账号是否启用;如果卡在 TLS,检查证书。发完后去 Gmail 收件箱看是否收到,同时检查垃圾箱——第一次发信大概率进垃圾箱,这是正常的,等 DKIM、SPF、DMARC 全部生效并积累一点信誉后会好转。
4.2 收信测试与日志追踪
收信测试反过来,用外部邮箱发到你的域名,然后看 Mailcow 日志确认投递路径。
# 实时跟踪 postfix 日志,观察收信过程 docker compose logs -f postfix-mailcow # 查看 dovecot 日志,确认邮件是否写入用户邮箱 docker compose logs -f dovecot-mailcow逻辑说明:Postfix 负责 SMTP 收发,Dovecot 负责 IMAP 存储。一封邮件进来,先过 Postfix,再经 Rspamd 反垃圾,最后交给 Dovecot 落盘。参数说明:-f是持续输出,按 Ctrl+C 退出。如果 Postfix 日志显示status=sent但用户收不到,去 Dovecot 日志看是不是配额满了或用户不存在。如果日志显示status=deferred,看delay原因,常见的是 DNS 解析失败或对端拒收。
4.3 反垃圾与病毒扫描的默认策略
Mailcow 默认启用 Rspamd 和 ClamAV。Rspamd 的规则比较激进,初期可能误判正常邮件。我一般会先观察一周,把误判的邮件在后台「 quarantine」里放出来,同时把发件人加白名单。
# 查看 Rspamd 的统计信息 docker compose exec rspamd-mailcow rspamc stat # 查看被隔离的邮件列表 docker compose exec rspamd-mailcow rspamc history逻辑说明:rspamc stat给出处理总量、垃圾比例、学习样本数;rspamc history列出最近处理记录。参数说明:如果垃圾比例异常高,检查是不是有账号密码泄露被用来发垃圾。ClamAV 吃内存,如果服务器内存紧张,可以在mailcow.conf里关掉它,但会失去病毒扫描能力。
5. 避坑与排查:自建邮件服务器最容易翻车的五件事
5.1 能收不能发,日志报 Connection timed out
现象:外部邮件能进来,自己发出去全部超时,Postfix 日志里一堆Connection timed out连向 25 端口。原因:云厂商封了 25 端口出站,这是最常见的新手翻车点。解决:提交工单申请解封,或者换一家允许邮件服务的厂商。申请时说明用途,一般一两个工作日能开。开之前可以用telnet gmail-smtp-in.l.google.com 25测试,通了才说明端口放行。
5.2 邮件进垃圾箱,SPF 或 DKIM 验证失败
现象:能发出去,但对方收到在垃圾箱,邮件头显示spf=softfail或dkim=fail。原因:DNS 记录没生效、填错,或者 PTR 和主机名不一致。解决:用dig TXT example.com +short查 SPF,用dig TXT dkim._domainkey.example.com +short查 DKIM,逐条比对后台生成的值。PTR 在 VPS 控制台确认,必须等于mail.example.com。三条全绿之后,信誉需要时间积累,不会立刻进收件箱。
5.3 容器反复重启,内存被 OOM Killer 干掉
现象:docker compose ps里某个容器状态是Restarting,日志显示Killed。原因:内存不足,ClamAV 和 Rspamd 是内存大户,2G 机器必崩。解决:升到 4G 以上,或者在mailcow.conf里禁用 ClamAV:把SKIP_CLAMD=y打开,然后docker compose down && docker compose up -d。禁用后病毒扫描没了,但反垃圾还在,小团队可以接受。
5.4 Web 后台打不开,Nginx 报 502
现象:浏览器访问https://mail.example.com显示 502 Bad Gateway。原因:Nginx 容器起来了但后端 PHP 或 MySQL 没就绪,或者证书生成失败。解决:先docker compose ps看php-fpm-mailcow和mysql-mailcow是否 running。如果 MySQL 在重启,看它日志是不是磁盘满了。如果都正常,检查mailcow.conf里的HTTP_PORT和HTTPS_PORT有没有被其他服务占用,ss -tlnp | grep 443能查。
5.5 客户端配置反复失败,IMAP 连不上
现象:Outlook 或手机自带邮件客户端配置时提示「服务器无响应」或「证书错误」。原因:端口填错或证书不被信任。解决:IMAP 用 993 端口 SSL,SMTP 用 465 端口 SSL,不要用 143 和 587 的 STARTTLS(虽然也支持,但客户端兼容性差)。证书问题如果是自签的,客户端会警告,建议用 Let's Encrypt 签正式证书。Mailcow 支持在后台申请,域名解析正确的前提下点一下就行。
6. 进阶:多域名别名、邮件归档与备份恢复的实操习惯
跑通基础收发之后,真正让 Mailcow 值回票价的是它的多域名和别名能力。我手上三个域名共用一个 Mailcow 实例,每个域名独立 DKIM,账号可以跨域名收信。后台「别名」功能可以做到sales@example.com转发到多个账号,也可以做 catch-all 把整个域名的未匹配邮件兜到一个邮箱。这里有个细节:catch-all 会招来大量垃圾,除非你确实需要,否则别开。
邮件归档我用的方案是 Mailcow 自带的「邮件归档」功能,在域名设置里开启后,所有进出邮件会额外存一份到归档邮箱,满足合规留痕需求。存储会翻倍,磁盘要留够。备份方面,Mailcow 官方提供了一个backup_and_restore.sh脚本,我每周跑一次全量备份,备份文件包含 MySQL 数据、邮件存储和配置。
# 创建全量备份,备份文件默认放在 /opt/mailcow-backup cd /opt/mailcow-dockerized ./helper-scripts/backup_and_restore.sh backup all # 恢复时先停服务,再执行恢复 docker compose down ./helper-scripts/backup_and_restore.sh restore逻辑说明:backup all备份数据库、vmail 邮件目录和配置文件;restore会提示你选择备份时间点。参数说明:备份目录可以在脚本里改,建议挂到独立磁盘或同步到异地。恢复前务必停容器,否则数据不一致。我踩过的坑是没停 MySQL 就恢复,结果数据库和邮件文件对不上,白折腾一晚上。
验证备份是否可用的方法很简单:找一台测试机,装好同版本 Mailcow,把备份文件拷过去跑恢复,看账号和邮件是否完整。别等真出事才验证,那时候后悔药没地方买。我的习惯是每月做一次恢复演练,花半小时,换来的是一年多的安稳。自建邮件服务器这件事,前期配置麻烦,但跑顺之后基本不用管,成本只有 VPS 费用。希望帮到你。
本文还有配套的精品资源,点击获取