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

如何通过Symfony的SendgridApiTransport实现SendGrid个性化替换?

Symfony 7.0 SendgridApiTransport 实现个性化替换方案

当前默认的SendgridApiTransport确实未直接支持SendGrid V3 API中personalizations字段下的substitutions个性化替换逻辑,你观察到的仅支持custom_args是准确的。以下是两种可行的实现方案:

方案一:自定义Transport扩展原生实现

通过继承SendgridApiTransport并重写buildPayload方法,在构建请求体时加入substitutions的处理逻辑:

namespace App\Mailer\Transport;

use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridApiTransport;
use Symfony\Component\Mime\Email;

class CustomSendgridApiTransport extends SendgridApiTransport
{
    protected function buildPayload(Email $email): array
    {
        $payload = parent::buildPayload($email);
        
        // 从邮件自定义元数据中获取替换规则
        $substitutions = $email->getMetadata('sendgrid_substitutions', []);
        
        if (!empty($substitutions) && isset($payload['personalizations'][0])) {
            $payload['personalizations'][0]['substitutions'] = $substitutions;
        }
        
        // 多收件人批量替换场景:循环处理每个personalization条目
        // foreach ($payload['personalizations'] as &$personalization) {
        //     // 根据收件人邮箱匹配对应的替换规则
        //     $recipientEmail = $personalization['to'][0]['email'];
        //     $personalization['substitutions'] = $this->getSubstitutionsForRecipient($recipientEmail);
        // }
        
        return $payload;
    }

    // 可选:为多收件人场景提供替换规则匹配逻辑
    // private function getSubstitutionsForRecipient(string $email): array
    // {
    //     // 从数据库/配置中获取对应收件人的替换规则
    //     return match($email) {
    //         'alice@example.com' => ['-name-' => 'Alice'],
    //         'bob@example.com' => ['-name-' => 'Bob'],
    //         default => []
    //     };
    // }
}

使用时在邮件中添加自定义元数据:

$email = (new Email())
    ->from('myname@mycompany.com')
    ->to('alice@example.com')
    ->subject('New mail')
    ->text('Hi -name-, lorem ipsum')
    ->setMetadata('sendgrid_substitutions', [
        '-name-' => 'Alice'
    ]);

方案二:利用邮件事件监听器动态修改请求体

通过监听Symfony Mailer的MessageEvent,在发送前动态修改SendGrid的请求payload:

namespace App\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridApiTransport;
use Symfony\Component\Mime\Email;
use Symfony\Component\HttpClient\Event\RequestEvent;

class SendgridSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            MessageEvent::class => 'prepareSubstitutions',
            RequestEvent::class => 'modifyRequestPayload',
        ];
    }

    private array $substitutions = [];

    public function prepareSubstitutions(MessageEvent $event): void
    {
        $transport = $event->getTransport();
        if (!$transport instanceof SendgridApiTransport) {
            return;
        }

        $message = $event->getMessage();
        if (!$message instanceof Email) {
            return;
        }

        // 暂存替换规则,后续在请求事件中使用
        $this->substitutions[$message->getId()] = $message->getMetadata('sendgrid_substitutions', []);
    }

    public function modifyRequestPayload(RequestEvent $event): void
    {
        $request = $event->getRequest();
        // 仅处理SendGrid API请求
        if (strpos($request->getUri(), 'sendgrid.com/v3/mail/send') === false) {
            return;
        }

        $messageId = $request->getHeaders()['x-mailer-message-id'][0] ?? '';
        if (empty($this->substitutions[$messageId])) {
            return;
        }

        // 修改请求体
        $payload = json_decode($request->getContent(), true);
        if (isset($payload['personalizations'][0])) {
            $payload['personalizations'][0]['substitutions'] = $this->substitutions[$messageId];
        }
        $request->setContent(json_encode($payload));
    }
}

在services.yaml中注册监听器:

services:
    App\EventListener\SendgridSubscriber:
        tags:
            - { name: kernel.event_subscriber }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:55:06