Skip to content

Commit a317491

Browse files
author
Mickael GOETZ
committed
[Mailer][SendGrid] add support for scheduling delivery via send_at API parameter
1 parent 7c43418 commit a317491

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

src/Symfony/Component/Mailer/Bridge/Sendgrid/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Add support for scheduling delivery with the `send_at` API parameter via a
8+
`Send-At` date-header
9+
410
7.2
511
---
612

src/Symfony/Component/Mailer/Bridge/Sendgrid/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ class SendGridConsumer implements ConsumerInterface
4444
}
4545
```
4646

47+
Scheduling
48+
----------
49+
50+
When using the **API transport** (with a `sendgrid+api` DSN), you can schedule
51+
your emails by providing a `\DateTimeInterface` object in a
52+
`Symfony\Component\Mime\Header\DateHeader` named `Send-At`.
53+
54+
```php
55+
$email = new \Symfony\Component\Mime\Email();
56+
$email->getHeaders()->addDateHeader('Send-At', (new \DateTime())->modify('+3 hours'));
57+
```
58+
It will be mapped to the `send_at` parameter of the `[POST] /mail/send`
59+
[API endpoint](https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body)
60+
4761
Resources
4862
---------
4963

src/Symfony/Component/Mailer/Bridge/Sendgrid/Tests/Transport/SendgridApiTransportTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,18 @@ public function testInlineWithoutCustomContentId()
290290

291291
$this->assertSame('text.txt', $payload['attachments'][0]['content_id']);
292292
}
293+
294+
public function testSendAtHeader()
295+
{
296+
$email = new Email();
297+
$email->getHeaders()->addDateHeader('Send-At', new \DateTime('2025-05-07 16:00:00', new \DateTimeZone('Europe/Paris')));
298+
$envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]);
299+
300+
$transport = new SendgridApiTransport('ACCESS_KEY');
301+
$method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload');
302+
$payload = $method->invoke($transport, $email, $envelope);
303+
304+
$this->assertArrayHasKey('send_at', $payload);
305+
$this->assertSame(1746626400, $payload['send_at']);
306+
}
293307
}

src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
2323
use Symfony\Component\Mime\Address;
2424
use Symfony\Component\Mime\Email;
25+
use Symfony\Component\Mime\Header\DateHeader;
2526
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
2627
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
2728
use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -126,7 +127,12 @@ private function getPayload(Email $email, Envelope $envelope): array
126127
continue;
127128
}
128129

129-
if ($header instanceof TagHeader) {
130+
if ('send-at' === $name) {
131+
if (!$header instanceof DateHeader) {
132+
throw new TransportException(sprintf('The Send-At header should be a "%s" instance to deduce the correct timestamp.', DateHeader::class));
133+
}
134+
$payload['send_at'] = $header->getDateTime()->getTimestamp();
135+
} elseif ($header instanceof TagHeader) {
130136
if (10 === \count($categories)) {
131137
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));
132138
}

0 commit comments

Comments
 (0)