SwiftMailer 已停维,新项目应改用 symfony/mailer;旧项目若必须使用,需限定版本为 ^6.3,注意 SMTP 配置、UTF-8 编码和连接复用以避免超时、乱码及性能问题。

composer install SwiftMailer 时提示找不到包
SwiftMailer 已在 2019 年停止维护,官方推荐迁移到 symfony/mailer。所以现在用 composer require swiftmailer/swiftmailer 会失败或安装旧版(v6.3.0 是最后一个稳定版),且与 PHP 8.2+、Laravel 10+ 等环境存在兼容问题。
实操建议:
- 确认是否真需要 SwiftMailer:新项目直接用
symfony/mailer+symfony/mime,它更轻、更安全、维护活跃 - 若必须用 SwiftMailer(如老系统维护),指定兼容版本:
composer require swiftmailer/swiftmailer:^6.3 - 避免写
composer require swiftmailer/swiftmailer:~6.0——波浪号会拉取 v6.4(不存在),报Could not find package - 安装后检查
vendor/swiftmailer/swiftmailer/CHANGES.md,确认实际版本是 6.3.0
用 SwiftMailer 发邮件时 connect() 超时或认证失败
不是代码写错了,大概率是传输层配置没对上服务商要求。Gmail、Outlook、阿里云邮件推送等对 SMTP 端口、加密方式、应用密码的要求差异很大。
常见错误现象:
-
Connection could not be established with host smtp.gmail.com:默认用了 tls + port 587,但某些网络拦截了 587 -
Expected response code 235 but got code "535":账号密码错,或 Gmail 没开「应用专用密码」 - 用 QQ 邮箱却填了
smtp.qq.com+ssl+465却没设setStreamOptions(['ssl' => ['allow_self_signed' => true]]),PHP 8.1+ 会拒绝自签名证书
实操建议:
- Gmail 必须用「应用专用密码」,不能用账户登录密码;开启路径:Google 账户 → 安全 → 两步验证 → 应用专用密码
- 阿里云邮件推送只支持 SMTP over TLS(port 587),不支持 SSL(port 465)
- QQ 邮箱若用 465,请显式设置:
$transport->setStreamOptions(['ssl' => ['verify_peer' => false]])(仅测试环境,生产请配好 CA)
发通知邮件时中文乱码、附件打不开、换行失效
SwiftMailer 默认按 US-ASCII 处理内容,不显式声明编码会导致标题乱码、正文断行异常、附件名损坏。这不是 bug,是它把编码责任交给了使用者。
使用场景:发订单通知、注册欢迎信、带 PDF 报表的周报
实操建议:
- 正文必须设编码:
$message->setBody($html, 'text/html', 'utf-8');纯文本用'text/plain' - 中文主题别直接
$message->setSubject('你好'),改用:$message->setSubject('=?UTF-8?B?'.base64_encode('你好').'?=') - 附件名含中文?用
$attachment->setFilename('报表_'.date('Y-m-d').'.pdf'),不要传原始中文名,否则 Outlook 会乱码 - 避免用
\n换行:HTML 邮件里换行用<br>,纯文本里用\r\n(Windows 风格),PHP 的\n在部分 MTA 中会被吞掉
为什么发邮件慢,或队列里卡住不动
SwiftMailer 的 send() 是同步阻塞调用。一次发 10 封,每封耗时 1.2 秒,整批就要 12 秒——用户点完「提交」干等,接口超时,Nginx 直接 504。
性能影响:
- SMTP 连接建立开销大(DNS 查询 + TLS 握手),每封都重连 = 白花时间
- 没启用连接池,
SmtpTransport默认每次send()都新建 socket - 日志级别设成
DEBUG且输出到文件?日志刷盘会拖慢整个流程
实操建议:
- 复用 transport:
$transport->start()后连续 send 多封,最后$transport->stop() - 发批量通知(如全员邮件)务必走队列:Laravel 用
Mail::to(...)->queue(),Symfony 用 Messenger +symfony/mailer - 开发时关掉 transport 日志:
$transport->setLogger(null),避免Swift_Plugins_Loggers_EchoLogger打屏拖慢响应
SwiftMailer 的坑不在语法,而在它把网络细节、编码边界、生命周期管理全摊开给你——稍不注意,就卡在 DNS 超时、证书校验或 MIME 头编码里。这些地方没报错,但就是不发、发错、发得慢。










