mailer配置必须指定transport,否则会抛出logicexception: no transport configured;需在config/packages/mailer.yaml中显式配置dsn,且仅装symfony/mailer不够,发mailjet等邮件须额外安装对应bridge包如symfony/mailjet-mailer。

Mailer配置必须指定transport,否则会报LogicException
Symfony Mailer默认不启用任何传输(transport),即使装了symfony/mailer包,直接调用MailerInterface::send()也会抛出LogicException: No transport configured。这不是环境问题,是设计使然——你得显式告诉它“用什么发”。
- 开发环境推荐用
smtp://localhost:1025配合mailhog或symfony-cli内置的symfony server:mail:watch - 生产环境常见配置:使用
smtp://user:pass@smtp.gmail.com:587(注意开启App密码)、sendgrid+api、或mailgun+api - 配置写在
config/packages/mailer.yaml里,dsn字段必须存在,且不能是空字符串或null
MailjetTransport需要额外安装symfony/mailjet-mailer
官方不把所有邮件服务商SDK打包进核心,Mailjet、SendGrid、Postmark等都要单独装对应bridge包。只装symfony/mailer后,MAILER_DSN=mailjet+api://...会静默失败或报Invalid DSN。
- 运行
composer require symfony/mailjet-mailer才能解析mailjet+api://协议 - 同理:
sendgrid+api→symfony/sendgrid-mailer;postmark+api→symfony/postmark-mailer - API密钥建议从
%env(MAILJET_API_KEY)%读取,不要硬编码在mailer.yaml中
模板邮件必须用TemplatedEmail,不能直接传Twig内容
很多人误以为$email->htmlTemplate('email/welcome.html.twig')只是设置模板路径,其实它还触发了自动渲染逻辑。如果手动调用$twig->render()再塞进htmlBody(),会导致主题、内联CSS、附件路径等丢失——尤其是用了symfony/webpack-encore或css-in-js时样式全崩。
- 正确做法:用
TemplatedEmail,调用htmlTemplate()和textTemplate(),再用context()传变量 - 模板里用
{{ email.subject }}、{{ email.from }}等自动注入的属性,不是靠全局app变量 - 附件需用
addPart()或attachFromPath(),不能在Twig里用asset()生成链接代替
异步发送要配enqueue或amqp,别用sync假装异步
设transport: 'async://default'只是语法糖,底层仍走同步HTTP或SMTP,除非你真接了消息队列。真正异步必须配enqueue(推荐)或amqp transport,并启动worker进程。
-
composer require enqueue/simple-client+ 配置enqueue.yaml指向Redis或AMQP - 发信时用
$mailer->send($email, new EnqueueStamp()),否则还是同步执行 - 本地开发可先用
doctrinetransport(基于数据库表),避免部署额外服务,但注意清理enqueue表
最常被忽略的是:没配failure_transport时,队列失败邮件直接丢弃,连日志都不打。线上务必加failure_transport: smtp兜底。











