Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9ef1fd9

Browse files
committed
added the Mailer component
1 parent 162d5a8 commit 9ef1fd9

File tree

93 files changed

+4832
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+4832
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
use Symfony\Component\Lock\Store\FlockStore;
7575
use Symfony\Component\Lock\Store\StoreFactory;
7676
use Symfony\Component\Lock\StoreInterface;
77+
use Symfony\Component\Mailer\Transport;
7778
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
7879
use Symfony\Component\Messenger\MessageBus;
7980
use Symfony\Component\Messenger\MessageBusInterface;
@@ -336,6 +337,10 @@ public function load(array $configs, ContainerBuilder $container)
336337
$loader->load('mime_type.xml');
337338
}
338339

340+
if (class_exists(Mailer::class)) {
341+
$loader->load('mailer.xml');
342+
}
343+
339344
$container->registerForAutoconfiguration(Command::class)
340345
->addTag('console.command');
341346
$container->registerForAutoconfiguration(ResourceCheckerInterface::class)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<defaults public="false" />
9+
10+
<service id="mailer" class="Symfony\Component\Mailer\Mailer">
11+
<argument type="service" id="mailer.transport" />
12+
<argument type="service" id="message_bus" on-invalid="ignore" />
13+
</service>
14+
<service id="Symfony\Component\Mailer\MailerInterface" alias="mailer" />
15+
16+
<service id="mailer.transport" class="Symfony\Component\Mailer\Transport\TransportInterface">
17+
<factory class="Symfony\Component\Mailer\Transport" method="fromDsn" />
18+
<argument>%env(MAILER_DSN)%</argument>
19+
<argument type="service" id="event_dispatcher" />
20+
<argument type="service" id="http_client" on-invalid="ignore" />
21+
<argument type="service" id="logger" on-invalid="ignore" />
22+
</service>
23+
<service id="Symfony\Component\Mailer\Transport\TransportInterface" alias="mailer.transport" />
24+
25+
<service id="mailer.messenger.message_handler" class="Symfony\Component\Mailer\Messenger\MessageHandler">
26+
<argument type="service" id="mailer.transport" />
27+
<tag name="messenger.message_handler" />
28+
</service>
29+
</services>
30+
</container>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
4.3.0
5+
-----
6+
7+
* added the bridge
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Amazon\Http\Api;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16+
use Symfony\Component\Mailer\Exception\TransportException;
17+
use Symfony\Component\Mailer\SmtpEnvelope;
18+
use Symfony\Component\Mailer\Transport\Http\Api\AbstractApiTransport;
19+
use Symfony\Component\Mime\Email;
20+
use Symfony\Contracts\HttpClient\HttpClientInterface;
21+
22+
/**
23+
* @experimental in 4.3
24+
*/
25+
class SesTransport extends AbstractApiTransport
26+
{
27+
private const ENDPOINT = 'https://email.%region%.amazonaws.com';
28+
29+
private $accessKey;
30+
private $secretKey;
31+
private $region;
32+
33+
/**
34+
* @param string $region Amazon SES region (currently one of us-east-1, us-west-2, or eu-west-1)
35+
*/
36+
public function __construct(string $accessKey, string $secretKey, string $region = null, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
37+
{
38+
$this->accessKey = $accessKey;
39+
$this->secretKey = $secretKey;
40+
$this->region = $region ?: 'eu-west-1';
41+
42+
parent::__construct($client, $dispatcher, $logger);
43+
}
44+
45+
protected function doSendEmail(Email $email, SmtpEnvelope $envelope): void
46+
{
47+
$date = gmdate('D, d M Y H:i:s e');
48+
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
49+
50+
$endpoint = \str_replace('%region%', $this->region, self::ENDPOINT);
51+
$response = $this->client->request('POST', $endpoint, [
52+
'headers' => [
53+
'X-Amzn-Authorization' => $auth,
54+
'Date' => $date,
55+
'Content-Type' => 'application/x-www-form-urlencoded',
56+
],
57+
'body' => $this->getPayload($email, $envelope),
58+
]);
59+
60+
if (200 !== $response->getStatusCode()) {
61+
$error = new \SimpleXMLElement($response->getContent(false));
62+
63+
throw new TransportException(sprintf('Unable to send an email: %s (code %s).', $error->Error->Message, $error->Error->Code));
64+
}
65+
}
66+
67+
private function getSignature($string)
68+
{
69+
return base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
70+
}
71+
72+
private function getPayload(Email $email, SmtpEnvelope $envelope): array
73+
{
74+
if ($email->getAttachments()) {
75+
return [
76+
'Action' => 'SendRawEmail',
77+
'RawMessage.Data' => \base64_encode($email->toString()),
78+
];
79+
}
80+
81+
$payload = [
82+
'Action' => 'SendEmail',
83+
'Destination.ToAddresses.member' => $this->stringifyAddresses($this->getRecipients($email, $envelope)),
84+
'Message.Subject.Data' => $email->getSubject(),
85+
'Source' => $envelope->getSender()->toString(),
86+
];
87+
88+
if ($emails = $email->getCc()) {
89+
$payload['Destination.CcAddresses.member'] = $this->stringifyAddresses($emails);
90+
}
91+
if ($emails = $email->getBcc()) {
92+
$payload['Destination.BccAddresses.member'] = $this->stringifyAddresses($emails);
93+
}
94+
if ($email->getTextBody()) {
95+
$payload['Message.Body.Text.Data'] = $email->getTextBody();
96+
}
97+
if ($email->getHtmlBody()) {
98+
$payload['Message.Body.Html.Data'] = $email->getHtmlBody();
99+
}
100+
101+
return $payload;
102+
}
103+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Amazon\Http;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16+
use Symfony\Component\HttpClient\HttpClient;
17+
use Symfony\Component\Mailer\Exception\TransportException;
18+
use Symfony\Component\Mailer\SentMessage;
19+
use Symfony\Component\Mailer\Transport\AbstractTransport;
20+
use Symfony\Contracts\HttpClient\HttpClientInterface;
21+
22+
/**
23+
* @experimental in 4.3
24+
*/
25+
class SesTransport extends AbstractTransport
26+
{
27+
private const ENDPOINT = 'https://email.%region%.amazonaws.com';
28+
29+
private $client;
30+
private $accessKey;
31+
private $secretKey;
32+
private $region;
33+
34+
/**
35+
* @param string $region Amazon SES region (currently one of us-east-1, us-west-2, or eu-west-1)
36+
*/
37+
public function __construct(string $accessKey, string $secretKey, string $region = null, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
38+
{
39+
$this->client = $client ?? HttpClient::create();
40+
$this->accessKey = $accessKey;
41+
$this->secretKey = $secretKey;
42+
$this->region = $region ?: 'eu-west-1';
43+
44+
parent::__construct($dispatcher, $logger);
45+
}
46+
47+
protected function doSend(SentMessage $message): void
48+
{
49+
$date = gmdate('D, d M Y H:i:s e');
50+
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
51+
52+
$endpoint = \str_replace('%region%', $this->region, self::ENDPOINT);
53+
$response = $this->client->request('POST', $endpoint, [
54+
'headers' => [
55+
'X-Amzn-Authorization' => $auth,
56+
'Date' => $date,
57+
],
58+
'body' => [
59+
'Action' => 'SendRawEmail',
60+
'RawMessage.Data' => \base64_encode($message->toString()),
61+
],
62+
]);
63+
64+
if (200 !== $response->getStatusCode()) {
65+
$error = new \SimpleXMLElement($response->getContent(false));
66+
67+
throw new TransportException(sprintf('Unable to send an email: %s (code %s).', $error->Error->Message, $error->Error->Code));
68+
}
69+
}
70+
71+
private function getSignature($string): string
72+
{
73+
return base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
74+
}
75+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2019 Fabien Potencier
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Amazon Mailer
2+
=============
3+
4+
Provides Amazon SES integration for Symfony Mailer.
5+
6+
Resources
7+
---------
8+
9+
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
10+
* [Report issues](https://github.com/symfony/symfony/issues) and
11+
[send Pull Requests](https://github.com/symfony/symfony/pulls)
12+
in the [main Symfony repository](https://github.com/symfony/symfony)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Bridge\Amazon\Smtp;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16+
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
17+
18+
/**
19+
* @author Fabien Potencier <[email protected]>
20+
*
21+
* @experimental in 4.3
22+
*/
23+
class SesTransport extends EsmtpTransport
24+
{
25+
/**
26+
* @param string $region Amazon SES region (currently one of us-east-1, us-west-2, or eu-west-1)
27+
*/
28+
public function __construct(string $username, string $password, string $region = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null)
29+
{
30+
parent::__construct(\sprintf('email-smtp.%s.amazonaws.com', $region ?: 'eu-west-1'), 587, 'tls', null, $dispatcher, $logger);
31+
32+
$this->setUsername($username);
33+
$this->setPassword($password);
34+
}
35+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "symfony/amazon-mailer",
3+
"type": "symfony-bridge",
4+
"description": "Symfony Amazon Mailer Bridge",
5+
"keywords": [],
6+
"homepage": "https://symfony.com",
7+
"license": "MIT",
8+
"authors": [
9+
{
10+
"name": "Fabien Potencier",
11+
"email": "[email protected]"
12+
},
13+
{
14+
"name": "Symfony Community",
15+
"homepage": "https://symfony.com/contributors"
16+
}
17+
],
18+
"require": {
19+
"php": "^7.1.3",
20+
"symfony/mailer": "^4.3"
21+
},
22+
"require-dev": {
23+
"symfony/http-client": "^4.3"
24+
},
25+
"autoload": {
26+
"psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Amazon\\": "" },
27+
"exclude-from-classmap": [
28+
"/Tests/"
29+
]
30+
},
31+
"minimum-stability": "dev",
32+
"extra": {
33+
"branch-alias": {
34+
"dev-master": "4.3-dev"
35+
}
36+
}
37+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
5+
backupGlobals="false"
6+
colors="true"
7+
bootstrap="vendor/autoload.php"
8+
failOnRisky="true"
9+
failOnWarning="true"
10+
>
11+
<php>
12+
<ini name="error_reporting" value="-1" />
13+
</php>
14+
15+
<testsuites>
16+
<testsuite name="Symfony Amazon Mailer Test Suite">
17+
<directory>./Tests/</directory>
18+
</testsuite>
19+
</testsuites>
20+
21+
<filter>
22+
<whitelist>
23+
<directory>./</directory>
24+
<exclude>
25+
<directory>./Resources</directory>
26+
<directory>./Tests</directory>
27+
<directory>./vendor</directory>
28+
</exclude>
29+
</whitelist>
30+
</filter>
31+
</phpunit>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
4.3.0
5+
-----
6+
7+
* added the bridge

0 commit comments

Comments
 (0)