dirtsimple/poste.ioposte.io 是一个基于Docker的优秀邮件服务器实现,本镜像对其进行了增强,使其功能更强大。
具体而言,本镜像支持:
/data卷安装和使用自定义Roundcube插件DES_KEY(详见DES_KEY变量),以支持存储加密数据的插件使用原生poste镜像的主机模式网络(poste.io推荐配置)时,一个主要挑战是它与同一机器上的其他邮件服务器兼容性差(例如难以同时运行开发和生产实例,或为多个客户端提供服务)。
具体而言,在主机模式网络中,poste.io会将其外部服务绑定到机器的所有IP地址,同时将多个内部服务绑定到本地端口(6379、-、***、和),这可能与邮件服务器以外的服务或其他poste.io实例冲突。
因此,poste.io不仅与其他邮件服务器(包括自身其他实例)不兼容,还与服务器上的其他服务冲突(这种设置下几乎失去了Docker容器的隔离优势)。最后,它还会使用任意IP发送邮件,无法选择特定发送IP。
本镜像通过添加两个环境变量和一个配置文件解决了这些问题,不仅能控制poste监听的IP,还能控制邮件发送的IP(可选按域名)。此外,它修补了poste.io的默认配置,使所有内部服务使用容器内的Unix域套接字,而非占用主机的本地端口。
添加的第一个变量是LISTEN_ON,可设置为特定IP列表、host(仅监听容器主机名绑定的地址)或*(poste默认行为,监听所有可用接口)。
第二个变量是SEND_ON,同样可设置为IP列表、host或*(未设置时默认使用LISTEN_ON的值)。默认情况下,邮件将从列表中的第一个IP发送(若为*则由操作系统选择)。若只有一个发送IP,所有邮件均使用该IP;否则将通过配置文件按发件域名从列表中选择IP。
使用本镜像时,只需将配置中的analogic/poste.io替换为dirtsimple/poste.io。例如,以下docker-compose.yml配置(将mail.example.com替换为实际主机名):
yamlversion: "2.3" services: poste: image: dirtsimple/poste.io restart: always network_mode: host # <-- poste必须使用主机模式网络 # 所有服务使用`mail.example.com`,同时作为默认HELO主机名 hostname: mail.example.com volumes: - ./data:/data - /etc/localtime:/etc/localtime:ro # ==== 以下为可选设置:默认无需任何环境变量 ==== environment: # 空格分隔的监听IP列表。若设为"host"(未设置时默认值), # 容器将监听容器主机名在DNS或/etc/hosts中配置的所有IP(IPv4和IPv6)。 # 设为"*"则监听所有可用地址(原生poste.io默认行为)。 - "LISTEN_ON=1.2.3.4 5.6.7.8 90a:11:12::13" # 空格分隔的邮件发送IP列表;列表中的第一个IP为默认值。 # 与LISTEN_ON类似,可设为"*"(任意可用地址)或"host"(容器主机名关联的所有IP)。 # 若列表仅包含一个地址,则所有邮件使用该IP发送。否则,将读取data/outbound-hosts.yml # 文件按域名确定发送IP,并验证是否在列表中。未设置时默认使用LISTEN_ON的值。 - "SEND_ON=9.10.11.12" # 也可使用其他标准poste.io环境变量,如HTTPS_PORT等。
注意以下事项:
mail.example.com),且至少有一个IP在公共DNS中注册LISTEN_ON中列出的IP)必须是主机服务器的公共IPnetwork_mode: host),其他网络模式下本镜像行为与原生analogic/poste.io基本一致,存在相同限制(此时LISTEN_ON、SEND_ON或outbound-hosts.yml中的IP设置无效)LISTEN_ON中第一个IP或容器内hostname -i返回的IP。如需覆盖此行为,可设置SEND_ON为特定IP,或创建管理发送IP中描述的/data/outbound-hosts.yml文件LISTEN_ON=*模式。这会禁用某些主机特定的垃圾邮件检查(如asn、fcrdns、karma/history等)。仅用于发送邮件的IP不会触发此行为,除非显式添加到中继网络列表。注意,示例中没有端口映射,因为容器使用主机模式网络,可直接访问服务器所有网络接口。因此必须明确定义容器使用的IP(通过主机名的DNS地址或LISTEN_ON变量设置),避免容器占用服务器所有IP(如需此行为,可设LISTEN_ON=*)。
简单场景下,本镜像只需一个主机名和IP:
复杂场景下可能需要多个IP或主机名,例如为每个域名提供mail.somedomain.com网站/MX,或分离不同域名的发送信誉,同时使用单个容器。这些场景可行,但需注意:容器的TLS证书(用于Web界面和SMTP)会列出所有托管主机名,无法完全隐藏域名共享同一容器的事实(如需完全隔离,需创建独立容器)。
若仅需为用户提供域名特定主机名或分离发送信誉,单个共享容器即可满足需求。
如需为每个域名提供mail.mydomain.com供用户配置邮件客户端、登录Web界面或作为MX记录,无需多个IP,只需多个主机名:
但仍需选择一个主域名用于启动容器和访问管理界面,该主域名将作为TLS证书的主名称,自定义域名在通过公共DNS解析且容器监听对应IP后,将作为备用名称添加到证书中。
如需为不同域名提供独立IP和主机名,步骤类似,但每个自定义主机名需通过A或AAAA记录指向特定IP,而非CNAME指向主域名。如需这些IP用于外发邮件,还需配置outbound-hosts.yml文件(见下节),并按需添加到SEND_ON变量。
当然,仍需配置容器监听所有这些IP,可通过LISTEN_ON显式指定,或为主域名添加A/AAAA记录。若服务器专用于单个poste实例,可设LISTEN_ON=*监听所有IP。
(注意:由于poste.io仅支持单TLS证书,连接容器的客户端仍能看到所有托管主机名,若不可接受,则需创建独立实例,每个实例服务独立IP。)
某些环境下可能需要为不同发件域名使用不同发送IP。为此,可在/data卷中添加outbound-hosts.yml文件,格式如下:
yaml# 未配置域名使用的默认信息 default: helo: poste.mygenericdomain.com ip: 1.2.3.4 exampledomain.com: helo: mx.exampledomain.com ip: 5.6.7.8
上述配置中,来自exampledomain.com的邮件将使用HELO mx.exampledomain.com和发送IP 5.6.7.8,其他域名使用默认配置(假设5.6.7.8是容器监听的IP之一)。
注意,此文件信息不会验证DNS或安全性(仅基本检查IP是否在SEND_ON范围内)。需确保所有helo主机名在DNS中与ip匹配,且列出的IP均为服务器网络接口的有效IP。
为确保最佳送达率,还应:
helo/ip组合通过SPF验证ip的反向DNS结果合理(最好与helo一致)helo地址添加到poste管理界面"邮件服务器设置"的TLS证书"备用名称"中,且对应ip是容器监听的地址配置变更时需更新所有相关信息!若自行控制所有相关域名的DNS,可通过域名列表和DNS自动生成此文件(如查询MX记录及对应地址)。(不应信任非控制域名的DNS,避免客户端自行选择发送IP。)
本镜像支持监听IPv6地址,理论上也可通过IPv6发送邮件。但由于支持IPv6接收的邮件服务器较少,除非确定仅与IPv6邮件服务器通信,否则不建议使用IPv6发送邮件。(还需测试网络环境中IPv6发送是否正常,以及向仅IPv4服务器发送IPv6邮件的情况。)
启动时,本镜像会自动安装、激活并尝试运行/data/roundcube-plugins子目录中找到的所有Roundcube插件的SQL初始化。仅支持无依赖(除Roundcube已安装组件外)的插件。(插件应设置为世界可读权限,但不可由www-data用户/组拥有或写入,避免文件写入漏洞导致远程执行。)
如需重新运行插件的SQL安装,可从/data/roundcube/installed-plugins文件中移除插件名称,然后重启容器。卸载插件需停止容器,从/data/roundcube-plugins目录移除插件,再启动容器(插件的SQL变更将保留)。
此功能仍处于实验阶段(仅测试过一个插件),建议先在开发环境测试,再用于生产。
部分插件(如ident_switch)可能需要在Roundcube数据库中存储加密数据。默认情况下,poste每次启动生成新加密密钥,导致加密数据无法解密。为解决此问题,可设置DES_KEY环境变量,值为48个随机十六进制字符。该字符串将在重启后保持一致,确保之前存储的加密数据可解密。可使用openssl rand -hex 24生成(24随机字节=48十六进制字符)。字符串必须恰好48个十六进制字符,否则容器的Webmail服务将无法正常运行。
不确定,但可通过克隆仓库、修改Dockerfile中的FROM并尝试构建验证。由于专业版与免费版的主要区别是管理界面代码,若缺失代码包含对localhost或127.0.0.1的硬编码/隐式引用,管理功能可能因未修补为使用Unix域套接字(或容器主机名)而失效。
若失效且能确定需修补的内容(可能是/opt/admin/src/ProBundle/中的PHP代码),欢迎反馈。(若正常工作,也欢迎告知!)
除latest和unstable外,Docker Hub上的镜像标签格式为"上游版本-本镜像修订版",例如2.2.2-0.3.1表示上游poste 2.2.2版本的0.3.1修订版(如需固定特定版本)。也可使用上游版本标签(如2.2.2)获取该上游版本的最新补丁,或latest获取最新稳定版。unstable标签始终对应GitHub的master分支。
manifest unknown 错误
TLS 证书验证失败
DNS 解析超时
410 错误:版本过低
402 错误:流量耗尽
身份认证失败错误
429 限流错误
凭证保存错误
来自真实用户的反馈,见证轩辕镜像的优质服务