diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php index a1b0ae7f1a81e..b6061f03cd3e6 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php @@ -12,7 +12,12 @@ namespace Symfony\Component\Mailer\Bridge\Amazon\Tests\Transport; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesApiTransport; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; class SesApiTransportTest extends TestCase { @@ -45,4 +50,83 @@ public function getTransportData() ], ]; } + + public function testSendEmail() + { + $awsApiCallback = function ($method, $url, $options) { + $requestParts = []; + parse_str($options['body'], $requestParts); + + $this->assertEquals('POST', $method); + $this->assertEquals('https://email.eu-west-1.amazonaws.com/', $url); + + $this->assertEquals($requestParts['Source'], 'sender@example.tld'); + $this->assertArrayNotHasKey('Destinations.member', $requestParts); + + return new MockResponse($this->createMockAwsSendRawEmailResponse()); + }; + + $httpClient = new MockHttpClient($awsApiCallback); + $transport = new SesApiTransport('ACCESS_KEY', 'SECRET_KEY', 'eu-west-1', $httpClient); + + $email = (new Email()) + ->from('sender@example.tld') + ->to('recipient-to@example.tld') + ->subject('Test Mail') + ->text('Text content of the test mail') + ->html('

HTML content of the test mail

'); + + $transport->send($email); + } + + public function testSendEmailWithEnvelopeOverride() + { + $awsApiCallback = function ($method, $url, $options) { + $requestParts = []; + parse_str($options['body'], $requestParts); + + $this->assertEquals('POST', $method); + $this->assertEquals('https://email.eu-west-1.amazonaws.com/', $url); + + $this->assertEquals($requestParts['Source'], 'envelope-sender@example.tld'); + $this->assertArrayHasKey('Destinations_member', $requestParts); + $this->assertEquals($requestParts['Destinations_member'], [ + 'envelope-recipient-1@example.tld', + 'envelope-recipient-2@example.tld', + ]); + + return new MockResponse($this->createMockAwsSendRawEmailResponse()); + }; + + $httpClient = new MockHttpClient($awsApiCallback); + $transport = new SesApiTransport('ACCESS_KEY', 'SECRET_KEY', 'eu-west-1', $httpClient); + + $email = (new Email()) + ->from('sender@example.tld') + ->to('recipient-to@example.tld') + ->subject('Test Mail') + ->text('Text content of the test mail') + ->html('

HTML content of the test mail

'); + + $envelope = new Envelope(Address::create('envelope-sender@example.tld'), [ + Address::create('envelope-recipient-1@example.tld'), + Address::create('envelope-recipient-2@example.tld'), + ]); + + $transport->send($email, $envelope); + } + + private function createMockAwsSendRawEmailResponse(): string + { + return << + + 0102016f1eb7661b-4294e7da-5d64-45c2-8998-e8ade5468d95-000000 + + + dc4fb17f-0320-428b-8c03-62f9ec9b98ba + + +XML; + } } diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php index 22ef23e84ba52..f0089070ff8bc 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php @@ -16,7 +16,9 @@ use Symfony\Component\Mailer\Exception\HttpTransportException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractApiTransport; +use Symfony\Component\Mime\Address; use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\MailboxListHeader; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -87,33 +89,42 @@ private function getSignature(string $string): string private function getPayload(Email $email, Envelope $envelope): array { - if ($email->getAttachments()) { - return [ - 'Action' => 'SendRawEmail', - 'RawMessage.Data' => base64_encode($email->toString()), - ]; - } - $payload = [ - 'Action' => 'SendEmail', - 'Destination.ToAddresses.member' => $this->stringifyAddresses($this->getRecipients($email, $envelope)), - 'Message.Subject.Data' => $email->getSubject(), + 'Action' => 'SendRawEmail', + 'RawMessage.Data' => base64_encode($email->toString()), 'Source' => $envelope->getSender()->toString(), ]; - if ($emails = $email->getCc()) { - $payload['Destination.CcAddresses.member'] = $this->stringifyAddresses($emails); - } - if ($emails = $email->getBcc()) { - $payload['Destination.BccAddresses.member'] = $this->stringifyAddresses($emails); - } - if ($email->getTextBody()) { - $payload['Message.Body.Text.Data'] = $email->getTextBody(); - } - if ($email->getHtmlBody()) { - $payload['Message.Body.Html.Data'] = $email->getHtmlBody(); + $headerRecipients = $this->getRecipientAddressesFromHeaders($email); + $envelopeRecipients = array_map(static function (Address $recipient) { + return $recipient->getAddress(); + }, $envelope->getRecipients()); + $requiresDestinations = \count(array_diff($headerRecipients, $envelopeRecipients)) > 0; + + if ($requiresDestinations) { + $payload['Destinations.member'] = $this->stringifyAddresses($envelope->getRecipients()); } return $payload; } + + /** + * @return string[] + */ + private function getRecipientAddressesFromHeaders(Email $email): array + { + $headers = $email->getHeaders(); + + $recipients = []; + foreach (['to', 'cc', 'bcc'] as $name) { + foreach ($headers->all($name) as $header) { + /* @var MailboxListHeader $header */ + foreach ($header->getAddresses() as $address) { + $recipients[] = $address->getAddress(); + } + } + } + + return $recipients; + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy