如何通过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
相关产品推荐
相关产品推荐

