swiftmailer 配置必须在 config/main.php(或 main-local.php)的 components 中以 'mailer' 键注册,transport 用数组定义,敏感信息从 getenv() 读取;535 错误主因是 gmail/outlook 认证失败,需启用应用专用密码或检查用户名、端口、加密方式;发信需调用 ->send()、正确设置模板路径和收件人;环境差异应通过 transport 配置动态切换,开发用 swift_mailtransport,生产用 swift_smtptransport。

SwiftMailer 配置项写在哪?不是在 config/web.php 里硬塞
Yii2 的邮件组件配置必须通过 components 注册,且推荐放在 config/main.php(或 config/main-local.php)中统一管理。直接在控制器里 new Swift_SmtpTransport 是反模式,会导致连接不复用、密码硬编码、环境切换困难。
- SMTP 配置必须用
mailer组件名注册,不能叫email或其他名字,否则Yii::$app->mailer拿不到 -
transport必须是数组形式描述 Swift_Transport,不能传实例对象(Yii 会自己 new) - 密码等敏感字段建议从环境变量读取:
getenv('SMTP_PASSWORD'),避免提交到 Git
'components' => [
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.gmail.com',
'username' => 'your@gmail.com',
'password' => getenv('SMTP_PASSWORD'),
'port' => 587,
'encryption' => 'tls',
],
],
],
发邮件时提示 “Expected response code 250 but got code ‘535’” 怎么办
这是典型的 SMTP 认证失败,Gmail/Outlook 等服务商返回的 535 错误基本等于“用户名或密码不对”,但真实原因常被掩盖:
- Gmail 默认禁用“不够安全的应用”,需开启
允许不够安全的应用(不推荐)或改用应用专用密码(启用两步验证后生成) - Outlook 使用
smtp-mail.outlook.com,端口必须是587+tls,用465+ssl会握手失败,但错误码仍可能是 535 - 某些企业邮箱要求完整邮箱地址作 username(如
user@company.com),只写user会拒登 - 密码里有特殊字符(如
@、/)未 URL 编码,会被 parse 错——实际应把 password 放进getenv(),避开配置文件解析
Yii::$app->mailer->compose() 为什么收不到邮件?检查这三点
compose 流程看似简单,但漏掉任意一环都会静默失败(无异常、无日志、邮件不发):
- 没调
->send():只写compose('contact')不会发,必须链式调用->send()或分开写$message->send() - 模板路径错:默认找
@app/mail/下的视图,compose('contact')对应@app/mail/contact.php;若放错目录或拼错文件名,会返回 null 而非报错 - 没设收件人:
->setTo()是必须的,->setFrom()可省略(用组件里配置的 from),但->setTo()缺失时send()直接返回 false
Yii::$app->mailer->compose('contact')
->setTo('admin@example.com')
->setFrom(['no-reply@site.com' => 'My Site'])
->setSubject('Contact form')
->send();
本地开发用 mail() 函数测试,上线却要切 SMTP?别来回改代码
环境差异应该由配置驱动,而不是 if-else 切逻辑。Yii 支持 transport 切换,关键在 transport 配置项动态替换:
- 开发环境用
Swift_MailTransport:无需 SMTP 账号,依赖系统 sendmail 或 php.ini 的sendmail_path - 生产环境保持
Swift_SmtpTransport,通过YII_ENV条件加载不同配置片段 - 注意
Swift_MailTransport不支持setBcc()和部分 header 设置,测试时别依赖这些特性
真正麻烦的是附件路径、模板中绝对 URL、以及开发时看不到真实发信日志——建议在 afterSend 事件里加日志,而不是靠 send() 返回值判断。











