简介Mailcow 是一套基于 Docker 容器化技术构建的开源邮件服务器解决方案面向需要自建企业邮箱、替代商业邮件服务的运维人员与开发者。它把 SMTP、IMAP、POP3、Webmail 等邮件服务与反垃圾、反病毒、DKIM、DMARC、SPF 等安全机制整合在一起通过 Docker Compose 即可完成安装、部署与升级降低了自建邮件系统的门槛。资源包共约 2000 个文件压缩后 10.98MB以 1515 个 PHP 源码为主体配合 78 个 Markdown 文档、61 个 JSON 配置、54 个 Shell 脚本、42 个 XML、36 个 JavaScript 及若干 YAML、Dockerfile、conf 等文件覆盖前端界面、后端逻辑、容器编排与部署脚本等模块。已有 202 人学习下载。借助完整源码与配置读者可深入理解邮件服务的组件协作方式参考其反垃圾、反病毒与域名认证策略的实现思路并据此搭建或二次开发自己的邮件系统。1. Mailcow 到底解决了谁的痛从一台裸机到可用的开源邮件服务器很多团队第一次认真考虑自建邮件服务往往不是因为预算而是因为业务系统需要一个能自己掌控的发信出口。订单通知、告警、日报、注册验证码这些邮件一旦走第三方通道量小的时候省事量一大就开始遇到限流、进垃圾箱、发件域被拉黑。这时候你会开始搜「开源邮件服务器」然后大概率撞上 Mailcow 这个名字。它是一套把 Postfix、Dovecot、Rspamd、ClamAV、SOGo、MySQL、Redis 等组件打包进 Docker 编排的开源邮件服务器解决方案带一个能点鼠标就完成域名、邮箱、别名、DKIM 配置的 Web 管理后台。适合谁适合有独立域名、能控制 25/465/587/993 端口、愿意花半天时间读文档的运维或后端工程师。它不适合完全不懂 DNS 的人也不适合指望装完就自动进收件箱的人。这篇笔记按「它是什么、怎么装、参数怎么调、坑在哪、怎么验证」的顺序讲清楚让你看完能判断值不值得投入以及照着做能不能跑通。2. 装之前先想清楚Mailcow 的组件分工与部署前置条件2.1 为什么是 Docker Compose 而不是单机编译Mailcow 最核心的工程决策是把一堆各自为政的邮件组件塞进同一个 Docker 网络里用docker-compose.yml统一编排。这个选择直接决定了它的部署体验你不需要分别编译 Postfix、配 Dovecot 的 LMTP socket、调 Rspamd 的 milter 顺序这些连接关系在镜像里已经接好了。常见做法是准备一台干净的 Linux 主机装好 Docker 和 Compose 插件然后拉取 Mailcow 的仓库改一个配置文件执行启动脚本。组件分工大致是这样Postfix 负责 SMTP 收发和投递Dovecot 负责 IMAP/POP3 和邮箱存储Rspamd 做垃圾邮件评分和 DKIM 签名ClamAV 扫病毒SOGo 提供 Webmail 和日历MySQL 存配置和元数据Redis 做缓存和限流Nginx 反代 Web 界面和 ACME 证书。理解这层分工后面排错时你才知道该看哪个容器的日志。前置条件里最容易被忽略的是端口和 DNS。25 端口出站很多云厂商默认封禁需要开工单解封443 和 80 要留给 ACME 签证书DNS 那边要提前规划好mail.你的域名的 A 记录、你的域名的 MX 记录以及 SPF、DKIM、DMARC 三条 TXT。这些不是装完再补的装之前没配好后面测试发信会一直失败。2.2 从零到能登录后台的最小步骤下面这套流程是我在 Debian 12 上反复用过的Ubuntu 22.04/24.04 同样适用。先确认主机名是 FQDN 格式比如mail.example.com而不是localhost否则 Postfix 的 myhostname 会出问题。# 1. 设置主机名必须和后面 mailcow.conf 里的 MAILCOW_HOSTNAME 一致 hostnamectl set-hostname mail.example.com # 2. 安装 Docker 和 Compose 插件用官方源别用系统自带的旧版本 apt update apt install -y ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod ar /etc/apt/keyrings/docker.asc echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release echo $VERSION_CODENAME) stable /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 3. 拉取 Mailcow 仓库 cd /opt git clone https://github.com/mailcow/mailcow-dockerized.git cd mailcow-dockerized # 4. 生成配置文件脚本会问你主机名和时区 ./generate_config.shgenerate_config.sh会生成mailcow.conf里面几个参数必须核对MAILCOW_HOSTNAME填你的 FQDNTZ填Asia/ShanghaiHTTP_PORT和HTTPS_PORT默认 80/443如果这两个端口被占用要改。SKIP_LETS_ENCRYPT如果你暂时没有公网域名可以先设y但生产环境不建议跳过。# 5. 拉镜像并启动第一次会下载几个 G耐心等 docker compose pull docker compose up -d # 6. 看容器状态全部 Up 或 healthy 才算正常 docker compose ps启动完成后访问https://mail.example.com默认管理员账号是admin密码是moohoo。第一件事就是改密码第二件事是进「系统 → 配置 → 邮箱设置」把默认的域名加进去。加域名时 Mailcow 会自动生成 DKIM 密钥你要把公钥复制到 DNS 的 TXT 记录里主机名通常是dkim._domainkey。提示docker compose up -d之后如果某个容器反复重启先docker compose logs 服务名看日志八成是端口冲突或 DNS 解析失败不要急着重装。3. 让邮件真正能发出去DNS 三件套与 DKIM 配置3.1 SPF、DKIM、DMARC 各自管什么装完能登录后台只是第一步邮件能不能进对方收件箱取决于 DNS 里这三条记录。SPF 告诉收件方哪些 IP 有权用你的域名发信格式是一条 TXT内容类似vspf1 mx a:mail.example.com -all。-all表示除了列出的来源其他一律视为伪造比~all严格。DKIM 是给每封邮件加数字签名收件方用你 DNS 里的公钥验证确认邮件没被篡改。DMARC 是策略层告诉收件方当 SPF 和 DKIM 都失败时怎么处理pquarantine是扔垃圾箱preject是直接拒收。这三条缺一不可。只配 SPF 不配 DKIM很多大厂邮箱会降权只配 DKIM 不配 DMARC你收不到对方域名的聚合报告出问题不知道从哪查。Mailcow 后台在「系统 → 配置 → 域名」里能直接看到 DKIM 公钥复制时注意不要带多余空格和换行。3.2 在 Mailcow 后台完成域名与邮箱的落地配置登录后台后按这个顺序操作先「邮箱 → 域名 → 添加域名」填example.com勾选「生成 DKIM 密钥」。保存后点进域名详情找到 DKIM 记录把dkim._domainkey.example.com的 TXT 值复制出来。然后去 DNS 服务商添加记录TTL 设 3600 即可。接着加邮箱账号「邮箱 → 邮箱 → 添加邮箱」填noreplyexample.com设密码。如果业务系统要发信建议单独建一个发信账号不要用管理员账号。别名和转发在「邮箱 → 别名」里配比如把postmasterexample.com转发到你的真实邮箱这是 RFC 要求的。# 验证 DNS 记录是否生效三条都要查 dig short TXT example.com | grep spf dig short TXT dkim._domainkey.example.com dig short TXT _dmarc.example.com # 用 swaks 测试发信需要先装 swaks apt install -y swaks swaks --to your-testgmail.com \ --from noreplyexample.com \ --server mail.example.com:587 \ --auth LOGIN \ --auth-user noreplyexample.com \ --tlsswaks会交互式问密码发完去收件箱看邮件头重点看Authentication-Results里 SPF、DKIM、DMARC 是不是都 pass。如果 DKIM 是 fail八成是 DNS 记录没生效或者公钥复制错了如果 SPF 是 softfail检查-all前面的 IP 列表有没有漏掉你的出口 IP。注意DNS 记录生效有延迟改完别立刻测等十分钟到半小时。用dig查到的结果和权威 DNS 一致才算生效。4. 参数调优与反垃圾Rspamd 阈值和限流怎么设4.1 Rspamd 评分阈值改哪里、改成多少Mailcow 默认的 Rspamd 配置对垃圾邮件判定偏保守正常业务邮件偶尔会被打高分。评分阈值在data/conf/rspamd/local.d/actions.conf里默认大概是reject 15、add_header 6、greylist 4。如果你发现正常通知邮件进了垃圾箱先把add_header调到 8观察一周再决定要不要动reject。改完不用重启整个 Mailcow重启 Rspamd 容器就行# 编辑阈值配置 vim data/conf/rspamd/local.d/actions.conf # 只重启 rspamd不影响其他服务 docker compose restart rspamd # 看 rspamd 日志确认配置加载成功 docker compose logs --tail50 rspamd除了阈值data/conf/rspamd/local.d/下还能加自定义规则。比如你的业务邮件里经常出现某个被误判的关键词可以写一条multimap规则给它减分。但我不建议一上来就写规则先把阈值调对再看日志里哪些规则命中最多针对性处理。4.2 发信限流与队列观察Mailcow 默认对每个邮箱有发信频率限制防止账号被盗后群发垃圾邮件。这个限制在「系统 → 配置 → 邮箱设置」里的Ratelimit部分可以按域名或邮箱单独设。业务系统发信量大时默认值可能不够用但也不要直接关掉限流建议按实际峰值设一个合理上限。队列观察用postqueue或者 Mailcow 后台的「系统 → 队列」页面。如果队列里堆积大量deferred状态的邮件点进去看Status字段常见原因是对方服务器拒收、DNS 解析失败、或者你的 IP 被列入黑名单。# 查看邮件队列 docker compose exec postfix-mailcow postqueue -p # 查看某封邮件的详细投递日志 docker compose exec postfix-mailcow postcat -q QUEUE_ID # 强制重试队列 docker compose exec postfix-mailcow postqueue -fpostqueue -p输出里的(Host or domain name not found)说明 DNS 有问题(Connection refused)说明对方 25 端口不通(450 4.7.1)通常是对方限流。这些信息比后台页面更原始排错时优先看。5. 避坑与排查Mailcow 部署中最容易翻车的五件事5.1 容器全起来了但收不到外部邮件现象是内部邮箱互发正常外部发进来一直超时。原因通常是 25 端口没有从公网可达或者云厂商安全组没放行。解决方法是先用telnet mail.example.com 25从外部网络测如果连不上检查安全组和主机防火墙如果连得上但没响应看 Postfix 日志里有没有connect from记录。5.2 DKIM 签名失败导致进垃圾箱现象是邮件头里dkimfail。原因有两个一是 DNS 记录没生效或公钥复制错二是 Mailcow 里域名配置的 DKIM selector 和 DNS 里的主机名对不上。解决方法是dig查 DKIM 记录和后台显示的公钥逐字符比对注意 TXT 记录值要用引号包起来长公钥要分段拼接。5.3 升级后 Web 后台打不开现象是docker compose pull之后up -dNginx 容器起不来。原因是新版本可能改了配置格式或依赖旧的数据卷不兼容。解决方法是升级前先备份mailcow.conf和data/目录升级后看docker compose logs nginx-mailcow如果是配置语法错误对照官方 release note 改配置。5.4 邮箱密码正确但 IMAP 登录失败现象是 Webmail 能登但客户端配 IMAP 一直认证失败。原因是 Mailcow 默认要求 TLS且部分客户端不支持现代加密套件。解决方法是确认客户端用 993 端口加 SSL/TLS用户名填完整邮箱地址不要只填前面的部分。如果还不行看 Dovecot 日志里的auth failed具体原因。5.5 磁盘写满导致服务雪崩现象是某天突然所有邮件都发不出去后台也卡。原因是邮件存储和日志把磁盘占满了。解决方法是定期清理data/下的日志和旧邮件或者给/var/lib/docker单独挂一块盘。监控磁盘用df -h低于 20% 就要处理。提示这五条里端口和 DNS 问题占了我遇到故障的七成。装之前把这两样确认好能省掉大量排查时间。6. 进阶技巧用 API 把 Mailcow 接进你的业务系统Mailcow 提供了一套 REST API可以用来自动创建邮箱、查收件箱、发信。对业务系统来说最实用的场景是注册时自动建邮箱或者告警系统通过 API 发信。API 密钥在后台「系统 → 配置 → 访问 → API」里生成调用时放在X-API-Key请求头里。import requests API_KEY 你的API密钥 BASE https://mail.example.com/api/v1 headers { X-API-Key: API_KEY, Content-Type: application/json } # 创建一个新邮箱 def create_mailbox(local_part, domain, password): payload { local_part: local_part, domain: domain, name: local_part, password: password, password2: password, quota: 1024, # 单位 MB active: 1 } r requests.post(f{BASE}/add/mailbox, jsonpayload, headersheaders) return r.json() # 发送一封邮件 def send_mail(from_addr, to_addr, subject, body): payload { sender: from_addr, rcpt: to_addr, subject: subject, body: body } r requests.post(f{BASE}/send/mail, jsonpayload, headersheaders) return r.json() if __name__ __main__: print(create_mailbox(testuser, example.com, Str0ngPass!)) print(send_mail(noreplyexample.com, youexample.com, 测试, 这是一封测试邮件))quota参数单位是 MB设 0 表示不限。send/mail接口走的是 Mailcow 内部的发信通道会正常经过 Rspamd 评分和 DKIM 签名所以不用担心绕过反垃圾。API 返回的是 JSON创建失败时msg字段会给出具体原因比如mailbox_exists或invalid_domain。验证 API 是否正常除了看返回码还可以在后台「系统 → 日志 → API」里看到每次调用的记录。如果返回 401检查 API 密钥有没有复制错如果返回 403检查密钥对应的权限范围。我自己的习惯是任何对 Mailcow 的配置改动先在测试环境跑一遍 API 调用确认返回符合预期再上生产。邮件这东西不像 Web 服务发出去就收不回来没有后悔药。另外API 密钥要当密码一样管别写进前端代码或者公开仓库。希望帮到你。本文还有配套的精品资源点击获取