diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md index d6b7062cf3f8c..4fa54b1bc61c5 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +5.4 +--- + +* Add support for templates and dynamic template data + 4.4.0 ----- diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php index 006a7583d2d4a..10f2d92377478 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridApiTransport; use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -222,4 +223,86 @@ public function testEnvelopeSenderAndRecipients() $this->assertCount(1, $payload['personalizations'][0]['to']); $this->assertSame($envelopeTo, $payload['personalizations'][0]['to'][0]['email']); } + + public function testSendTemplateIdWithDynamicTemplateData() + { + $templateId = 'd-0aac27809ad64ae98d5ebaf896ea8b33'; + $dynamicTemplateData = [ + 'foo' => 'bar', + ]; + + $email = new Email(); + $email->from(new Address('foo@example.com', 'Ms. Foo Bar')) + ->to(new Address('bar@example.com', 'Mr. Recipient')) + ->bcc('baz@example.com') + ->text('content'); + + $email->getHeaders()->addTextHeader('X-Template-ID', $templateId); + $email->getHeaders()->addTextHeader('X-Dynamic-Template-Data', json_encode($dynamicTemplateData)); + + $response = $this->createMock(ResponseInterface::class); + + $response + ->expects($this->once()) + ->method('getStatusCode') + ->willReturn(202); + $response + ->expects($this->once()) + ->method('getHeaders') + ->willReturn(['x-message-id' => '1']); + + $httpClient = $this->createMock(HttpClientInterface::class); + + $httpClient + ->expects($this->once()) + ->method('request') + ->with('POST', 'https://api.sendgrid.com/v3/mail/send', [ + 'json' => [ + 'personalizations' => [ + [ + 'to' => [[ + 'email' => 'bar@example.com', + 'name' => 'Mr. Recipient', + ]], + 'subject' => null, + 'dynamic_template_data' => $dynamicTemplateData, + 'bcc' => [['email' => 'baz@example.com']], + ], + ], + 'from' => [ + 'email' => 'foo@example.com', + 'name' => 'Ms. Foo Bar', + ], + 'content' => [ + ['type' => 'text/plain', 'value' => 'content'], + ], + 'template_id' => $templateId, + ], + 'auth_bearer' => 'foo', + ]) + ->willReturn($response); + + $mailer = new SendgridApiTransport('foo', $httpClient); + $mailer->send($email); + } + + public function testSendWithInvalidTemplateIdThrowsInvalidArgumentException() + { + $invalidTemplateId = 'd-abcd'; + + $email = new Email(); + $email->from(new Address('foo@example.com', 'Ms. Foo Bar')) + ->to(new Address('bar@example.com', 'Mr. Recipient')) + ->bcc('baz@example.com') + ->text('content'); + + $email->getHeaders()->addTextHeader('X-Template-ID', $invalidTemplateId); + + $mailer = new SendgridApiTransport('foo', $this->createMock(HttpClientInterface::class)); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf('Invalid TemplateID. Got: "%s"', $invalidTemplateId)); + + $mailer->send($email); + } } diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index f1424ae9589c5..143890d015509 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Address; @@ -101,6 +102,8 @@ private function getPayload(Email $email, Envelope $envelope): array $payload['personalizations'][] = $personalization; + $dynamicTemplateData = []; + // these headers can't be overwritten according to Sendgrid docs // see https://sendgrid.api-docs.io/v3.0/mail-send/mail-send-errors#-Headers-Errors $headersToBypass = ['x-sg-id', 'x-sg-eid', 'received', 'dkim-signature', 'content-transfer-encoding', 'from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'reply-to']; @@ -109,9 +112,34 @@ private function getPayload(Email $email, Envelope $envelope): array continue; } + if ('x-template-id' === $name) { + $templateId = $header->getBodyAsString(); + + if (!preg_match('/^d\-[a-z0-9]{32}$/', $templateId)) { + throw new InvalidArgumentException(sprintf('Invalid TemplateID. Got: "%s".', $templateId)); + } + + $payload['template_id'] = $templateId; + + continue; + } + + if ('x-dynamic-template-data' === $name) { + $dynamicTemplateData = json_decode($header->getBodyAsString(), true); + + continue; + } + $payload['headers'][$name] = $header->getBodyAsString(); } + if ([] !== $dynamicTemplateData) { + // we need to add the substitutions to every available personalization + foreach ($payload['personalizations'] as $key => $personalization) { + $payload['personalizations'][$key] = array_merge($payload['personalizations'][$key], ['dynamic_template_data' => $dynamicTemplateData]); + } + } + return $payload; }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: