- 后端
- 通信
- 云原生
【免费下载链接】docker-mailserver
Production-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.
本文围绕 docker-mailserver(DMS)的文件型账户供给器(Provisioner: FILE)展开,系统讲解如何通过容器内的setupCLI 与 Config Volume 中的三个核心配置文件(postfix-accounts.cf、postfix-virtual.cf、dovecot-quotas.cf)管理邮箱账户、别名与配额,并深入解析其底层实现(脚本、Postfix/Dovecot 配置生成与测试用例)。读完本文,你将掌握 DMS 账户体系的完整操作链路、配置文件格式与已知边界,能够独立完成从建号、设别名、配配额到排障的整套实战任务。
1. 总览:DMS 的两种账户供给方式与 File 模式定位
DMS 通过环境变量ACCOUNT_PROVISIONER选择账户来源:
FILE(默认):账户、别名、配额存储在 Config Volume 的纯文本配置文件中,由容器启动脚本转换成 Postfix 与 Dovecot 可用的内部配置;LDAP:账户信息来自 LDAP 目录(参见 LDAP Provisioner 文档)。
本文只讨论 File 模式。在mailserver.env中ACCOUNT_PROVISIONER默认留空,由 target/scripts/helpers/accounts.sh 中的_create_accounts()判断:仅当该值等于FILE时才走文件型账户创建流程(见 accounts.sh),因此“不设置”即等价于 File 模式。
File 模式下,所有配置都归属于Config Volume(默认映射docker-data/dms/config/→ 容器内/tmp/docker-mailserver/),具体挂载方式可参考 Optional Config 文档的 Volumes 章节。
2. 管理方式:setupCLI
官方推荐通过容器内的setupCLI 管理账户及其关联配置文件。它是一系列 Bash 脚本的入口,在 target/bin/setup 中定义了全部子命令的分发逻辑:
setup [ OPTIONS... ] COMMAND [ help | ARGUMENTS... ] COMMAND := { email | alias | quota | dovecot-master | config | relay | debug } SUBCOMMANDsetup email add/update/del/list/restrictsetup alias add/del/listsetup quota set/delsetup dovecot-master add/update/del/listsetup config dkimsetup relay add-auth/add-domain/exclude-domainsetup fail2ban、setup debug ...
完整命令列表可用setup help查看;每个子命令都支持help参数获取用法说明(例如setup email add help)。
2.1 进入容器执行
文档示例先启动一个基础实例,再进入容器执行setup:
# 启动一个基础 DMS 实例,然后进入容器使用 setup CLI: docker run --rm -itd --name dms --hostname mail.example.com mailserver/docker-mailserver docker exec -it dms bash # 创建账户: setup email add hello@example.com your-password-here # 创建别名: setup alias add your-alias-here@example.com hello@example.com # 将邮箱容量限制为 10 MiB: setup quota set hello@example.com 10M2.2 宿主机侧的setup.sh包装器
仓库根目录提供了 setup.sh,它自动探测 Docker/Podman(见 setup.sh),找到运行中的 DMS 容器后,等价于执行docker exec -it <container> setup <args>(见 setup.sh);若没有运行中的容器,则会基于镜像临时起一个新容器执行命令。也就是说,上面的命令在宿主机上同样可以写成:
./setup.sh email add hello@example.com your-password-here ./setup.sh alias add your-alias-here@example.com hello@example.com ./setup.sh quota set hello@example.com 10M2.3 安全密码输入
命令行不带密码时,脚本会交互式提示输入(见 postfix-accounts.sh 的_password_request_if_missing():两次静默输入并做一致性校验),从而避免密码进入 shell 历史记录:
$ setup email add hello@example.com Enter Password: Confirm Password:2.4 删除账户的级联行为
setup email del会同时删除该账户关联的别名与配额。从源码 delmailuser 可以看到执行顺序:
- 校验账户存在;
- 可选删除磁盘上的邮箱目录(
-y确认删除 /-n明确保留,见 delmailuser 的交互提示与-y强制); - 删除该账户名下的全部虚拟别名(
_manage_virtual_aliases_delete '_'); - 删除其配额条目(
_manage_dovecot_quota_delete); - 最后才从
postfix-accounts.cf删除账户。
测试用例同样验证了这一级联行为与“缺少配置文件时不报错”的容错逻辑(见 account_management.bats)。
3. 配置参考:账户(Accounts)
3.1 文件位置与格式
配置文件:docker-data/dms/config/postfix-accounts.cf
格式为逐行文本,两列字段以|分隔:
- User(用户):账户邮箱主地址;
- Password(密码):账户密码的 SHA512-CRYPT 哈希(下方示例中明文密码为
secret)。
示例(假设 DMS 为example.com域管理邮件):
hello@example.com|{SHA512-CRYPT}$6$W4rxRQwI6HNMt9n3$riCi5/OqUxnU8eZsOlZwoCnrNgu1gBGPkJc.ER.LhJCu7sOg9i1kBrRIistlBIp938GdBgMlYuoXYUU5A4Qiv0不用setup email add生成密码哈希:兼容的哈希可由 Dovecot 工具直接生成:
doveadm pw -s SHA512-CRYPT -u hello@example.com -p secret这实际上就是setup email add在底层所做的操作:_manage_accounts()调用doveadm pw -s SHA512-CRYPT -u "${MAIL_ACCOUNT}" -p "${PASSWD}"生成哈希后写入文件(见 postfix-accounts.sh)。
3.2 底层消费:Postfix vmailbox 与 Dovecot UserDB
setup email add只把条目写入postfix-accounts.cf,真正的“建号”发生在变更检测(changedetector)触发后。由 accounts.sh 的_create_accounts()完成:
- 逐行以
|为分隔符解析(while IFS=$'|' read -r LOGIN PASS USER_ATTRIBUTES),忽略注释与空行; - 为每个账户生成
/etc/postfix/vmailbox行LOGIN DOMAIN/USER/(Postfix 的virtual_mailbox_maps); - 为每个账户生成
/etc/dovecot/userdb行,格式为user:password:uid:gid:(gecos):home:(shell):extra_fields,其中 uid/gid 使用DMS_VMAIL_UID/DMS_VMAIL_GID,home 为/var/mail/<domain>/<user>/home; - 创建邮箱目录
/var/mail/<domain>/<user>/home,若存在docker-data/dms/config/<login>.dovecot.sieve则复制为用户的.dovecot.sieve筛件; - 账户的本地部分(local-part)与域部分(domain-part)会用于填充 Postfix 的 vhost 域表(见 postfix.sh)。
容器启动脚本 dovecot.sh 会在检测到postfix-accounts.cf后启用auth-passwdfile.inc(passdb),实现 IMAP/POP3 的密码文件认证。
3.3 重要约定
- 大小写归一化:创建账户时会自动将邮箱地址规范为小写——DMS 不支持同一地址的多种大小写变体。源码在 postfix-accounts.sh 的
_arg_check_mail_account()中实现:检测到大写字母时发出警告并转小写。测试用例专门验证了USeRx@domain.tld被归一化为userx@domain.tld(见 account_management.bats)。另外,登录认证对大小写不敏感(测试中USER1@...大写登录可成功,见同文件 L62-L66)。 - 登录用户名即邮箱地址:所选邮箱地址同时是邮件客户端认证时的登录用户名。
- 邮箱目录结构:账户邮箱位于
/var/mail/<domain>/<local-part>,测试中通过[[ -d /var/mail/localhost.localdomain/user1 ]]验证(见 account_management.bats)。
3.4 Dovecot "extra fields" 扩展列
在postfix-accounts.cf中追加第三列可自定义“额外字段”(extra fields),用于在转换为 Dovecot UserDB 条目时携带额外属性(如自定义 quota 属性userdb_quota_storage_size、userdb_quota_storage_grace,参见 accounts.sh 的_add_attribute_dovecot_quota())。
注意:DMS 本身并不理解这些自定义内容,只是原样透传。若这些字段改变了脚本所依赖的约定(如 mailbox 路径或类型),可能导致预期之外的 bug。
4. 配置参考:别名(Aliases)
4.1 文件位置与格式
配置文件:docker-data/dms/config/postfix-virtual.cf
格式为逐行“键值对”(别名→目标地址),以空白字符分隔。
示例(假设 DMS 为example.com域管理邮件):
# 别名投递到已有账户: alias1@example.com hello@example.com # 别名转发到外部邮箱: alias2@example.com external-account@gmail.com从源码看,别名键(第一列)可以是user@domain、只有本地部分的user,以及通配的@domain(见 postfix-virtual.sh)。
4.2 底层消费
容器启动时,aliases.sh 的_handle_postfix_virtual_config()将postfix-virtual.cf直接复制为/etc/postfix/virtual;Postfix 的virtual_alias_maps默认配置为texthash:/etc/postfix/virtual(见 target/postfix/main.cf)。
值得注意的联动逻辑:当ENABLE_QUOTAS=1时,accounts.sh 的_create_dovecot_alias_dummy_accounts()会为“指向本地真实账户”的别名在 Dovecot userdb 中生成共享同一存储的“dummy 条目”,供quota-status策略服务在入站投递时做配额检查,以降低退信(backscatter)风险。该行为由测试显式验证(见 account_management.bats)。
4.3 已知问题与限制
setupCLI 禁止别名与账户共用同一地址:目前无法用setup email add或setup alias add添加一个已作为别名或账户存在的地址。该限制源于历史 bug(账户/别名重叠曾引发投递问题),但仍存在合法的重叠使用场景。作为临时方案,你可以手动编辑postfix-virtual.cf绕过此限制——除setupCLI 外,运行时没有针对这一限制的其他检查(对应校验逻辑在 postfix-virtual.sh 与 postfix-accounts.sh 中)。
通配 catch-all(@example.com):
- 这种无本地部分的别名受支持,但必须牢记:Postfix 中别名的优先级高于账户的真实地址;
- 因此通配会先被匹配,把整个域的信件都导向别名目标;对域内每个非别名地址,你需要额外为其配置一个别名来兜底;
- Postfix 读取别名配置时会选择与收件人地址最匹配的条目,因此更具体的别名必须声明在通配别名之前。
别名链与多收件人:虽然技术上可以向多个收件人投递,但 DMS 并不官方支持:
- 某些功能集成(如配额 dummy 账户、
setup alias add的增删逻辑)假定每个别名只有一个目标,多目标可能出问题; - 嵌套别名(目标本身又是别名)同样不受支持,例如与
setup alias add存在兼容性问题。Postfix 本身虽可递归解析别名,但项目脚本/功能对此支持有限(见 postfix-virtual.sh 的警告注释)。
4.4 配置 RegEx 别名
配置文件:docker-data/dms/config/postfix-regexp.cf
该文件与postfix-virtual.cf类似,区别在于别名值改为正则模式匹配。此功能没有setupCLI 支持,只能手动改配置文件。
示例:将test用户的所有邮件投递到qa@example.com:
# 记得转义正则特殊字符,如 `.` => `\.`, # 否则你的别名模式可能比预期更宽松: /^test[0-9][0-9]*@example\.com/ qa@example.com4.5 技术细节:优先级与加载机制
postfix-virtual.cf拥有更高优先级,postfix-regexp.cf仅在虚拟别名表中未找到匹配时才被检查;- 两者都会被复制到容器内
/etc/postfix/(分别是/etc/postfix/virtual与/etc/postfix/regexp),并在main.cf的virtual_alias_maps中配置。因为postfix-virtual.cf在该设置中声明在前(见 target/postfix/main.cf),它会先被处理,postfix-regexp.cf作为后备(_handle_postfix_regexp_config()通过_add_to_or_update_postfix_main追加pcre:/etc/postfix/regexp,见 aliases.sh)。
5. 配置参考:配额(Quotas)
5.1 文件位置与格式
配置文件:docker-data/dms/config/dovecot-quotas.cf
格式为逐行文本,两列字段以:分隔:
- Dovecot UserDB 账户:DMS 账户,应能在
postfix-accounts.cf中找到对应条目; - 配额上限:以字节表示(支持二进制单位后缀:
M=>MiB,G=>GiB)。
示例:为账户hello@example.com设置不超过 5 GiB 的存储上限:
hello@example.com:5G5.2 底层消费
启动时_add_attribute_dovecot_quota()从该文件读取配额,按:切分后转换为 Dovecot userdb 的userdb_quota_storage_size额外字段,并根据单位后缀额外追加userdb_quota_storage_grace(取数值的 1/10 作为宽限空间,见 accounts.sh)。写操作由 dovecot-quotas.sh 的_manage_dovecot_quota()完成(setup quota set对应update,setup quota del对应delete)。
默认ENABLE_QUOTAS=1(见 mailserver.env)。测试验证了setup email list在配额启用/禁用时输出格式的差异(见 account_management.bats)。
6. 其他相关能力
- Dovecot Master 账户:
setup dovecot-master add/update/del/list管理docker-data/dms/config/dovecot-masters.cf,复用与账户相同的管理逻辑(见 postfix-accounts.sh),用于支持管理员的“主账户”登录场景。完整机制可参考 Master Accounts 文档。 - 账户列表查询:
setup email list(底层为 listmailuser)列出全部账户。 - 变更检测:所有
setup写操作完成后,由容器的 changedetector 服务感知文件变化并重新生成 Postfix/Dovecot 内部配置(见 addmailuser 的注释),因此账户不会“即时”生效,存在短暂延迟,属正常现象。
7. 从setupCLI 到配置文件的完整调用链
将前述内容串联起来,一次setup email add的完整链路如下:
- 宿主机
./setup.sh解析出容器/镜像后,执行docker exec ... setup email add ...(setup.sh); - 容器内
setup脚本将email add分发给addmailuser(target/bin/setup); addmailuser调用_manage_accounts_create(addmailuser);_manage_accounts完成地址校验、大小写归一化、密码哈希生成,并写入/tmp/docker-mailserver/postfix-accounts.cf(postfix-accounts.sh);- changedetector 触发后,
_create_accounts()根据配置文件重建/etc/postfix/vmailbox与/etc/dovecot/userdb,并创建邮箱目录(accounts.sh)。
对应地,setup alias add→addalias→_manage_virtual_aliases_update写入postfix-virtual.cf;setup quota set→setquota→_manage_dovecot_quota_update写入dovecot-quotas.cf。所有数据库文件的操作统一收敛在 database/manage 目录下,结构清晰、便于维护。
8. 实操核对清单
| 需求 | 推荐命令 / 文件 | 底层消费方 |
|---|---|---|
| 添加账户 | setup email add <addr> [<pass>] | postfix-accounts.cf→ vmailbox / Dovecot userdb |
| 删除账户(含别名、配额) | setup email del [-y|-n] <addr> | 级联清理三个配置文件 |
| 修改密码 | setup email update <addr> [<pass>] | 重写postfix-accounts.cf哈希 |
| 添加别名 | setup alias add <alias> <target> | postfix-virtual.cf→/etc/postfix/virtual |
| RegEx 别名 | 手动编辑postfix-regexp.cf | /etc/postfix/regexp(virtual_alias_maps后备) |
| 设置配额 | setup quota set <addr> <size> | dovecot-quotas.cf→ userdb 额外字段 |
| 查看账户 | setup email list | 读取postfix-accounts.cf |
9. 进一步阅读
- 配置文件所属的 Config Volume 说明
- 账户管理的总览文档:Account Management 概述
- LDAP 供给方式对照阅读:Provisioner - LDAP
- 用
user-patches.sh自定义容器内配置:User Patches - 相关源码与测试:target/scripts/helpers/accounts.sh、target/scripts/helpers/database/manage/postfix-accounts.sh、target/scripts/helpers/database/manage/postfix-virtual.sh、target/scripts/helpers/database/manage/dovecot-quotas.sh、test/tests/parallel/set3/mta/account_management.bats
- 后端
- 通信
- 云原生
【免费下载链接】docker-mailserver
Production-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.
相关推荐
docker-mailserver 实践:基于 LDAP 认证的 Forward-Only 转发型邮件服务器完整配置指南
docker mailserver 实践:基于 LDAP 认证的 Forward Only 转发型邮件服务器完整配置指南 本指南以 docker mailser
后端通信云原生aws-cli配置文件管理:多环境多账户的配置最佳实践
aws cli配置文件管理:多环境多账户的配置最佳实践 概述 AWS CLI(Command Line Interface)是管理AWS资源的强大工具,但在多环
开发工具云原生运维Tiny File Manager 终极多用户权限管理:10个实战配置技巧与目录隔离完整指南
Tiny File Manager 终极多用户权限管理:10个实战配置技巧与目录隔离完整指南 Tiny File Manager 是一款功能强大的单文件PHP文
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考