Mercury需同时启用MercuryS(收信)和MercuryC(转发)模块才能使PHP mail()正常工作;仅修改IP绑定或端口无效,必须勾选MercuryC SMTP relaying client并确保sendmail_path配置正确。

Mercury 默认监听 25 端口,但 Windows 下该端口常被占用或受防火墙/ISP 封锁,直接改端口不解决问题,必须同步调整 Mercury 模块启用状态、客户端配置和 PHP 的 sendmail_path 或 SMTP 设置。
为什么改了 Mercury 的“IP interface to use”还是连不上 25 端口
Mercury 不是只靠“绑定 IP”就开放端口的。它默认只启用 MercuryS SMTP Server(接收邮件),但不自动启用 MercuryC SMTP Client(向外转发)——而本地 PHP 的 mail() 函数依赖后者完成中继。即使你把 IP interface to use 设为 127.0.0.1,若 MercuryC SMTP Client 未勾选,mail() 仍会超时失败,错误日志里通常只有 Failed to connect to mailserver 这类模糊提示。
- 必须进入
Configuration / Protocol modules,勾选MercuryC SMTP relaying client,同时取消MercuryE SMTP end-to-end delivery client - 重启 Mercury 后检查任务管理器:应看到
mercury.exe和mercuryc.exe两个进程在运行 - 用命令行验证端口是否真在监听:
netstat -ano | findstr :25,确认 PID 对应的是mercury.exe而非其他程序(如 Skype、Windows Mail)
想换端口(比如 587)能不能直接改 MercuryS SMTP Server 的 port
不能。MercuryS SMTP Server 的端口设置仅控制“收信端口”,而 PHP 的 mail() 函数走的是 sendmail_path 或 SMTP 配置,它不读 MercuryS 的端口,而是硬编码连接 localhost:25。你改 MercuryS 的端口,PHP 仍会去连 25,结果就是 Connection refused。
XAMPP 8.0.30 是一款免费、开源的跨平台 Web 服务器集成包,专为快速搭建本地 PHP 开发环境而设计。该版本核心组件包括:Apache 2.4.56、MySQL 8.0.33、PHP 8.0.30、phpMyAdmin 5.2.1 等。它支持 Windows、Linux 和 macOS 系统,可让开发者在个人电脑上轻松模拟服务器环境,无需复杂配置即可运行 WordPress、Thin
- 若坚持用非 25 端口,必须切换到
sendmail.exe方案:修改php.ini中的sendmail_path指向sendmail.exe -t,再在sendmail.ini里配smtp_port=587 - Mercury 本身不支持对外 SMTP 客户端使用自定义端口;它的
MercuryC SMTP Client只能通过 “Smart host” 转发,且端口由 “Connection port/type” 下拉菜单限定(如 STARTTLS 对应 587,SSL 对应 465) - 改端口本质是绕开系统级限制,但代价是放弃 Mercury 内置 relay,转而依赖外部 SMTP(Gmail/163 等)
php.ini 里 SMTP 和 sendmail_path 不能共存
二者互斥。XAMPP 默认注释掉 SMTP 行,启用 sendmail_path;一旦你取消注释 SMTP = localhost,PHP 就会忽略 sendmail_path,并强制走 socket 连接 localhost:25 —— 此时 MercuryS 必须运行且允许中继,否则直接失败。
- 推荐方案:保持
sendmail_path = "C:\xampp\sendmail\sendmail.exe -t"开启,禁用SMTP行(前面加分号) - 如果用 Mercury 做中继,
sendmail.ini中smtp_server应设为localhost,smtp_port必须是25(MercuryC 不支持改) - 若用 Gmail 等外发,
sendmail.ini改成smtp_server=smtp.gmail.com+smtp_port=587+smtp_ssl=auto,此时 Mercury 可完全关闭
真正卡住人的不是端口号本身,而是没意识到 Mercury 是“双模块架构”:收信(S)、转发(C)要分开启用,且 PHP 的 mail() 在不同配置下走的是完全不同的底层路径。改一个地方,漏掉另一个,就会陷入“明明填了端口却连不上”的循环。

















