ThinkPHP 6 多环境 SMTP 配置核心在 .env 文件,通过 MAIL_DRIVER 等环境变量动态注入;config/mail.php 仅保留驱动类型声明,不硬编码参数;PHP 8.1+/OpenSSL 3.0 下需显式设 MAIL_ENCRYPTION=tls 并匹配端口;开发用 log 驱动、生产切 smtp 由环境变量自动切换;自定义 SMTP 驱动须通过 transport 配置或 Mail::setTransport() 设置 Swift_SmtpTransport 实例。

ThinkPHP 6 配置多环境 SMTP 邮件驱动的关键位置在哪
核心配置不在 config/mail.php 里硬编码,而是在环境变量中动态注入。ThinkPHP 6 的 think\facade\Mail 默认读取 MAIL_HOST、MAIL_USER 等环境变量,而非直接从 PHP 配置文件取值——这点和 TP5 差异很大,很多人照搬旧写法导致本地能发、线上 500。
实操建议:
- 把 SMTP 配置全挪到
.env文件,不同环境(dev/staging/prod)用不同 .env.* 文件管理 -
config/mail.php中只保留基础结构,如'driver' => env('MAIL_DRIVER', 'smtp'),其余字段留空或设为null - 确保
think\facade\Mail初始化前已加载环境变量(默认已做,但若手动调用Env::load()过早,可能被覆盖)
SMTP 驱动在 PHP 8.1+ 和 OpenSSL 3.0 下发信失败的典型报错
常见错误是 Connection failed: stream_socket_enable_crypto(): SSL operation failed 或 Failed to authenticate on SMTP server,本质不是账号密码错,而是加密协议不匹配。
原因和解法:
立即学习“PHP免费学习笔记(深入)”;
- 腾讯企业邮箱、阿里云邮件推送等默认关闭 TLS 1.0/1.1,PHP 8.1+ 的 OpenSSL 3.0 默认禁用弱协议,需显式指定
MAIL_ENCRYPTION=tls(不能写STARTTLS或空字符串) -
MAIL_PORT必须与加密方式严格对应:465 →ssl;587 →tls;部分服务商(如网易)要求 993/995 以外端口一律走tls - 某些内网环境 DNS 解析慢,导致连接超时,可在
config/mail.php加'timeout' => 10,避免卡死
如何让开发环境用 log 驱动、生产环境切回 smtp 驱动
不是靠 if-else 判断 App::isDebug(),而是靠环境变量驱动自动切换。ThinkPHP 6 的 Mail 组件会根据 MAIL_DRIVER 值自动实例化对应驱动类,log 驱动本身存在且无需额外安装。
操作步骤:
- 开发环境
.env写:MAIL_DRIVER=log,此时所有Mail::to()->send()不发信,只写入runtime/log/下的邮件日志 - 测试环境可设
MAIL_DRIVER=smtp+MAIL_HOST=smtp.qq.com,但MAIL_PASSWORD必须是 QQ 邮箱的「SMTP 授权码」,不是登录密码 - 生产环境务必关闭
debug并确保MAIL_FROM_ADDRESS是已验证过的发信域名邮箱,否则很多云邮箱服务直接拒收
自定义 SMTP 驱动时 getTransport() 方法被绕过的原因
有人想继承 think\mail\driver\Smtp 改写认证逻辑,却发现重写的 getTransport() 根本没执行——因为 ThinkPHP 6 默认使用 Swift_SmtpTransport,而框架在初始化时已通过 new Swift_SmtpTransport() 硬编码创建实例,不走你重写的类。
真正生效的方式只有两种:
- 改
config/mail.php的'transport' => ['type' => 'smtp'],再配合'smtp' => [...]子配置项微调行为(比如加'stream_options'控制 SSL 上下文) - 完全弃用内置驱动,自己 new 一个
Swift_SmtpTransport实例传给Mail::setTransport(),但要注意生命周期管理,避免重复初始化 - 别试图 patch
think\mail\driver\Smtp,它的connect()方法里有大量私有属性和异常吞并逻辑,改了容易漏掉auth()或startTls()的调用时机
环境兼容真正的难点不在配置格式,而在各云邮箱服务商对 TLS 版本、证书链、HELO 域名、发信频率的隐性限制——这些不会报错,只会静默丢信或进垃圾箱。



















