From 68ac9dec9d370b94b39e95f4ed2c15002e054800 Mon Sep 17 00:00:00 2001 From: atymic Date: Sat, 25 Jul 2026 14:28:43 +1000 Subject: [PATCH] [13.x] Add SES tenant support to the SES v2 transport --- .../Mail/Transport/SesV2Transport.php | 19 ++++++++ tests/Mail/MailSesV2TransportTest.php | 47 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/Illuminate/Mail/Transport/SesV2Transport.php b/src/Illuminate/Mail/Transport/SesV2Transport.php index 3052a0826b46..64d090af60d9 100644 --- a/src/Illuminate/Mail/Transport/SesV2Transport.php +++ b/src/Illuminate/Mail/Transport/SesV2Transport.php @@ -56,6 +56,10 @@ protected function doSend(SentMessage $message): void $options['ListManagementOptions'] = $listManagementOptions; } + if ($tenantName = $this->tenantName($message)) { + $options['TenantName'] = $tenantName; + } + foreach ($message->getOriginalMessage()->getHeaders()->all() as $header) { if ($header instanceof MetadataHeader) { $options['EmailTags'][] = ['Name' => $header->getKey(), 'Value' => $header->getValue()]; @@ -114,6 +118,21 @@ protected function listManagementOptions(SentMessage $message) } } + /** + * Extract the SES tenant name, if applicable. + * + * @param \Symfony\Component\Mailer\SentMessage $message + * @return string|null + */ + protected function tenantName(SentMessage $message) + { + if ($header = $message->getOriginalMessage()->getHeaders()->get('X-SES-TENANT-NAME')) { + return $header->getBodyAsString() ?: null; + } + + return null; + } + /** * Get the Amazon SES V2 client for the SesV2Transport instance. * diff --git a/tests/Mail/MailSesV2TransportTest.php b/tests/Mail/MailSesV2TransportTest.php index 232c8bcb17df..2fc2b6ee515b 100755 --- a/tests/Mail/MailSesV2TransportTest.php +++ b/tests/Mail/MailSesV2TransportTest.php @@ -76,6 +76,53 @@ public function testSend(): void (new SesV2Transport($client))->send($message); } + public function testSendWithTenantName(): void + { + $message = new Email(); + $message->subject('Foo subject'); + $message->text('Bar body'); + $message->sender('myself@example.com'); + $message->to('me@example.com'); + $message->getHeaders()->addTextHeader('X-SES-TENANT-NAME', 'my-tenant'); + + $client = m::mock(SesV2Client::class); + $sesResult = m::mock(); + $sesResult->shouldReceive('get') + ->with('MessageId') + ->once() + ->andReturn('ses-message-id'); + $client->shouldReceive('sendEmail')->once() + ->with(m::on(function ($arg) { + return $arg['TenantName'] === 'my-tenant'; + })) + ->andReturn($sesResult); + + (new SesV2Transport($client))->send($message); + } + + public function testSendWithoutTenantNameDoesNotSetTheOption(): void + { + $message = new Email(); + $message->subject('Foo subject'); + $message->text('Bar body'); + $message->sender('myself@example.com'); + $message->to('me@example.com'); + + $client = m::mock(SesV2Client::class); + $sesResult = m::mock(); + $sesResult->shouldReceive('get') + ->with('MessageId') + ->once() + ->andReturn('ses-message-id'); + $client->shouldReceive('sendEmail')->once() + ->with(m::on(function ($arg) { + return ! array_key_exists('TenantName', $arg); + })) + ->andReturn($sesResult); + + (new SesV2Transport($client))->send($message); + } + public function testSendError(): void { $message = new Email();