yii::$app->mailer->compose()调用后不发邮件,主因是mailer配置未置于components且key非'mailer'、usefiletransport未设为false、或compose后未调用send()。

Yii::$app->mailer->compose() 调用后不发邮件?不是代码写错了,是配置、调用链或环境开关没对齐——90% 的“发不出”问题都卡在这三处。
mailer 配置必须放在 components 里,且 key 必须叫 'mailer'
Yii 框架只认 'mailer' 这个组件名,写成 'email' 或 'mail' 都拿不到实例。配置位置也必须是 config/main.php(或 main-local.php),不能塞进 web.php 里凑数,更不能在控制器里直接 new Swift_SmtpTransport。
正确结构示例:
'components' => [
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false,
'viewPath' => '@app/mail',
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.gmail.com',
'username' => 'your@gmail.com',
'password' => getenv('SMTP_PASSWORD'),
'port' => 587,
'encryption' => 'tls',
],
],
],
-
useFileTransport设为false才真发,设为true会静默存到@runtime/mail/目录下生成 .eml 文件(适合开发调试) -
password务必从getenv()读,硬编码在配置里既不安全,又容易因特殊字符(如@、/)被解析出错 - 多个邮箱通道要复用同一套 transport 逻辑?别复制粘贴配置,用
Yii::createObject()动态构造 transport 实例更可控
compose() 后必须显式调用 send(),否则等于没写
Yii::$app->mailer->compose() 只返回一个 MessageInterface 对象,它不自动发送。漏掉 ->send() 或分开写 $message->send(),程序不会报错,但收件人永远等不到邮件。
- 单封邮件:必须链式调用
->setTo()->setSubject()->setHtmlBody()->send() - 模板路径错也静默失败:
compose('welcome')默认找@app/mail/welcome.php,文件不存在或拼错名,compose()返回null,后续send()会报Call to a member function send() on null - 批量发送用
sendMultiple(),但传入数组每个元素都得是已调用compose()并设置好setTo()的完整消息对象
535 错误 = 认证失败,但真实原因常藏在端口/加密/用户名格式里
SMTP 返回 535 Authentication failed,第一反应是密码错,但实际更可能是:
- Gmail 要求开两步验证 + 应用专用密码,用主账号密码必挂;Outlook 必须用
smtp-mail.outlook.com+587/tls,填465/ssl也会返回 535 - 企业邮箱(如网易、腾讯企业邮)的
username必须是完整邮箱地址(user@company.com),只写user就拒登 - QQ 邮箱端口填
25很可能被运营商拦截,推荐改用587或465;163 邮箱若用994端口,需确认是否真启用了 SSL(多数情况应选465) - 本地开发时用
useFileTransport => true,但忘了上线前关掉,结果邮件全堆在 runtime 目录里没人看
附件和中文文件名处理最容易翻车
attach() 接收绝对路径,相对路径(如 img/logo.png)大概率失败;attachContent() 适合动态内容,但中文文件名默认乱码。
- 附件路径务必用
Yii::getAlias('@webroot/path/to/file.pdf')转成绝对路径 - 中文文件名要先转码:
mb_convert_encoding('发票.pdf', 'GB2312', 'UTF-8'),或干脆用英文名 + 正文说明 - 大附件(>2MB)易触发 PHP
memory_limit或max_execution_time,建议前端提示“请压缩后上传”,后端加@ini_set('memory_limit', '128M')临时兜底 - 图片内嵌(
embed())和普通附件(attach())别混用;内嵌图需在 HTML 中用cid:xxx引用,否则显示为乱码占位符
useFileTransport 关着,但 transport 配错了端口,错误日志里只报连接超时,根本不会提一句“你连的其实是假 smtp”;再比如模板里用了未定义变量,compose() 返回 null,但没人检查就直接 send(),最后只看到 Fatal error。这些点不踩一遍,很难信。











