8000 [Mailer] Support Amazon SES ConfigurationSetName · symfony/symfony@6e6f9f2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6e6f9f2

Browse files
author
Clara van Miert
committed
[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 10000 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
1 parent a80dbc5 commit 6e6f9f2

8 files changed

+91
-5
lines changed

src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiAsyncAwsTransportTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public function testSend()
6868
$this->assertSame('Fabien <fabpot@symfony.com>', $content['FromEmailAddress']);
6969
$this->assertSame('Hello There!', $content['Content']['Simple']['Body']['Text']['Data']);
7070
$this->assertSame('<b>Hello There!</b>', $content['Content']['Simple']['Body']['Html']['Data']);
71+
$this->assertSame('aws-configuration-set-name', $content['ConfigurationSetName']);
7172

7273
$json = '{"MessageId": "foobar"}';
7374

@@ -85,6 +86,8 @@ public function testSend()
8586
->text('Hello There!')
8687
->html('<b>Hello There!</b>');
8788

89+
$mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name');
90+
8891
$message = $transport->send($mail);
8992

9093
$this->assertSame('foobar', $message->getMessageId());

src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesApiTransportTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public function testSend()
6868
$this->assertSame('Saif Eddin <saif.gmati@symfony.com>', $content['Destination_ToAddresses_member'][0]);
6969
$this->assertSame('Fabien <fabpot@symfony.com>', $content['Source']);
7070
$this->assertSame('Hello There!', $content['Message_Body_Text_Data']);
71+
$this->assertSame('aws-configuration-set-name', $content['ConfigurationSetName']);
7172

7273
$xml = '<SendEmailResponse xmlns="https://email.amazonaws.com/doc/2010-03-31/">
7374
<SendEmailResult>
@@ -88,6 +89,53 @@ public function testSend()
8889
->from(new Address('fabpot@symfony.com', 'Fabien'))
8990
->text('Hello There!');
9091

92+
$mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name');
93+
94+
$message = $transport->send($mail);
95+
96+
$this->assertSame('foobar', $message->getMessageId());
97+
}
98+
99+
public function testSendWithAttachments()
100+
{
101+
$client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface {
102+
$this->assertSame('POST', $method);
103+
$this->assertSame('https://email.eu-west-1.amazonaws.com:8984/', $url);
104+
$this->assertStringContainsStringIgnoringCase('X-Amzn-Authorization: AWS3-HTTPS AWSAccessKeyId=ACCESS_KEY,Algorithm=HmacSHA256,Signature=', $options['headers'][0] ?? $options['request_headers'][0]);
105+
106+
parse_str($options['body'], $body);
107+
$content = base64_decode($body['RawMessage_Data']);
108+
109+
$this->assertStringContainsString('Hello!', $content);
110+
$this->assertStringContainsString('Saif Eddin <saif.gmati@symfony.com>', $content);
111+
$this->assertStringContainsString('Fabien <fabpot@symfony.com>', $content);
112+
$this->assertStringContainsString('Hello There!', $content);
113+
$this->assertStringContainsString(base64_encode('attached data'), $content);
114+
115+
$this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']);
116+
117+
$xml = '<SendEmailResponse xmlns="https://email.amazonaws.com/doc/2010-03-31/">
118+
<SendRawEmailResult>
119+
<MessageId>foobar</MessageId>
120+
</SendRawEmailResult>
121+
</SendEmailResponse>';
122+
123+
return new MockResponse($xml, [
124+
'http_code' => 200,
125+
]);
126+
});
127+
$transport = new SesApiTransport('ACCESS_KEY', 'SECRET_KEY', null, $client);
128+
$transport->setPort(8984);
129+
130+
$mail = new Email();
131+
$mail->subject('Hello!')
132+
->to(new Address('saif.gmati@symfony.com', 'Saif Eddin'))
133+
->from(new Address('fabpot@symfony.com', 'Fabien'))
134+
->text('Hello There!')
135+
->attach('attached data');
136+
137+
$mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name');
138+
91139
$message = $transport->send($mail);
92140

93141
$this->assertSame('foobar', $message->getMessageId());

src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpAsyncAwsTransportTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public function testSend()
6868
$this->assertStringContainsString('Saif Eddin <saif.gmati@symfony.com>', $content);
6969
$this->assertStringContainsString('Fabien <fabpot@symfony.com>', $content);
7070
$this->assertStringContainsString('Hello There!', $content);
71+
$this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']);
7172

7273
$json = '{"MessageId": "foobar"}';
7374

@@ -84,6 +85,8 @@ public function testSend()
8485
->from(new Address('fabpot@symfony.com', 'Fabien'))
8586
->text('Hello There!');
8687

88+
$mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name');
89+
8790
$message = $transport->send($mail);
8891

8992
$this->assertSame('foobar', $message->getMessageId());

src/Symfony/Component/Mailer/Bridge/Amazon/Tests/Transport/SesHttpTransportTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public function testSend()
7070
$this->assertStringContainsString('Fabien <fabpot@symfony.com>', $content);
7171
$this->assertStringContainsString('Hello There!', $content);
7272

73+
$this->assertSame('aws-configuration-set-name', $body['ConfigurationSetName']);
74+
7375
$xml = '<SendEmailResponse xmlns="https://email.amazonaws.com/doc/2010-03-31/">
7476
<SendRawEmailResult>
7577
<MessageId>foobar</MessageId>
@@ -89,6 +91,8 @@ public function testSend()
8991
->from(new Address('fabpot@symfony.com', 'Fabien'))
9092
->text('Hello There!');
9193

94+
$mail->getHeaders()->addTextHeader('X-SES-CONFIGURATION-SET', 'aws-configuration-set-name');
95+
9296
$message = $transport->send($mail);
9397

9498
$this->assertSame('foobar', $message->getMessageId());

src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiAsyncAwsTransport.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ protected function getRequest(SentMessage $message): SendEmailRequest
8686
'Charset' => $email->getHtmlCharset(),
8787
]);
8888
}
89+
if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) {
90+
$request['ConfigurationSetName'] = $header->getBodyAsString();
91+
}
8992

9093
return new SendEmailRequest($request);
9194
}

src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,16 @@ private function getSignature(string $string): string
9090
private function getPayload(Email $email, Envelope $envelope): array
9191
{
9292
if ($email->getAttachments()) {
93-
return [
93+
$payload = [
9494
'Action' => 'SendRawEmail',
9595
'RawMessage.Data' => base64_encode($email->toString()),
9696
];
97+
98+
if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) {
99+
$payload['ConfigurationSetName'] = $header->getBodyAsString();
100+
}
101+
102+
return $payload;
97103
}
98104

99105
$payload = [
@@ -118,6 +124,9 @@ private function getPayload(Email $email, Envelope $envelope): array
118124
if ($email->getReplyTo()) {
119125
$payload['ReplyToAddresses.member'] = $this->stringifyAddresses($email->getReplyTo());
120126
}
127+
if ($header = $email->getHeaders()->get('X-SES-CONFIGURATION-SET')) {
128+
$payload['ConfigurationSetName'] = $header->getBodyAsString();
129+
}
121130

122131
return $payload;
123132
}

src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpAsyncAwsTransport.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Mailer\Exception\HttpTransportException;
2020
use Symfony\Component\Mailer\SentMessage;
2121
use Symfony\Component\Mailer\Transport\AbstractTransport;
22+
use Symfony\Component\Mime\Message;
2223
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
2324

2425
/**
@@ -67,7 +68,7 @@ protected function doSend(SentMessage $message): void
6768

6869
protected function getRequest(SentMessage $message): SendEmailRequest
6970
{
70-
return new SendEmailRequest([
71+
$request = [
7172
'Destination' => $destination = new Destination([
7273
'ToAddresses' => $this->stringifyAddresses($message->getEnvelope()->getRecipients()),
7374
]),
@@ -76,6 +77,13 @@ protected function getRequest(SentMessage $message): SendEmailRequest
7677
'Data' => $message->toString(),
7778
],
7879
],
79-
]);
80+
];
81+
82+
if (($message->getOriginalMessage() instanceof Message)
83+
&& $configurationSetHeader = $message->getOriginalMessage()->getHeaders()->get('X-SES-CONFIGURATION-SET')) {
84+
$request['ConfigurationSetName'] = $configurationSetHeader->getBodyAsString();
85+
}
86+
87+
return new SendEmailRequest($request);
8088
}
8189
}

src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Mailer\Exception\HttpTransportException;
1616
use Symfony\Component\Mailer\SentMessage;
1717
use Symfony\Component\Mailer\Transport\AbstractHttpTransport;
18+
use Symfony\Component\Mime\Message;
1819
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
1920
use Symfony\Contracts\HttpClient\HttpClientInterface;
2021
use Symfony\Contracts\HttpClient\ResponseInterface;
@@ -54,7 +55,7 @@ protected function doSendHttp(SentMessage $message): ResponseInterface
5455
$date = gmdate('D, d M Y H:i:s e');
5556
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
5657

57-
$response = $this->client->request('POST', 'https://'.$this->getEndpoint(), [
58+
$request = [
5859
'headers' => [
5960
'X-Amzn-Authorization' => $auth,
6061
'Date' => $date,
@@ -63,7 +64,14 @@ protected function doSendHttp(SentMessage $message): ResponseInterface
6364
'Action' => 'SendRawEmail',
6465
'RawMessage.Data' => base64_encode($message->toString()),
6566
],
66-
]);
67+
];
68+
69+
if (($message->getOriginalMessage() instanceof Message)
70+
&& $configurationSetHeader = $message->getOriginalMessage()->getHeaders()->get('X-SES-CONFIGURATION-SET')) {
71+
$request['body']['ConfigurationSetName'] = $configurationSetHeader->getBodyAsString();
72+
}
73+
74+
$response = $this->client->request('POST', 'https://'.$this->getEndpoint(), $request);
6775

6876
$result = new \SimpleXMLElement($response->getContent(false));
6977
if (200 !== $response->getStatusCode()) {

0 commit comments

Comments
 (0)
0