From a36fec32048940dbc0dfcc225ab0393dda6d6574 Mon Sep 17 00:00:00 2001 From: Clara van Miert Date: Thu, 20 Aug 2020 18:03:09 +0200 Subject: [PATCH] [Mailer] Support Amazon SES ConfigurationSetName In Amazon SES a Configuration Set can be used to monitor email sending events (delivery, bounces, complaints etc.). In order to use this feature the ConfigurationSetName needs to be sent along with the email. Setting the `X-SES-CONFIGURATION-SET` header should accomplish this for all SES Transports now. Ref: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-configuration-sets-in-email.html --- .../Transport/SesApiAsyncAwsTransportTest.php | 3 ++ .../Tests/Transport/SesApiTransportTest.php | 48 +++++++++++++++++++ .../SesHttpAsyncAwsTransportTest.php | 3 ++ .../Tests/Transport/SesHttpTransportTest.php | 4 ++ .../Transport/SesApiAsyncAwsTransport.php | 3 ++ .../Amazon/Transport/SesApiTransport.php | 11 ++++- .../Transport/SesHttpAsyncAwsTransport.php | 12 ++++- .../Amazon/Transport/SesHttpTransport.php | 12 ++++- 8 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php index 88e1bd98ccf21..2cd87cf96b2fa 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php @@ -69,6 +69,7 @@ public function testSend() $this->assertSame('Hello There!', $content['Content']['Simple']['Body']['Text']['Data']); $this->assertSame('Hello There!', $content['Content']['Simple']['Body']['Html']['Data']); $this->assertSame(['replyto-1@example.com', 'replyto-2@example.com'], $content['ReplyToAddresses']); + $this->assertSame('aws-configuration-set-name', $content['ConfigurationSetName']); $json = '{"MessageId": "foobar"}'; @@ -87,6 +88,8 @@ public function testSend() ->html('Hello There!') ->replyTo(new Address('replyto-1@example.com'), new Address('replyto-2@example.com')); + $mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name'); + $message = $transport->send($mail); $this->assertSame('foobar', $message->getMessageId()); 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 2a4adfa418a74..b4dfa191aea0f 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php @@ -68,6 +68,7 @@ public function testSend() $this->assertSame('Saif Eddin ', $content['Destination_ToAddresses_member'][0]); $this->assertSame('Fabien ', $content['Source']); $this->assertSame('Hello There!', $content['Message_Body_Text_Data']); + $this->assertSame('aws-configuration-set-name', $content['ConfigurationSetName']); $xml = ' @@ -88,6 +89,53 @@ public function testSend() ->from(new Address('fabpot@symfony.com', 'Fabien')) ->text('Hello There!'); + $mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name'); + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } + + public function testSendWithAttachments() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://email.eu-west-1.amazonaws.com:8984/', $url); + $this->assertStringContainsStringIgnoringCase('X-Amzn-Authorization: AWS3-HTTPS AWSAccessKeyId=ACCESS_KEY,Algorithm=HmacSHA256,Signature=', $options['headers'][0] ?? $options['request_headers'][0]); + + parse_str($options['body'], $body); + $content = base64_decode($body['RawMessage_Data']); + + $this->assertStringContainsString('Hello!', $content); + $this->assertStringContainsString('Saif Eddin ', $content); + $this->assertStringContainsString('Fabien ', $content); + $this->assertStringContainsString('Hello There!', $content); + $this->assertStringContainsString(base64_encode('attached data'), $content); + + $this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']); + + $xml = ' + + foobar + +'; + + return new MockResponse($xml, [ + 'http_code' => 200, + ]); + }); + $transport = new SesApiTransport('ACCESS_KEY', 'SECRET_KEY', null, $client); + $transport->setPort(8984); + + $mail = new Email(); + $mail->subject('Hello!') + ->to(new Address('saif.gmati@symfony.com', 'Saif Eddin')) + ->from(new Address('fabpot@symfony.com', 'Fabien')) + ->text('Hello There!') + ->attach('attached data'); + + $mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name'); + $message = $transport->send($mail); $this->assertSame('foobar', $message->getMessageId()); diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpAsyncAwsTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpAsyncAwsTransportTest.php index ff3a6e23adcf1..5b79491fbcb0d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpAsyncAwsTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpAsyncAwsTransportTest.php @@ -68,6 +68,7 @@ public function testSend() $this->assertStringContainsString('Saif Eddin ', $content); $this->assertStringContainsString('Fabien ', $content); $this->assertStringContainsString('Hello There!', $content); + $this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']); $json = '{"MessageId": "foobar"}'; @@ -84,6 +85,8 @@ public function testSend() ->from(new Address('fabpot@symfony.com', 'Fabien')) ->text('Hello There!'); + $mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name'); + $message = $transport->send($mail); $this->assertSame('foobar', $message->getMessageId()); diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpTransportTest.php index 994990443d31a..e1f28be82497c 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpTransportTest.php @@ -70,6 +70,8 @@ public function testSend() $this->assertStringContainsString('Fabien ', $content); $this->assertStringContainsString('Hello There!', $content); + $this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']); + $xml = ' foobar @@ -89,6 +91,8 @@ public function testSend() ->from(new Address('fabpot@symfony.com', 'Fabien')) ->text('Hello There!'); + $mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name'); + $message = $transport->send($mail); $this->assertSame('foobar', $message->getMessageId()); diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiAsyncAwsTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiAsyncAwsTransport.php index e7878ccc8b7e6..9c03fe37445a8 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiAsyncAwsTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiAsyncAwsTransport.php @@ -89,6 +89,9 @@ protected function getRequest(SentMessage $message): SendEmailRequest if ($emails = $email->getReplyTo()) { $request['ReplyToAddresses'] = $this->stringifyAddresses($emails); } + if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) { + $request['ConfigurationSetName'] = $header->getBodyAsString(); + } return new SendEmailRequest($request); } diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php index 45ccd65cdf13f..b872be52c6195 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php @@ -90,10 +90,16 @@ private function getSignature(string $string): string private function getPayload(Email $email, Envelope $envelope): array { if ($email->getAttachments()) { - return [ + $payload = [ 'Action' => 'SendRawEmail', 'RawMessage.Data' => base64_encode($email->toString()), ]; + + if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) { + $payload['ConfigurationSetName'] = $header->getBodyAsString(); + } + + return $payload; } $payload = [ @@ -118,6 +124,9 @@ private function getPayload(Email $email, Envelope $envelope): array if ($email->getReplyTo()) { $payload['ReplyToAddresses.member'] = $this->stringifyAddresses($email->getReplyTo()); } + if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) { + $payload['ConfigurationSetName'] = $header->getBodyAsString(); + } return $payload; } diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpAsyncAwsTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpAsyncAwsTransport.php index 284e56b331a45..58ae25e792190 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpAsyncAwsTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpAsyncAwsTransport.php @@ -19,6 +19,7 @@ use Symfony\Component\Mailer\Exception\HttpTransportException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractTransport; +use Symfony\Component\Mime\Message; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** @@ -67,7 +68,7 @@ protected function doSend(SentMessage $message): void protected function getRequest(SentMessage $message): SendEmailRequest { - return new SendEmailRequest([ + $request = [ 'Destination' => new Destination([ 'ToAddresses' => $this->stringifyAddresses($message->getEnvelope()->getRecipients()), ]), @@ -76,6 +77,13 @@ protected function getRequest(SentMessage $message): SendEmailRequest 'Data' => $message->toString(), ], ], - ]); + ]; + + if (($message->getOriginalMessage() instanceof Message) + && $configurationSetHeader = $message->getOriginalMessage()->getHeaders()->get('X-SES-CONFIGURATION-SET')) { + $request['ConfigurationSetName'] = $configurationSetHeader->getBodyAsString(); + } + + return new SendEmailRequest($request); } } diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php index e3fefd4583a5e..20af6c519a3b9 100644 --- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php @@ -15,6 +15,7 @@ use Symfony\Component\Mailer\Exception\HttpTransportException; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Transport\AbstractHttpTransport; +use Symfony\Component\Mime\Message; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -54,7 +55,7 @@ protected function doSendHttp(SentMessage $message): ResponseInterface $date = gmdate('D, d M Y H:i:s e'); $auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date)); - $response = $this->client->request('POST', 'https://'.$this->getEndpoint(), [ + $request = [ 'headers' => [ 'X-Amzn-Authorization' => $auth, 'Date' => $date, @@ -63,7 +64,14 @@ protected function doSendHttp(SentMessage $message): ResponseInterface 'Action' => 'SendRawEmail', 'RawMessage.Data' => base64_encode($message->toString()), ], - ]); + ]; + + if (($message->getOriginalMessage() instanceof Message) + && $configurationSetHeader = $message->getOriginalMessage()->getHeaders()->get('X-SES-CONFIGURATION-SET')) { + $request['body']['ConfigurationSetName'] = $configurationSetHeader->getBodyAsString(); + } + + $response = $this->client->request('POST', 'https://'.$this->getEndpoint(), $request); $result = new \SimpleXMLElement($response->getContent(false)); if (200 !== $response->getStatusCode()) { 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