diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md index 4a068489286f3..ca039e3cab16e 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.3 +--- + + * Add support for scheduling delivery with the `send_at` API parameter via a + `Send-At` date-header + 7.2 --- diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md b/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md index 8f97d4ea08bd5..b672c30b24e0d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md @@ -44,6 +44,20 @@ class SendGridConsumer implements ConsumerInterface } ``` +Scheduling +---------- + +When using the **API transport** (with a `sendgrid+api` DSN), you can schedule +your emails by providing a `\DateTimeInterface` object in a +`Symfony\Component\Mime\Header\DateHeader` named `Send-At`. + +```php +$email = new \Symfony\Component\Mime\Email(); +$email->getHeaders()->addDateHeader('Send-At', (new \DateTime())->modify('+3 hours')); +``` +It will be mapped to the `send_at` parameter of the `[POST] /mail/send` +[API endpoint](https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body) + Resources --------- 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 37dd4598cbaeb..6dcf94f794092 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php @@ -290,4 +290,18 @@ public function testInlineWithoutCustomContentId() $this->assertSame('text.txt', $payload['attachments'][0]['content_id']); } + + public function testSendAtHeader() + { + $email = new Email(); + $email->getHeaders()->addDateHeader('Send-At', new \DateTime('2025-05-07 16:00:00', new \DateTimeZone('Europe/Paris'))); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new SendgridApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload'); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('send_at', $payload); + $this->assertSame(1746626400, $payload['send_at']); + } } diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index ea5261c642b71..e4bfea707b9dc 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -22,6 +22,7 @@ use Symfony\Component\Mailer\Transport\AbstractApiTransport; use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\DateHeader; use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -126,7 +127,12 @@ private function getPayload(Email $email, Envelope $envelope): array continue; } - if ($header instanceof TagHeader) { + if ('send-at' === $name) { + if (!$header instanceof DateHeader) { + throw new TransportException(sprintf('The Send-At header should be a "%s" instance to deduce the correct timestamp.', DateHeader::class)); + } + $payload['send_at'] = $header->getDateTime()->getTimestamp(); + } elseif ($header instanceof TagHeader) { if (10 === \count($categories)) { throw new TransportException(\sprintf('Too many "%s" instances present in the email headers. Sendgrid does not accept more than 10 categories on an email.', TagHeader::class)); }