You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony签名邮件报错:无法创建Email实例,如何解决?

问题:Symfony Mailer SMIME签名后发送失败报错

报错信息

Unable to send message with the "Symfony\Component\Mailer\Transport\AbstractApiTransport" transport: Unable to create an Email from an instance of "Symfony\Component\Mime\Message" as the body is too complex.

问题背景

移除SMIME签名功能后邮件可正常发送,但为了让邮件服务商优先处理邮件,需要保留签名功能并解决该报错。

邮件配置

MAILER_DSN=roundrobin(mailgun+api://*****55643c7e*****f8361b5*****27c-e61ae8dd-7*****:sandboxef6*****2742745ce*****c048689*****.mailgun.org@default?region=us)

相关代码

use Twig\Environment;
use App\Core\MailStruct;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mime\Email;
use Twig\Loader\FilesystemLoader;
use Symfony\Bridge\Twig\Mime\BodyRenderer;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Crypto\SMimeSigner;
use Symfony\Contracts\Service\Attribute\Required;

public function __construct(MailerInterface $mailer)
{
    $this->mailer = $mailer;
}

public function send(MailStruct $mail): void
{
    
    $email = (new TemplatedEmail())
    ->from('mailgun@*****.mailgun.org')
    ->to('b***@yahoo.com')
    ->replyTo('mailgun@*****.mailgun.org')
    ->priority(Email::PRIORITY_HIGH)
    ->subject('Time for Symfony Mailer!')
    ->htmlTemplate('test.html.twig')
    ->locale('de')
    ->context([
        'expiration_date' => '77',
        'username' => 'stellaGregory',
        'address' => '6 Kamasojo',
    ]);

    $loader = new FilesystemLoader('../templates/');
    $twigEnv = new Environment($loader);
    $twigBodyRenderer = new BodyRenderer($twigEnv);
    $twigBodyRenderer->render($email);

    try {
        $signer = new SMimeSigner(__DIR__.'/certificate/certificate.crt', __DIR__.'/certificate/private.key');
        $email = $signer->sign($email);
        $this->mailer->send($email);   
    } catch (\Throwable $th) {
        throw $th;
    }
}

解决方案

核心原因

报错根源在于你使用的Mailgun API传输(mailgun+api://)属于AbstractApiTransport,这类传输需要将邮件解析为结构化的Email对象来调用服务商API,但SMIME签名后,原TemplatedEmail会被转换为Symfony\Component\Mime\Message——这是一个完整的MIME消息对象,结构过于复杂,无法被API传输解析。

解决办法

切换到SMTP传输协议,SMTP传输直接发送完整的MIME消息,不需要解析邮件结构,完美支持签名后的复杂Message对象。

  1. 修改MAILER_DSN配置
    将原API协议的DSN替换为SMTP协议的DSN,格式如下:
MAILER_DSN=mailgun+smtp://SMTP_USERNAME:SMTP_PASSWORD@default?region=us
  • SMTP_USERNAME和SMTP_PASSWORD可在Mailgun控制台的「SMTP凭证」板块获取(通常用户名是postmaster@your-domain.mailgun.org,密码是随机生成的字符串)。
  • 如果使用roundrobin负载均衡,格式为:
MAILER_DSN=roundrobin(mailgun+smtp://SMTP_USERNAME:SMTP_PASSWORD@default?region=us)
  1. 代码优化(可选)
    原代码中手动实例化Twig环境和渲染器不符合Symfony最佳实践,可改为注入Twig服务:
// 构造函数注入Twig\Environment
public function __construct(MailerInterface $mailer, private Environment $twigEnv)
{
    $this->mailer = $mailer;
}

public function send(MailStruct $mail): void
{
    $email = (new TemplatedEmail())
        ->from('mailgun@*****.mailgun.org')
        ->to('b***@yahoo.com')
        ->replyTo('mailgun@*****.mailgun.org')
        ->priority(Email::PRIORITY_HIGH)
        ->subject('Time for Symfony Mailer!')
        ->htmlTemplate('test.html.twig')
        ->locale('de')
        ->context([
            'expiration_date' => '77',
            'username' => 'stellaGregory',
            'address' => '6 Kamasojo',
        ]);

    // 无需手动渲染,TemplatedEmail会自动通过Twig服务渲染
    try {
        $signer = new SMimeSigner(__DIR__.'/certificate/certificate.crt', __DIR__.'/certificate/private.key');
        $email = $signer->sign($email);
        $this->mailer->send($email);   
    } catch (\Throwable $th) {
        throw $th;
    }
}

内容的提问来源于stack exchange,提问作者DevOPlug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:53:16