From 97264a924a41c5421a887ba2092d727b1d418eac Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Tue, 24 Aug 2021 16:40:14 +0100 Subject: [PATCH 01/13] [Mailer] Added OhMySMTP Bridge This commit adds the https://ohmysmtp.com bridge to enable sending over the OhMySMTP API. --- .../FrameworkExtension.php | 2 + .../Resources/config/mailer_transports.php | 5 + .../Mailer/Bridge/Ohmysmtp/.gitattributes | 4 + .../Mailer/Bridge/Ohmysmtp/.gitignore | 3 + .../Mailer/Bridge/Ohmysmtp/CHANGELOG.md | 7 + .../Component/Mailer/Bridge/Ohmysmtp/LICENSE | 19 +++ .../Mailer/Bridge/Ohmysmtp/README.md | 12 ++ .../Transport/OhmysmtpApiTransportTest.php | 143 ++++++++++++++++++ .../Transport/OhmysmtpSmtpTransportTest.php | 51 +++++++ .../OhmysmtpTransportFactoryTest.php | 99 ++++++++++++ .../Transport/OhmysmtpApiTransport.php | 142 +++++++++++++++++ .../Transport/OhmysmtpSmtpTransport.php | 63 ++++++++ .../Transport/OhmysmtpTransportFactory.php | 47 ++++++ .../Mailer/Bridge/Ohmysmtp/composer.json | 33 ++++ .../Mailer/Bridge/Ohmysmtp/phpunit.xml.dist | 31 ++++ .../Exception/UnsupportedSchemeException.php | 4 + .../UnsupportedSchemeExceptionTest.php | 3 + src/Symfony/Component/Mailer/Transport.php | 2 + 18 files changed, 670 insertions(+) create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json create mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 44c37e270946a..5f887476b19cc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -93,6 +93,7 @@ use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mercure\HubRegistry; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; @@ -2354,6 +2355,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', SesTransportFactory::class => 'mailer.transport_factory.amazon', + OhmysmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', ]; foreach ($classToServices as $class => $service) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php index 9c330ab2c7333..0313772779bda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -19,6 +19,7 @@ use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\NativeTransportFactory; use Symfony\Component\Mailer\Transport\NullTransportFactory; @@ -76,6 +77,10 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') + ->set('mailer.transport_factory.ohmysmtp', OhmysmtpTransportFactory::class) + ->parent('mailer.transport_factory.abstract') + ->tag('mailer.transport_factory') + ->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory', ['priority' => -100]) diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes new file mode 100644 index 0000000000000..84c7add058fb5 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes @@ -0,0 +1,4 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore new file mode 100644 index 0000000000000..c49a5d8df5c65 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md new file mode 100644 index 0000000000000..0e281bb45bad9 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +5.4.0 +----- + + * Added the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE new file mode 100644 index 0000000000000..383e7a54586e7 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019-2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md new file mode 100644 index 0000000000000..854ccfea6b6b6 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md @@ -0,0 +1,12 @@ +OhMySMTP Bridge +=============== + +Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php new file mode 100644 index 0000000000000..50d66dddbab44 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpApiTransport; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\ResponseInterface; + +class OhmysmtpApiTransportTest extends TestCase +{ + /** + * @dataProvider getTransportData + */ + public function testToString(OhmysmtpApiTransport $transport, string $expected) + { + $this->assertSame($expected, (string) $transport); + } + + public function getTransportData() + { + return [ + [ + new OhmysmtpApiTransport('KEY'), + 'ohmysmtp+api://app.ohmysmtp.com/api/v1', + ], + [ + (new OhmysmtpApiTransport('KEY'))->setHost('example.com'), + 'ohmysmtp+api://example.com', + ], + [ + (new OhmysmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), + 'ohmysmtp+api://example.com:99', + ], + ]; + } + + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhmysmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhmysmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('Headers', $payload); + $this->assertCount(1, $payload['Headers']); + + $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); + } + + public function testSend() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); + $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); + + $body = json_decode($options['body'], true); + $this->assertSame('"Fabien" ', $body['from']); + $this->assertSame('"Saif Eddin" ', $body['to']); + $this->assertSame('Hello!', $body['subject']); + $this->assertSame('Hello There!', $body['textbody']); + + return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ + 'http_code' => 200, + ]); + }); + + $transport = new OhmysmtpApiTransport('KEY', $client); + + $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!'); + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } + + public function testSendThrowsForErrorResponse() + { + $client = new MockHttpClient(static function (string $method, string $url, array $options): ResponseInterface { + return new MockResponse(json_encode(['Message' => 'i\'m a teapot', 'ErrorCode' => 418]), [ + 'http_code' => 418, + 'response_headers' => [ + 'content-type' => 'application/json', + ], + ]); + }); + $transport = new OhmysmtpApiTransport('KEY', $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!'); + + $this->expectException(HttpTransportException::class); + $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).'); + $transport->send($mail); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhmysmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhmysmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayNotHasKey('Headers', $payload); + $this->assertArrayHasKey('tags', $payload); + + $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php new file mode 100644 index 0000000000000..57a2de70f1fb9 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpSmtpTransport; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Email; + +class OhmysmtpSmtpTransportTest extends TestCase +{ + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + + $transport = new OhmysmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhmysmtpSmtpTransport::class, 'addOhmysmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(1, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $transport = new OhmysmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhmysmtpSmtpTransport::class, 'addOhmysmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(2, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php new file mode 100644 index 0000000000000..5936d874c97ef --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; + +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpApiTransport; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpSmtpTransport; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Test\TransportFactoryTestCase; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportFactoryInterface; + +class OhmysmtpTransportFactoryTest extends TransportFactoryTestCase +{ + public function getFactory(): TransportFactoryInterface + { + return new OhmysmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + } + + public function supportsProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+api', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'example.com'), + true, + ]; + } + + public function createProvider(): iterable + { + $dispatcher = $this->getDispatcher(); + $logger = $this->getLogger(); + + yield [ + new Dsn('ohmysmtp+api', 'default', self::USER), + new OhmysmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), + (new OhmysmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), + ]; + + yield [ + new Dsn('ohmysmtp', 'default', self::USER), + new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default', self::USER), + new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default', self::USER), + new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + } + + public function unsupportedSchemeProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+foo', 'default', self::USER), + 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', + ]; + } + + public function incompleteDsnProvider(): iterable + { + yield [new Dsn('ohmysmtp+api', 'default')]; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php new file mode 100644 index 0000000000000..fe5b3e99a1340 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\AbstractApiTransport; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Paul Oms + */ +class OhmysmtpApiTransport extends AbstractApiTransport +{ + private const HOST = 'app.ohmysmtp.com/api/v1'; + + private $key; + + public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + $this->key = $key; + + parent::__construct($client, $dispatcher, $logger); + } + + public function __toString(): string + { + return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); + } + + protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface + { + $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ + 'headers' => [ + 'Accept' => 'application/json', + 'OhMySMTP-Server-Token' => $this->key, + 'Content-Type' => 'application/json', + 'User-Agent' => "OhMySMTP Symfony Mailer", + ], + 'json' => $this->getPayload($email, $envelope), + ]); + + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (DecodingExceptionInterface $e) { + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); + } + + if (200 !== $statusCode) { + throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); + } + + $sentMessage->setMessageId($result['id']); + + return $response; + } + + private function getPayload(Email $email, Envelope $envelope): array + { + $payload = [ + 'from' => $envelope->getSender()->toString(), + 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), + 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), + 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), + 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), + 'subject' => $email->getSubject(), + 'textbody' => $email->getTextBody(), + 'htmlbody' => $email->getHtmlBody(), + 'attachments' => $this->getAttachments($email), + 'tags' => [] + ]; + + $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; + + foreach ($email->getHeaders()->all() as $name => $header) { + if (\in_array($name, $headersToBypass, true)) { + continue; + } + + if ($header instanceof TagHeader) { + array_push($payload['tags'], $header->getValue()); + continue; + } + + $payload['Headers'][] = [ + 'Name' => $name, + 'Value' => $header->getBodyAsString(), + ]; + } + + return $payload; + } + + private function getAttachments(Email $email): array + { + $attachments = []; + foreach ($email->getAttachments() as $attachment) { + $headers = $attachment->getPreparedHeaders(); + $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $disposition = $headers->getHeaderBody('Content-Disposition'); + + $att = [ + 'name' => $filename, + 'content' => $attachment->bodyToString(), + 'content_type' => $headers->get('Content-Type')->getBody(), + ]; + + if ('inline' === $disposition) { + $att['cid'] = 'cid:'.$filename; + } + + $attachments[] = $att; + } + + return $attachments; + } + + private function getEndpoint(): ?string + { + return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php new file mode 100644 index 0000000000000..c35b1f009c29c --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @author Paul Oms + */ +class OhmysmtpSmtpTransport extends EsmtpTransport +{ + public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); + + $this->setUsername($id); + $this->setPassword($id); + } + + public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage + { + if ($message instanceof Message) { + $this->addOhmysmtpHeaders($message); + } + + return parent::send($message, $envelope); + } + + private function addOhmysmtpHeaders(Message $message): void + { + $headers = $message->getHeaders(); + + foreach ($headers->all() as $name => $header) { + if ($header instanceof TagHeader) { + if ($headers->get('X-OMS-Tags') != null) { + $existing = $headers->get('X-OMS-Tags')->getBody(); + $headers->remove('X-OMS-Tags'); + $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); + } else{ + $headers->addTextHeader('X-OMS-Tags', $header->getValue()); + } + $headers->remove($name); + } + } + } +} + diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php new file mode 100644 index 0000000000000..b3680a517aad8 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; + +use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; +use Symfony\Component\Mailer\Transport\AbstractTransportFactory; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportInterface; + +/** + * @author Paul Oms + */ +final class OhmysmtpTransportFactory extends AbstractTransportFactory +{ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + $user = $this->getUser($dsn); + + if ('ohmysmtp+api' === $scheme) { + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); + + return (new OhmysmtpApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); + } + + if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { + return new OhmysmtpSmtpTransport($user, $this->dispatcher, $this->logger); + } + + throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json new file mode 100644 index 0000000000000..056e8d96a4f8b --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/ohmysmtp-mailer", + "type": "symfony-bridge", + "description": "Symfony OhMySMTP Mailer Bridge", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1", + "symfony/mailer": "^5.3.0|^6.0" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Ohmysmtp\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist new file mode 100644 index 0000000000000..706e4cf3c1339 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + diff --git a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php index 3e1660cae1075..e6755ca72ac6c 100644 --- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php @@ -52,6 +52,10 @@ class UnsupportedSchemeException extends LogicException 'class' => Bridge\Amazon\Transport\SesTransportFactory::class, 'package' => 'symfony/amazon-mailer', ], + 'ohmysmtp' => [ + 'class' => Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory::class, + 'package' => 'symfony/ohmysmtp-mailer', + ], ]; public function __construct(Dsn $dsn, string $name = null, array $supported = []) diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index a3cb6351e96f9..85ecaeb65490b 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -21,6 +21,7 @@ use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Dsn; @@ -40,6 +41,7 @@ public static function setUpBeforeClass(): void PostmarkTransportFactory::class => false, SendgridTransportFactory::class => false, SendinblueTransportFactory::class => false, + OhmysmtpTransportFactory::class => false, SesTransportFactory::class => false, ]); } @@ -66,6 +68,7 @@ public function messageWhereSchemeIsPartOfSchemeToPackageMapProvider(): \Generat yield ['postmark', 'symfony/postmark-mailer']; yield ['sendgrid', 'symfony/sendgrid-mailer']; yield ['sendinblue', 'symfony/sendinblue-mailer']; + yield ['ohmysmtp', 'symfony/ohmysmtp-mailer']; yield ['ses', 'symfony/amazon-mailer']; } diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index a57225ed2f65e..8d32faa47c122 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -21,6 +21,7 @@ use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Dsn; @@ -51,6 +52,7 @@ class Transport PostmarkTransportFactory::class, SendgridTransportFactory::class, SendinblueTransportFactory::class, + OhmysmtpTransportFactory::class, SesTransportFactory::class, ]; From 11c21e5ec853a07a9b6faddc9835a228bc4aa507 Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Tue, 24 Aug 2021 17:00:19 +0100 Subject: [PATCH 02/13] This commit fixes the Fabbot coding standard issues --- .../DependencyInjection/FrameworkExtension.php | 2 +- .../FrameworkBundle/Resources/config/mailer_transports.php | 2 +- .../Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php | 6 +++--- .../Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php | 5 ++--- .../Tests/Exception/UnsupportedSchemeExceptionTest.php | 2 +- src/Symfony/Component/Mailer/Transport.php | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 5f887476b19cc..e6c60dec079ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -90,10 +90,10 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Mailer; use Symfony\Component\Mercure\HubRegistry; use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php index 0313772779bda..b3c8a7230d4f1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -16,10 +16,10 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; use Symfony\Component\Mailer\Transport\NativeTransportFactory; use Symfony\Component\Mailer\Transport\NullTransportFactory; diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php index fe5b3e99a1340..cf66e78ace8e2 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php @@ -52,7 +52,7 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e 'Accept' => 'application/json', 'OhMySMTP-Server-Token' => $this->key, 'Content-Type' => 'application/json', - 'User-Agent' => "OhMySMTP Symfony Mailer", + 'User-Agent' => 'OhMySMTP Symfony Mailer', ], 'json' => $this->getPayload($email, $envelope), ]); @@ -87,7 +87,7 @@ private function getPayload(Email $email, Envelope $envelope): array 'textbody' => $email->getTextBody(), 'htmlbody' => $email->getHtmlBody(), 'attachments' => $this->getAttachments($email), - 'tags' => [] + 'tags' => [], ]; $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; @@ -98,7 +98,7 @@ private function getPayload(Email $email, Envelope $envelope): array } if ($header instanceof TagHeader) { - array_push($payload['tags'], $header->getValue()); + $payload['tags'][] = $header->getValue(); continue; } diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php index c35b1f009c29c..10e2a7da05a3d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php @@ -48,11 +48,11 @@ private function addOhmysmtpHeaders(Message $message): void foreach ($headers->all() as $name => $header) { if ($header instanceof TagHeader) { - if ($headers->get('X-OMS-Tags') != null) { + if (null != $headers->get('X-OMS-Tags')) { $existing = $headers->get('X-OMS-Tags')->getBody(); $headers->remove('X-OMS-Tags'); $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); - } else{ + } else { $headers->addTextHeader('X-OMS-Tags', $header->getValue()); } $headers->remove($name); @@ -60,4 +60,3 @@ private function addOhmysmtpHeaders(Message $message): void } } } - diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index 85ecaeb65490b..11713d8127c41 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -18,10 +18,10 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Dsn; diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index 8d32faa47c122..cdf8fef62dc56 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -18,10 +18,10 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; +use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; use Symfony\Component\Mailer\Exception\InvalidArgumentException; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\Dsn; From d376a5e626b87a8b883344ee2e626b3f7fa57a15 Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Tue, 24 Aug 2021 17:38:20 +0100 Subject: [PATCH 03/13] Fix license year --- src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE index 383e7a54586e7..efb17f98e7dd3 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2019-2021 Fabien Potencier +Copyright (c) 2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From b2bffb2326de720912dcdac5ae5c078e35f1f01d Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 16:17:38 +0100 Subject: [PATCH 04/13] Rename Ohmysmtp to OhMySmtp, add DSN example and Author --- .../FrameworkExtension.php | 4 +-- .../Resources/config/mailer_transports.php | 4 +-- .../Mailer/Bridge/Ohmysmtp/CHANGELOG.md | 4 +-- .../Mailer/Bridge/Ohmysmtp/README.md | 12 ++++++++ .../Transport/OhmysmtpApiTransportTest.php | 28 +++++++++---------- .../Transport/OhmysmtpSmtpTransportTest.php | 14 +++++----- .../OhmysmtpTransportFactoryTest.php | 22 +++++++-------- .../Transport/OhmysmtpApiTransport.php | 4 +-- .../Transport/OhmysmtpSmtpTransport.php | 8 +++--- .../Transport/OhmysmtpTransportFactory.php | 8 +++--- .../Mailer/Bridge/Ohmysmtp/composer.json | 6 +++- .../Exception/UnsupportedSchemeException.php | 2 +- .../UnsupportedSchemeExceptionTest.php | 4 +-- src/Symfony/Component/Mailer/Transport.php | 4 +-- 14 files changed, 70 insertions(+), 54 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index e6c60dec079ab..59cbecf8afc16 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -90,7 +90,7 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -2355,7 +2355,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', SendinblueTransportFactory::class => 'mailer.transport_factory.sendinblue', SesTransportFactory::class => 'mailer.transport_factory.amazon', - OhmysmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', + OhMySmtpTransportFactory::class => 'mailer.transport_factory.ohmysmtp', ]; foreach ($classToServices as $class => $service) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php index b3c8a7230d4f1..7bddfa7567cee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -16,7 +16,7 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -77,7 +77,7 @@ ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') - ->set('mailer.transport_factory.ohmysmtp', OhmysmtpTransportFactory::class) + ->set('mailer.transport_factory.ohmysmtp', OhMySmtpTransportFactory::class) ->parent('mailer.transport_factory.abstract') ->tag('mailer.transport_factory') diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md index 0e281bb45bad9..37308ee9aead6 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -5.4.0 +5.4 ----- - * Added the bridge + * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md index 854ccfea6b6b6..fdeeb9f8a7727 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md @@ -3,6 +3,18 @@ OhMySMTP Bridge Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. + +DSN example +----------- + +``` +MAILER_DSN=ohmysmtp+api://API_TOKEN@default +``` + +where: + - `API_TOKEN` is your OhMySMTP API Token + + Resources --------- diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php index 50d66dddbab44..341260f4a45c3 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpApiTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\HttpTransportException; use Symfony\Component\Mailer\Header\TagHeader; @@ -22,12 +22,12 @@ use Symfony\Component\Mime\Email; use Symfony\Contracts\HttpClient\ResponseInterface; -class OhmysmtpApiTransportTest extends TestCase +class OhMySmtpApiTransportTest extends TestCase { /** * @dataProvider getTransportData */ - public function testToString(OhmysmtpApiTransport $transport, string $expected) + public function testToString(OhMySmtpApiTransport $transport, string $expected) { $this->assertSame($expected, (string) $transport); } @@ -36,15 +36,15 @@ public function getTransportData() { return [ [ - new OhmysmtpApiTransport('KEY'), + new OhMySmtpApiTransport('KEY'), 'ohmysmtp+api://app.ohmysmtp.com/api/v1', ], [ - (new OhmysmtpApiTransport('KEY'))->setHost('example.com'), + (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), 'ohmysmtp+api://example.com', ], [ - (new OhmysmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), + (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), 'ohmysmtp+api://example.com:99', ], ]; @@ -56,8 +56,8 @@ public function testCustomHeader() $email->getHeaders()->addTextHeader('foo', 'bar'); $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - $transport = new OhmysmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhmysmtpApiTransport::class, 'getPayload'); + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); $method->setAccessible(true); $payload = $method->invoke($transport, $email, $envelope); @@ -72,7 +72,7 @@ public function testSend() $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { $this->assertSame('POST', $method); $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); - $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); + $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][0] ?? $options['request_headers'][0]); $body = json_decode($options['body'], true); $this->assertSame('"Fabien" ', $body['from']); @@ -85,7 +85,7 @@ public function testSend() ]); }); - $transport = new OhmysmtpApiTransport('KEY', $client); + $transport = new OhMySmtpApiTransport('KEY', $client); $mail = new Email(); $mail->subject('Hello!') @@ -108,7 +108,7 @@ public function testSendThrowsForErrorResponse() ], ]); }); - $transport = new OhmysmtpApiTransport('KEY', $client); + $transport = new OhMySmtpApiTransport('KEY', $client); $transport->setPort(8984); $mail = new Email(); @@ -130,8 +130,8 @@ public function testTagAndMetadataHeaders() $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - $transport = new OhmysmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhmysmtpApiTransport::class, 'getPayload'); + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); $method->setAccessible(true); $payload = $method->invoke($transport, $email, $envelope); diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php index 57a2de70f1fb9..15def04559b99 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php @@ -9,22 +9,22 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpSmtpTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; use Symfony\Component\Mailer\Header\TagHeader; use Symfony\Component\Mime\Email; -class OhmysmtpSmtpTransportTest extends TestCase +class OhMySmtpSmtpTransportTest extends TestCase { public function testCustomHeader() { $email = new Email(); $email->getHeaders()->addTextHeader('foo', 'bar'); - $transport = new OhmysmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhmysmtpSmtpTransport::class, 'addOhmysmtpHeaders'); + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); $method->setAccessible(true); $method->invoke($transport, $email); @@ -39,8 +39,8 @@ public function testTagAndMetadataHeaders() $email->getHeaders()->add(new TagHeader('password-reset')); $email->getHeaders()->add(new TagHeader('2nd-tag')); - $transport = new OhmysmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhmysmtpSmtpTransport::class, 'addOhmysmtpHeaders'); + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); $method->setAccessible(true); $method->invoke($transport, $email); diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php index 5936d874c97ef..2d8a3073828e3 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php @@ -9,20 +9,20 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Tests\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpApiTransport; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpSmtpTransport; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Test\TransportFactoryTestCase; use Symfony\Component\Mailer\Transport\Dsn; use Symfony\Component\Mailer\Transport\TransportFactoryInterface; -class OhmysmtpTransportFactoryTest extends TransportFactoryTestCase +class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase { public function getFactory(): TransportFactoryInterface { - return new OhmysmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + return new OhMySmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); } public function supportsProvider(): iterable @@ -60,27 +60,27 @@ public function createProvider(): iterable yield [ new Dsn('ohmysmtp+api', 'default', self::USER), - new OhmysmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), + new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), ]; yield [ new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), - (new OhmysmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), + (new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), ]; yield [ new Dsn('ohmysmtp', 'default', self::USER), - new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), ]; yield [ new Dsn('ohmysmtp+smtp', 'default', self::USER), - new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), ]; yield [ new Dsn('ohmysmtp+smtps', 'default', self::USER), - new OhmysmtpSmtpTransport(self::USER, $dispatcher, $logger), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), ]; } diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php index cf66e78ace8e2..d0775b7fab68d 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; @@ -27,7 +27,7 @@ /** * @author Paul Oms */ -class OhmysmtpApiTransport extends AbstractApiTransport +class OhMySmtpApiTransport extends AbstractApiTransport { private const HOST = 'app.ohmysmtp.com/api/v1'; diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php index 10e2a7da05a3d..9d23baeae5724 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; @@ -23,7 +23,7 @@ /** * @author Paul Oms */ -class OhmysmtpSmtpTransport extends EsmtpTransport +class OhMySmtpSmtpTransport extends EsmtpTransport { public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { @@ -36,13 +36,13 @@ public function __construct(string $id, EventDispatcherInterface $dispatcher = n public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { if ($message instanceof Message) { - $this->addOhmysmtpHeaders($message); + $this->addOhMySmtpHeaders($message); } return parent::send($message, $envelope); } - private function addOhmysmtpHeaders(Message $message): void + private function addOhMySmtpHeaders(Message $message): void { $headers = $message->getHeaders(); diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php index b3680a517aad8..b14c5998cd2d8 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport; +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; @@ -19,7 +19,7 @@ /** * @author Paul Oms */ -final class OhmysmtpTransportFactory extends AbstractTransportFactory +final class OhMySmtpTransportFactory extends AbstractTransportFactory { public function create(Dsn $dsn): TransportInterface { @@ -30,11 +30,11 @@ public function create(Dsn $dsn): TransportInterface $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - return (new OhmysmtpApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); + return (new OhMySmtpApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); } if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { - return new OhmysmtpSmtpTransport($user, $this->dispatcher, $this->logger); + return new OhMySmtpSmtpTransport($user, $this->dispatcher, $this->logger); } throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json index 056e8d96a4f8b..561dba7e405f0 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json @@ -13,6 +13,10 @@ { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Paul Oms", + "homepage": "https://ohmysmtp.com" } ], "require": { @@ -24,7 +28,7 @@ "symfony/http-client": "^4.4|^5.0|^6.0" }, "autoload": { - "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Ohmysmtp\\": "" }, + "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, "exclude-from-classmap": [ "/Tests/" ] diff --git a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php index e6755ca72ac6c..50d6346873207 100644 --- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php @@ -53,7 +53,7 @@ class UnsupportedSchemeException extends LogicException 'package' => 'symfony/amazon-mailer', ], 'ohmysmtp' => [ - 'class' => Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory::class, + 'class' => Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class, 'package' => 'symfony/ohmysmtp-mailer', ], ]; diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index 11713d8127c41..68b34f871b2e4 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -18,7 +18,7 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -41,7 +41,7 @@ public static function setUpBeforeClass(): void PostmarkTransportFactory::class => false, SendgridTransportFactory::class => false, SendinblueTransportFactory::class => false, - OhmysmtpTransportFactory::class => false, + OhMySmtpTransportFactory::class => false, SesTransportFactory::class => false, ]); } diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index cdf8fef62dc56..3334b4068e553 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -18,7 +18,7 @@ use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; -use Symfony\Component\Mailer\Bridge\Ohmysmtp\Transport\OhmysmtpTransportFactory; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory; @@ -52,7 +52,7 @@ class Transport PostmarkTransportFactory::class, SendgridTransportFactory::class, SendinblueTransportFactory::class, - OhmysmtpTransportFactory::class, + OhMySmtpTransportFactory::class, SesTransportFactory::class, ]; From 570f27fb3f798d91aba0aabe9f67e32b3338e7da Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 19:30:30 +0100 Subject: [PATCH 05/13] Fix breaking test and move getUser after scheme check --- .../Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php | 2 +- .../Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php index 341260f4a45c3..48960f4704adf 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php @@ -72,7 +72,7 @@ public function testSend() $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { $this->assertSame('POST', $method); $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); - $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][0] ?? $options['request_headers'][0]); + $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); $body = json_decode($options['body'], true); $this->assertSame('"Fabien" ', $body['from']); diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php index b14c5998cd2d8..79103815b0c25 100644 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php +++ b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php @@ -24,17 +24,16 @@ final class OhMySmtpTransportFactory extends AbstractTransportFactory public function create(Dsn $dsn): TransportInterface { $scheme = $dsn->getScheme(); - $user = $this->getUser($dsn); if ('ohmysmtp+api' === $scheme) { $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); $port = $dsn->getPort(); - return (new OhMySmtpApiTransport($user, $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); + return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); } if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { - return new OhMySmtpSmtpTransport($user, $this->dispatcher, $this->logger); + return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); } throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); From 01b9e826d6ec041728b192a2679c2177c159fb09 Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:15:45 +0100 Subject: [PATCH 06/13] Change directory case to match class names --- .../Mailer/Bridge/OhMySmtp/.gitattributes | 4 + .../Mailer/Bridge/OhMySmtp/.gitignore | 3 + .../Mailer/Bridge/OhMySmtp/CHANGELOG.md | 7 + .../Component/Mailer/Bridge/OhMySmtp/LICENSE | 19 +++ .../Mailer/Bridge/OhMySmtp/README.md | 24 +++ .../Transport/OhMySmtpApiTransportTest.php | 143 ++++++++++++++++++ .../Transport/OhMySmtpSmtpTransportTest.php | 51 +++++++ .../OhMySmtpTransportFactoryTest.php | 99 ++++++++++++ .../Transport/OhMySmtpApiTransport.php | 142 +++++++++++++++++ .../Transport/OhMySmtpSmtpTransport.php | 62 ++++++++ .../Transport/OhMySmtpTransportFactory.php | 46 ++++++ .../Mailer/Bridge/OhMySmtp/composer.json | 37 +++++ .../Mailer/Bridge/OhMySmtp/phpunit.xml.dist | 31 ++++ 13 files changed, 668 insertions(+) create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes new file mode 100644 index 0000000000000..84c7add058fb5 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes @@ -0,0 +1,4 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore new file mode 100644 index 0000000000000..c49a5d8df5c65 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md new file mode 100644 index 0000000000000..37308ee9aead6 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +5.4 +----- + + * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE new file mode 100644 index 0000000000000..efb17f98e7dd3 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md new file mode 100644 index 0000000000000..fdeeb9f8a7727 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md @@ -0,0 +1,24 @@ +OhMySMTP Bridge +=============== + +Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. + + +DSN example +----------- + +``` +MAILER_DSN=ohmysmtp+api://API_TOKEN@default +``` + +where: + - `API_TOKEN` is your OhMySMTP API Token + + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php new file mode 100644 index 0000000000000..48960f4704adf --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\ResponseInterface; + +class OhMySmtpApiTransportTest extends TestCase +{ + /** + * @dataProvider getTransportData + */ + public function testToString(OhMySmtpApiTransport $transport, string $expected) + { + $this->assertSame($expected, (string) $transport); + } + + public function getTransportData() + { + return [ + [ + new OhMySmtpApiTransport('KEY'), + 'ohmysmtp+api://app.ohmysmtp.com/api/v1', + ], + [ + (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), + 'ohmysmtp+api://example.com', + ], + [ + (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), + 'ohmysmtp+api://example.com:99', + ], + ]; + } + + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('Headers', $payload); + $this->assertCount(1, $payload['Headers']); + + $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); + } + + public function testSend() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); + $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); + + $body = json_decode($options['body'], true); + $this->assertSame('"Fabien" ', $body['from']); + $this->assertSame('"Saif Eddin" ', $body['to']); + $this->assertSame('Hello!', $body['subject']); + $this->assertSame('Hello There!', $body['textbody']); + + return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ + 'http_code' => 200, + ]); + }); + + $transport = new OhMySmtpApiTransport('KEY', $client); + + $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!'); + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } + + public function testSendThrowsForErrorResponse() + { + $client = new MockHttpClient(static function (string $method, string $url, array $options): ResponseInterface { + return new MockResponse(json_encode(['Message' => 'i\'m a teapot', 'ErrorCode' => 418]), [ + 'http_code' => 418, + 'response_headers' => [ + 'content-type' => 'application/json', + ], + ]); + }); + $transport = new OhMySmtpApiTransport('KEY', $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!'); + + $this->expectException(HttpTransportException::class); + $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).'); + $transport->send($mail); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayNotHasKey('Headers', $payload); + $this->assertArrayHasKey('tags', $payload); + + $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php new file mode 100644 index 0000000000000..15def04559b99 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Email; + +class OhMySmtpSmtpTransportTest extends TestCase +{ + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(1, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(2, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php new file mode 100644 index 0000000000000..2d8a3073828e3 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; +use Symfony\Component\Mailer\Test\TransportFactoryTestCase; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportFactoryInterface; + +class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase +{ + public function getFactory(): TransportFactoryInterface + { + return new OhMySmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + } + + public function supportsProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+api', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'example.com'), + true, + ]; + } + + public function createProvider(): iterable + { + $dispatcher = $this->getDispatcher(); + $logger = $this->getLogger(); + + yield [ + new Dsn('ohmysmtp+api', 'default', self::USER), + new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), + (new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), + ]; + + yield [ + new Dsn('ohmysmtp', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + } + + public function unsupportedSchemeProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+foo', 'default', self::USER), + 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', + ]; + } + + public function incompleteDsnProvider(): iterable + { + yield [new Dsn('ohmysmtp+api', 'default')]; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php new file mode 100644 index 0000000000000..d0775b7fab68d --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\AbstractApiTransport; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Paul Oms + */ +class OhMySmtpApiTransport extends AbstractApiTransport +{ + private const HOST = 'app.ohmysmtp.com/api/v1'; + + private $key; + + public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + $this->key = $key; + + parent::__construct($client, $dispatcher, $logger); + } + + public function __toString(): string + { + return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); + } + + protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface + { + $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ + 'headers' => [ + 'Accept' => 'application/json', + 'OhMySMTP-Server-Token' => $this->key, + 'Content-Type' => 'application/json', + 'User-Agent' => 'OhMySMTP Symfony Mailer', + ], + 'json' => $this->getPayload($email, $envelope), + ]); + + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (DecodingExceptionInterface $e) { + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); + } + + if (200 !== $statusCode) { + throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); + } + + $sentMessage->setMessageId($result['id']); + + return $response; + } + + private function getPayload(Email $email, Envelope $envelope): array + { + $payload = [ + 'from' => $envelope->getSender()->toString(), + 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), + 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), + 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), + 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), + 'subject' => $email->getSubject(), + 'textbody' => $email->getTextBody(), + 'htmlbody' => $email->getHtmlBody(), + 'attachments' => $this->getAttachments($email), + 'tags' => [], + ]; + + $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; + + foreach ($email->getHeaders()->all() as $name => $header) { + if (\in_array($name, $headersToBypass, true)) { + continue; + } + + if ($header instanceof TagHeader) { + $payload['tags'][] = $header->getValue(); + continue; + } + + $payload['Headers'][] = [ + 'Name' => $name, + 'Value' => $header->getBodyAsString(), + ]; + } + + return $payload; + } + + private function getAttachments(Email $email): array + { + $attachments = []; + foreach ($email->getAttachments() as $attachment) { + $headers = $attachment->getPreparedHeaders(); + $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $disposition = $headers->getHeaderBody('Content-Disposition'); + + $att = [ + 'name' => $filename, + 'content' => $attachment->bodyToString(), + 'content_type' => $headers->get('Content-Type')->getBody(), + ]; + + if ('inline' === $disposition) { + $att['cid'] = 'cid:'.$filename; + } + + $attachments[] = $att; + } + + return $attachments; + } + + private function getEndpoint(): ?string + { + return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php new file mode 100644 index 0000000000000..9d23baeae5724 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @author Paul Oms + */ +class OhMySmtpSmtpTransport extends EsmtpTransport +{ + public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); + + $this->setUsername($id); + $this->setPassword($id); + } + + public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage + { + if ($message instanceof Message) { + $this->addOhMySmtpHeaders($message); + } + + return parent::send($message, $envelope); + } + + private function addOhMySmtpHeaders(Message $message): void + { + $headers = $message->getHeaders(); + + foreach ($headers->all() as $name => $header) { + if ($header instanceof TagHeader) { + if (null != $headers->get('X-OMS-Tags')) { + $existing = $headers->get('X-OMS-Tags')->getBody(); + $headers->remove('X-OMS-Tags'); + $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); + } else { + $headers->addTextHeader('X-OMS-Tags', $header->getValue()); + } + $headers->remove($name); + } + } + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php new file mode 100644 index 0000000000000..79103815b0c25 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; +use Symfony\Component\Mailer\Transport\AbstractTransportFactory; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportInterface; + +/** + * @author Paul Oms + */ +final class OhMySmtpTransportFactory extends AbstractTransportFactory +{ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + + if ('ohmysmtp+api' === $scheme) { + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); + + return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); + } + + if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { + return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); + } + + throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json new file mode 100644 index 0000000000000..561dba7e405f0 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/ohmysmtp-mailer", + "type": "symfony-bridge", + "description": "Symfony OhMySMTP Mailer Bridge", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Paul Oms", + "homepage": "https://ohmysmtp.com" + } + ], + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1", + "symfony/mailer": "^5.3.0|^6.0" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist new file mode 100644 index 0000000000000..706e4cf3c1339 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + From 8f7afafa258d7717b20b5ddc604efc3511f4fa28 Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:27:05 +0100 Subject: [PATCH 07/13] Readd files --- .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitattributes | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitignore | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/CHANGELOG.md | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/LICENSE | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/README.md | 0 .../Tests/Transport/OhMySmtpApiTransportTest.php | 0 .../Tests/Transport/OhMySmtpSmtpTransportTest.php | 0 .../Tests/Transport/OhMySmtpTransportFactoryTest.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpApiTransport.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpSmtpTransport.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpTransportFactory.php | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/composer.json | 0 .../Mailer/Bridge/{OhMySmtp => ohmysmtp}/phpunit.xml.dist | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitattributes (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitignore (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/CHANGELOG.md (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/LICENSE (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/README.md (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpApiTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpSmtpTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpTransportFactoryTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpApiTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpSmtpTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpTransportFactory.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/composer.json (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/phpunit.xml.dist (100%) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist From 134441425f62f0c11a4c014ab00dc70583b1537a Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:27:48 +0100 Subject: [PATCH 08/13] Change directory case to match class names --- .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/.gitattributes | 0 .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/.gitignore | 0 .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/CHANGELOG.md | 0 .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/LICENSE | 0 .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/README.md | 0 .../Tests/Transport/OhMySmtpApiTransportTest.php | 0 .../Tests/Transport/OhMySmtpSmtpTransportTest.php | 0 .../Tests/Transport/OhMySmtpTransportFactoryTest.php | 0 .../{ohmysmtp => OhMySmtp}/Transport/OhMySmtpApiTransport.php | 0 .../{ohmysmtp => OhMySmtp}/Transport/OhMySmtpSmtpTransport.php | 0 .../{ohmysmtp => OhMySmtp}/Transport/OhMySmtpTransportFactory.php | 0 .../Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/composer.json | 0 .../Mailer/Bridge/{ohmysmtp => OhMySmtp}/phpunit.xml.dist | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/.gitattributes (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/.gitignore (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/CHANGELOG.md (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/LICENSE (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/README.md (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Tests/Transport/OhMySmtpApiTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Tests/Transport/OhMySmtpSmtpTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Tests/Transport/OhMySmtpTransportFactoryTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Transport/OhMySmtpApiTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Transport/OhMySmtpSmtpTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/Transport/OhMySmtpTransportFactory.php (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/composer.json (100%) rename src/Symfony/Component/Mailer/Bridge/{ohmysmtp => OhMySmtp}/phpunit.xml.dist (100%) diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist rename to src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist From 7421a131bcdd9349b830f304cd06e567c482fbe3 Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:30:26 +0100 Subject: [PATCH 09/13] Reverting back to unchanged file case --- .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitattributes | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitignore | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/CHANGELOG.md | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/LICENSE | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/README.md | 0 .../Tests/Transport/OhMySmtpApiTransportTest.php | 0 .../Tests/Transport/OhMySmtpSmtpTransportTest.php | 0 .../Tests/Transport/OhMySmtpTransportFactoryTest.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpApiTransport.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpSmtpTransport.php | 0 .../{OhMySmtp => ohmysmtp}/Transport/OhMySmtpTransportFactory.php | 0 .../Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/composer.json | 0 .../Mailer/Bridge/{OhMySmtp => ohmysmtp}/phpunit.xml.dist | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitattributes (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/.gitignore (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/CHANGELOG.md (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/LICENSE (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/README.md (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpApiTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpSmtpTransportTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Tests/Transport/OhMySmtpTransportFactoryTest.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpApiTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpSmtpTransport.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/Transport/OhMySmtpTransportFactory.php (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/composer.json (100%) rename src/Symfony/Component/Mailer/Bridge/{OhMySmtp => ohmysmtp}/phpunit.xml.dist (100%) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist similarity index 100% rename from src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist rename to src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist From 35bbd5792e734690ba110f99dfe45d12b636faaa Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:34:46 +0100 Subject: [PATCH 10/13] Removed everything in ohmysmtp folders --- .../Mailer/Bridge/Ohmysmtp/.gitattributes | 4 - .../Mailer/Bridge/Ohmysmtp/.gitignore | 3 - .../Mailer/Bridge/Ohmysmtp/CHANGELOG.md | 7 - .../Component/Mailer/Bridge/Ohmysmtp/LICENSE | 19 --- .../Mailer/Bridge/Ohmysmtp/README.md | 24 --- .../Transport/OhmysmtpApiTransportTest.php | 143 ------------------ .../Transport/OhmysmtpSmtpTransportTest.php | 51 ------- .../OhmysmtpTransportFactoryTest.php | 99 ------------ .../Transport/OhmysmtpApiTransport.php | 142 ----------------- .../Transport/OhmysmtpSmtpTransport.php | 62 -------- .../Transport/OhmysmtpTransportFactory.php | 46 ------ .../Mailer/Bridge/Ohmysmtp/composer.json | 37 ----- .../Mailer/Bridge/Ohmysmtp/phpunit.xml.dist | 31 ---- .../Mailer/Bridge/ohmysmtp/.gitattributes | 4 - .../Mailer/Bridge/ohmysmtp/.gitignore | 3 - .../Mailer/Bridge/ohmysmtp/CHANGELOG.md | 7 - .../Component/Mailer/Bridge/ohmysmtp/LICENSE | 19 --- .../Mailer/Bridge/ohmysmtp/README.md | 24 --- .../Transport/OhMySmtpApiTransportTest.php | 143 ------------------ .../Transport/OhMySmtpSmtpTransportTest.php | 51 ------- .../OhMySmtpTransportFactoryTest.php | 99 ------------ .../Transport/OhMySmtpApiTransport.php | 142 ----------------- .../Transport/OhMySmtpSmtpTransport.php | 62 -------- .../Transport/OhMySmtpTransportFactory.php | 46 ------ .../Mailer/Bridge/ohmysmtp/composer.json | 37 ----- .../Mailer/Bridge/ohmysmtp/phpunit.xml.dist | 31 ---- 26 files changed, 1336 deletions(-) delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json delete mode 100644 src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json delete mode 100644 src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes deleted file mode 100644 index 84c7add058fb5..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore deleted file mode 100644 index c49a5d8df5c65..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md deleted file mode 100644 index 37308ee9aead6..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -CHANGELOG -========= - -5.4 ------ - - * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE deleted file mode 100644 index efb17f98e7dd3..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md deleted file mode 100644 index fdeeb9f8a7727..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/README.md +++ /dev/null @@ -1,24 +0,0 @@ -OhMySMTP Bridge -=============== - -Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. - - -DSN example ------------ - -``` -MAILER_DSN=ohmysmtp+api://API_TOKEN@default -``` - -where: - - `API_TOKEN` is your OhMySMTP API Token - - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php deleted file mode 100644 index 48960f4704adf..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpApiTransportTest.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\ResponseInterface; - -class OhMySmtpApiTransportTest extends TestCase -{ - /** - * @dataProvider getTransportData - */ - public function testToString(OhMySmtpApiTransport $transport, string $expected) - { - $this->assertSame($expected, (string) $transport); - } - - public function getTransportData() - { - return [ - [ - new OhMySmtpApiTransport('KEY'), - 'ohmysmtp+api://app.ohmysmtp.com/api/v1', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), - 'ohmysmtp+api://example.com', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), - 'ohmysmtp+api://example.com:99', - ], - ]; - } - - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $method->setAccessible(true); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayHasKey('Headers', $payload); - $this->assertCount(1, $payload['Headers']); - - $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); - } - - public function testSend() - { - $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { - $this->assertSame('POST', $method); - $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); - $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); - - $body = json_decode($options['body'], true); - $this->assertSame('"Fabien" ', $body['from']); - $this->assertSame('"Saif Eddin" ', $body['to']); - $this->assertSame('Hello!', $body['subject']); - $this->assertSame('Hello There!', $body['textbody']); - - return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ - 'http_code' => 200, - ]); - }); - - $transport = new OhMySmtpApiTransport('KEY', $client); - - $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!'); - - $message = $transport->send($mail); - - $this->assertSame('foobar', $message->getMessageId()); - } - - public function testSendThrowsForErrorResponse() - { - $client = new MockHttpClient(static function (string $method, string $url, array $options): ResponseInterface { - return new MockResponse(json_encode(['Message' => 'i\'m a teapot', 'ErrorCode' => 418]), [ - 'http_code' => 418, - 'response_headers' => [ - 'content-type' => 'application/json', - ], - ]); - }); - $transport = new OhMySmtpApiTransport('KEY', $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!'); - - $this->expectException(HttpTransportException::class); - $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).'); - $transport->send($mail); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $method->setAccessible(true); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayNotHasKey('Headers', $payload); - $this->assertArrayHasKey('tags', $payload); - - $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php deleted file mode 100644 index 15def04559b99..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpSmtpTransportTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Email; - -class OhMySmtpSmtpTransportTest extends TestCase -{ - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->setAccessible(true); - $method->invoke($transport, $email); - - $this->assertCount(1, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->setAccessible(true); - $method->invoke($transport, $email); - - $this->assertCount(2, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php deleted file mode 100644 index 2d8a3073828e3..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Tests/Transport/OhmysmtpTransportFactoryTest.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; -use Symfony\Component\Mailer\Test\TransportFactoryTestCase; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportFactoryInterface; - -class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase -{ - public function getFactory(): TransportFactoryInterface - { - return new OhMySmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); - } - - public function supportsProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+api', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'example.com'), - true, - ]; - } - - public function createProvider(): iterable - { - $dispatcher = $this->getDispatcher(); - $logger = $this->getLogger(); - - yield [ - new Dsn('ohmysmtp+api', 'default', self::USER), - new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), - (new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), - ]; - - yield [ - new Dsn('ohmysmtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - } - - public function unsupportedSchemeProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+foo', 'default', self::USER), - 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', - ]; - } - - public function incompleteDsnProvider(): iterable - { - yield [new Dsn('ohmysmtp+api', 'default')]; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php deleted file mode 100644 index d0775b7fab68d..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpApiTransport.php +++ /dev/null @@ -1,142 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\AbstractApiTransport; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; -use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\HttpClient\ResponseInterface; - -/** - * @author Paul Oms - */ -class OhMySmtpApiTransport extends AbstractApiTransport -{ - private const HOST = 'app.ohmysmtp.com/api/v1'; - - private $key; - - public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - $this->key = $key; - - parent::__construct($client, $dispatcher, $logger); - } - - public function __toString(): string - { - return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); - } - - protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface - { - $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ - 'headers' => [ - 'Accept' => 'application/json', - 'OhMySMTP-Server-Token' => $this->key, - 'Content-Type' => 'application/json', - 'User-Agent' => 'OhMySMTP Symfony Mailer', - ], - 'json' => $this->getPayload($email, $envelope), - ]); - - try { - $statusCode = $response->getStatusCode(); - $result = $response->toArray(false); - } catch (DecodingExceptionInterface $e) { - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); - } catch (TransportExceptionInterface $e) { - throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); - } - - if (200 !== $statusCode) { - throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); - } - - $sentMessage->setMessageId($result['id']); - - return $response; - } - - private function getPayload(Email $email, Envelope $envelope): array - { - $payload = [ - 'from' => $envelope->getSender()->toString(), - 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), - 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), - 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), - 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), - 'subject' => $email->getSubject(), - 'textbody' => $email->getTextBody(), - 'htmlbody' => $email->getHtmlBody(), - 'attachments' => $this->getAttachments($email), - 'tags' => [], - ]; - - $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; - - foreach ($email->getHeaders()->all() as $name => $header) { - if (\in_array($name, $headersToBypass, true)) { - continue; - } - - if ($header instanceof TagHeader) { - $payload['tags'][] = $header->getValue(); - continue; - } - - $payload['Headers'][] = [ - 'Name' => $name, - 'Value' => $header->getBodyAsString(), - ]; - } - - return $payload; - } - - private function getAttachments(Email $email): array - { - $attachments = []; - foreach ($email->getAttachments() as $attachment) { - $headers = $attachment->getPreparedHeaders(); - $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); - $disposition = $headers->getHeaderBody('Content-Disposition'); - - $att = [ - 'name' => $filename, - 'content' => $attachment->bodyToString(), - 'content_type' => $headers->get('Content-Type')->getBody(), - ]; - - if ('inline' === $disposition) { - $att['cid'] = 'cid:'.$filename; - } - - $attachments[] = $att; - } - - return $attachments; - } - - private function getEndpoint(): ?string - { - return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php deleted file mode 100644 index 9d23baeae5724..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpSmtpTransport.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; -use Symfony\Component\Mime\Message; -use Symfony\Component\Mime\RawMessage; - -/** - * @author Paul Oms - */ -class OhMySmtpSmtpTransport extends EsmtpTransport -{ - public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); - - $this->setUsername($id); - $this->setPassword($id); - } - - public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage - { - if ($message instanceof Message) { - $this->addOhMySmtpHeaders($message); - } - - return parent::send($message, $envelope); - } - - private function addOhMySmtpHeaders(Message $message): void - { - $headers = $message->getHeaders(); - - foreach ($headers->all() as $name => $header) { - if ($header instanceof TagHeader) { - if (null != $headers->get('X-OMS-Tags')) { - $existing = $headers->get('X-OMS-Tags')->getBody(); - $headers->remove('X-OMS-Tags'); - $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); - } else { - $headers->addTextHeader('X-OMS-Tags', $header->getValue()); - } - $headers->remove($name); - } - } - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php deleted file mode 100644 index 79103815b0c25..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/Transport/OhmysmtpTransportFactory.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; -use Symfony\Component\Mailer\Transport\AbstractTransportFactory; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportInterface; - -/** - * @author Paul Oms - */ -final class OhMySmtpTransportFactory extends AbstractTransportFactory -{ - public function create(Dsn $dsn): TransportInterface - { - $scheme = $dsn->getScheme(); - - if ('ohmysmtp+api' === $scheme) { - $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); - $port = $dsn->getPort(); - - return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); - } - - if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { - return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); - } - - throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); - } - - protected function getSupportedSchemes(): array - { - return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json deleted file mode 100644 index 561dba7e405f0..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/ohmysmtp-mailer", - "type": "symfony-bridge", - "description": "Symfony OhMySMTP Mailer Bridge", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Paul Oms", - "homepage": "https://ohmysmtp.com" - } - ], - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1", - "symfony/mailer": "^5.3.0|^6.0" - }, - "require-dev": { - "symfony/http-client": "^4.4|^5.0|^6.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist deleted file mode 100644 index 706e4cf3c1339..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/Ohmysmtp/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Resources - ./Tests - ./vendor - - - - diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes deleted file mode 100644 index 84c7add058fb5..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore deleted file mode 100644 index c49a5d8df5c65..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md deleted file mode 100644 index 37308ee9aead6..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -CHANGELOG -========= - -5.4 ------ - - * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE deleted file mode 100644 index efb17f98e7dd3..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md deleted file mode 100644 index fdeeb9f8a7727..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/README.md +++ /dev/null @@ -1,24 +0,0 @@ -OhMySMTP Bridge -=============== - -Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. - - -DSN example ------------ - -``` -MAILER_DSN=ohmysmtp+api://API_TOKEN@default -``` - -where: - - `API_TOKEN` is your OhMySMTP API Token - - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php deleted file mode 100644 index 48960f4704adf..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpApiTransportTest.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpClient\MockHttpClient; -use Symfony\Component\HttpClient\Response\MockResponse; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\ResponseInterface; - -class OhMySmtpApiTransportTest extends TestCase -{ - /** - * @dataProvider getTransportData - */ - public function testToString(OhMySmtpApiTransport $transport, string $expected) - { - $this->assertSame($expected, (string) $transport); - } - - public function getTransportData() - { - return [ - [ - new OhMySmtpApiTransport('KEY'), - 'ohmysmtp+api://app.ohmysmtp.com/api/v1', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), - 'ohmysmtp+api://example.com', - ], - [ - (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), - 'ohmysmtp+api://example.com:99', - ], - ]; - } - - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $method->setAccessible(true); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayHasKey('Headers', $payload); - $this->assertCount(1, $payload['Headers']); - - $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); - } - - public function testSend() - { - $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { - $this->assertSame('POST', $method); - $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); - $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); - - $body = json_decode($options['body'], true); - $this->assertSame('"Fabien" ', $body['from']); - $this->assertSame('"Saif Eddin" ', $body['to']); - $this->assertSame('Hello!', $body['subject']); - $this->assertSame('Hello There!', $body['textbody']); - - return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ - 'http_code' => 200, - ]); - }); - - $transport = new OhMySmtpApiTransport('KEY', $client); - - $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!'); - - $message = $transport->send($mail); - - $this->assertSame('foobar', $message->getMessageId()); - } - - public function testSendThrowsForErrorResponse() - { - $client = new MockHttpClient(static function (string $method, string $url, array $options): ResponseInterface { - return new MockResponse(json_encode(['Message' => 'i\'m a teapot', 'ErrorCode' => 418]), [ - 'http_code' => 418, - 'response_headers' => [ - 'content-type' => 'application/json', - ], - ]); - }); - $transport = new OhMySmtpApiTransport('KEY', $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!'); - - $this->expectException(HttpTransportException::class); - $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).'); - $transport->send($mail); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); - - $transport = new OhMySmtpApiTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); - $method->setAccessible(true); - $payload = $method->invoke($transport, $email, $envelope); - - $this->assertArrayNotHasKey('Headers', $payload); - $this->assertArrayHasKey('tags', $payload); - - $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php deleted file mode 100644 index 15def04559b99..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mime\Email; - -class OhMySmtpSmtpTransportTest extends TestCase -{ - public function testCustomHeader() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->setAccessible(true); - $method->invoke($transport, $email); - - $this->assertCount(1, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - } - - public function testTagAndMetadataHeaders() - { - $email = new Email(); - $email->getHeaders()->addTextHeader('foo', 'bar'); - $email->getHeaders()->add(new TagHeader('password-reset')); - $email->getHeaders()->add(new TagHeader('2nd-tag')); - - $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); - $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); - $method->setAccessible(true); - $method->invoke($transport, $email); - - $this->assertCount(2, $email->getHeaders()->toArray()); - $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); - $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php deleted file mode 100644 index 2d8a3073828e3..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; - -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; -use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; -use Symfony\Component\Mailer\Test\TransportFactoryTestCase; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportFactoryInterface; - -class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase -{ - public function getFactory(): TransportFactoryInterface - { - return new OhMySmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); - } - - public function supportsProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+api', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default'), - true, - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'example.com'), - true, - ]; - } - - public function createProvider(): iterable - { - $dispatcher = $this->getDispatcher(); - $logger = $this->getLogger(); - - yield [ - new Dsn('ohmysmtp+api', 'default', self::USER), - new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), - (new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), - ]; - - yield [ - new Dsn('ohmysmtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtp', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - - yield [ - new Dsn('ohmysmtp+smtps', 'default', self::USER), - new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), - ]; - } - - public function unsupportedSchemeProvider(): iterable - { - yield [ - new Dsn('ohmysmtp+foo', 'default', self::USER), - 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', - ]; - } - - public function incompleteDsnProvider(): iterable - { - yield [new Dsn('ohmysmtp+api', 'default')]; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php deleted file mode 100644 index d0775b7fab68d..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpApiTransport.php +++ /dev/null @@ -1,142 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Exception\HttpTransportException; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\AbstractApiTransport; -use Symfony\Component\Mime\Email; -use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; -use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\HttpClient\ResponseInterface; - -/** - * @author Paul Oms - */ -class OhMySmtpApiTransport extends AbstractApiTransport -{ - private const HOST = 'app.ohmysmtp.com/api/v1'; - - private $key; - - public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - $this->key = $key; - - parent::__construct($client, $dispatcher, $logger); - } - - public function __toString(): string - { - return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); - } - - protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface - { - $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ - 'headers' => [ - 'Accept' => 'application/json', - 'OhMySMTP-Server-Token' => $this->key, - 'Content-Type' => 'application/json', - 'User-Agent' => 'OhMySMTP Symfony Mailer', - ], - 'json' => $this->getPayload($email, $envelope), - ]); - - try { - $statusCode = $response->getStatusCode(); - $result = $response->toArray(false); - } catch (DecodingExceptionInterface $e) { - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); - } catch (TransportExceptionInterface $e) { - throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); - } - - if (200 !== $statusCode) { - throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); - } - - $sentMessage->setMessageId($result['id']); - - return $response; - } - - private function getPayload(Email $email, Envelope $envelope): array - { - $payload = [ - 'from' => $envelope->getSender()->toString(), - 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), - 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), - 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), - 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), - 'subject' => $email->getSubject(), - 'textbody' => $email->getTextBody(), - 'htmlbody' => $email->getHtmlBody(), - 'attachments' => $this->getAttachments($email), - 'tags' => [], - ]; - - $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; - - foreach ($email->getHeaders()->all() as $name => $header) { - if (\in_array($name, $headersToBypass, true)) { - continue; - } - - if ($header instanceof TagHeader) { - $payload['tags'][] = $header->getValue(); - continue; - } - - $payload['Headers'][] = [ - 'Name' => $name, - 'Value' => $header->getBodyAsString(), - ]; - } - - return $payload; - } - - private function getAttachments(Email $email): array - { - $attachments = []; - foreach ($email->getAttachments() as $attachment) { - $headers = $attachment->getPreparedHeaders(); - $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); - $disposition = $headers->getHeaderBody('Content-Disposition'); - - $att = [ - 'name' => $filename, - 'content' => $attachment->bodyToString(), - 'content_type' => $headers->get('Content-Type')->getBody(), - ]; - - if ('inline' === $disposition) { - $att['cid'] = 'cid:'.$filename; - } - - $attachments[] = $att; - } - - return $attachments; - } - - private function getEndpoint(): ?string - { - return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php deleted file mode 100644 index 9d23baeae5724..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpSmtpTransport.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Mailer\Envelope; -use Symfony\Component\Mailer\Header\TagHeader; -use Symfony\Component\Mailer\SentMessage; -use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; -use Symfony\Component\Mime\Message; -use Symfony\Component\Mime\RawMessage; - -/** - * @author Paul Oms - */ -class OhMySmtpSmtpTransport extends EsmtpTransport -{ - public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) - { - parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); - - $this->setUsername($id); - $this->setPassword($id); - } - - public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage - { - if ($message instanceof Message) { - $this->addOhMySmtpHeaders($message); - } - - return parent::send($message, $envelope); - } - - private function addOhMySmtpHeaders(Message $message): void - { - $headers = $message->getHeaders(); - - foreach ($headers->all() as $name => $header) { - if ($header instanceof TagHeader) { - if (null != $headers->get('X-OMS-Tags')) { - $existing = $headers->get('X-OMS-Tags')->getBody(); - $headers->remove('X-OMS-Tags'); - $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); - } else { - $headers->addTextHeader('X-OMS-Tags', $header->getValue()); - } - $headers->remove($name); - } - } - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php deleted file mode 100644 index 79103815b0c25..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/Transport/OhMySmtpTransportFactory.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; - -use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; -use Symfony\Component\Mailer\Transport\AbstractTransportFactory; -use Symfony\Component\Mailer\Transport\Dsn; -use Symfony\Component\Mailer\Transport\TransportInterface; - -/** - * @author Paul Oms - */ -final class OhMySmtpTransportFactory extends AbstractTransportFactory -{ - public function create(Dsn $dsn): TransportInterface - { - $scheme = $dsn->getScheme(); - - if ('ohmysmtp+api' === $scheme) { - $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); - $port = $dsn->getPort(); - - return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); - } - - if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { - return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); - } - - throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); - } - - protected function getSupportedSchemes(): array - { - return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; - } -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json deleted file mode 100644 index 561dba7e405f0..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "symfony/ohmysmtp-mailer", - "type": "symfony-bridge", - "description": "Symfony OhMySMTP Mailer Bridge", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Paul Oms", - "homepage": "https://ohmysmtp.com" - } - ], - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1", - "symfony/mailer": "^5.3.0|^6.0" - }, - "require-dev": { - "symfony/http-client": "^4.4|^5.0|^6.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist deleted file mode 100644 index 706e4cf3c1339..0000000000000 --- a/src/Symfony/Component/Mailer/Bridge/ohmysmtp/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Resources - ./Tests - ./vendor - - - - From bd15c562200ff2b2a83fff3624cb16c11281992a Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Wed, 25 Aug 2021 21:35:36 +0100 Subject: [PATCH 11/13] Readding with the correct dir case --- .../Mailer/Bridge/OhMySmtp/.gitattributes | 4 + .../Mailer/Bridge/OhMySmtp/.gitignore | 3 + .../Mailer/Bridge/OhMySmtp/CHANGELOG.md | 7 + .../Component/Mailer/Bridge/OhMySmtp/LICENSE | 19 +++ .../Mailer/Bridge/OhMySmtp/README.md | 24 +++ .../Transport/OhMySmtpApiTransportTest.php | 143 ++++++++++++++++++ .../Transport/OhMySmtpSmtpTransportTest.php | 51 +++++++ .../OhMySmtpTransportFactoryTest.php | 99 ++++++++++++ .../Transport/OhMySmtpApiTransport.php | 142 +++++++++++++++++ .../Transport/OhMySmtpSmtpTransport.php | 62 ++++++++ .../Transport/OhMySmtpTransportFactory.php | 46 ++++++ .../Mailer/Bridge/OhMySmtp/composer.json | 37 +++++ .../Mailer/Bridge/OhMySmtp/phpunit.xml.dist | 31 ++++ 13 files changed, 668 insertions(+) create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json create mode 100644 src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes new file mode 100644 index 0000000000000..84c7add058fb5 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitattributes @@ -0,0 +1,4 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore new file mode 100644 index 0000000000000..c49a5d8df5c65 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md new file mode 100644 index 0000000000000..37308ee9aead6 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +5.4 +----- + + * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE new file mode 100644 index 0000000000000..efb17f98e7dd3 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md new file mode 100644 index 0000000000000..fdeeb9f8a7727 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/README.md @@ -0,0 +1,24 @@ +OhMySMTP Bridge +=============== + +Provides [OhMySMTP](https://ohmysmtp.com) integration for Symfony Mailer. + + +DSN example +----------- + +``` +MAILER_DSN=ohmysmtp+api://API_TOKEN@default +``` + +where: + - `API_TOKEN` is your OhMySMTP API Token + + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php new file mode 100644 index 0000000000000..48960f4704adf --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\ResponseInterface; + +class OhMySmtpApiTransportTest extends TestCase +{ + /** + * @dataProvider getTransportData + */ + public function testToString(OhMySmtpApiTransport $transport, string $expected) + { + $this->assertSame($expected, (string) $transport); + } + + public function getTransportData() + { + return [ + [ + new OhMySmtpApiTransport('KEY'), + 'ohmysmtp+api://app.ohmysmtp.com/api/v1', + ], + [ + (new OhMySmtpApiTransport('KEY'))->setHost('example.com'), + 'ohmysmtp+api://example.com', + ], + [ + (new OhMySmtpApiTransport('KEY'))->setHost('example.com')->setPort(99), + 'ohmysmtp+api://example.com:99', + ], + ]; + } + + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('Headers', $payload); + $this->assertCount(1, $payload['Headers']); + + $this->assertEquals(['Name' => 'foo', 'Value' => 'bar'], $payload['Headers'][0]); + } + + public function testSend() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://app.ohmysmtp.com/api/v1/send', $url); + $this->assertStringContainsStringIgnoringCase('OhMySMTP-Server-Token: KEY', $options['headers'][1] ?? $options['request_headers'][1]); + + $body = json_decode($options['body'], true); + $this->assertSame('"Fabien" ', $body['from']); + $this->assertSame('"Saif Eddin" ', $body['to']); + $this->assertSame('Hello!', $body['subject']); + $this->assertSame('Hello There!', $body['textbody']); + + return new MockResponse(json_encode(['id' => 'foobar', 'status' => 'pending']), [ + 'http_code' => 200, + ]); + }); + + $transport = new OhMySmtpApiTransport('KEY', $client); + + $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!'); + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } + + public function testSendThrowsForErrorResponse() + { + $client = new MockHttpClient(static function (string $method, string $url, array $options): ResponseInterface { + return new MockResponse(json_encode(['Message' => 'i\'m a teapot', 'ErrorCode' => 418]), [ + 'http_code' => 418, + 'response_headers' => [ + 'content-type' => 'application/json', + ], + ]); + }); + $transport = new OhMySmtpApiTransport('KEY', $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!'); + + $this->expectException(HttpTransportException::class); + $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).'); + $transport->send($mail); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $envelope = new Envelope(new Address('alice@system.com'), [new Address('bob@system.com')]); + + $transport = new OhMySmtpApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpApiTransport::class, 'getPayload'); + $method->setAccessible(true); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayNotHasKey('Headers', $payload); + $this->assertArrayHasKey('tags', $payload); + + $this->assertSame(['password-reset', '2nd-tag'], $payload['tags']); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php new file mode 100644 index 0000000000000..15def04559b99 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mime\Email; + +class OhMySmtpSmtpTransportTest extends TestCase +{ + public function testCustomHeader() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(1, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + } + + public function testTagAndMetadataHeaders() + { + $email = new Email(); + $email->getHeaders()->addTextHeader('foo', 'bar'); + $email->getHeaders()->add(new TagHeader('password-reset')); + $email->getHeaders()->add(new TagHeader('2nd-tag')); + + $transport = new OhMySmtpSmtpTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(OhMySmtpSmtpTransport::class, 'addOhMySmtpHeaders'); + $method->setAccessible(true); + $method->invoke($transport, $email); + + $this->assertCount(2, $email->getHeaders()->toArray()); + $this->assertSame('foo: bar', $email->getHeaders()->get('FOO')->toString()); + $this->assertSame('X-OMS-Tags: password-reset, 2nd-tag', $email->getHeaders()->get('X-OMS-Tags')->toString()); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php new file mode 100644 index 0000000000000..2d8a3073828e3 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Tests\Transport; + +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport; +use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory; +use Symfony\Component\Mailer\Test\TransportFactoryTestCase; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportFactoryInterface; + +class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase +{ + public function getFactory(): TransportFactoryInterface + { + return new OhMySmtpTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + } + + public function supportsProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+api', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default'), + true, + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'example.com'), + true, + ]; + } + + public function createProvider(): iterable + { + $dispatcher = $this->getDispatcher(); + $logger = $this->getLogger(); + + yield [ + new Dsn('ohmysmtp+api', 'default', self::USER), + new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+api', 'example.com', self::USER, '', 8080), + (new OhMySmtpApiTransport(self::USER, $this->getClient(), $dispatcher, $logger))->setHost('example.com')->setPort(8080), + ]; + + yield [ + new Dsn('ohmysmtp', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtp', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + + yield [ + new Dsn('ohmysmtp+smtps', 'default', self::USER), + new OhMySmtpSmtpTransport(self::USER, $dispatcher, $logger), + ]; + } + + public function unsupportedSchemeProvider(): iterable + { + yield [ + new Dsn('ohmysmtp+foo', 'default', self::USER), + 'The "ohmysmtp+foo" scheme is not supported; supported schemes for mailer "ohmysmtp" are: "ohmysmtp", "ohmysmtp+api", "ohmysmtp+smtp", "ohmysmtp+smtps".', + ]; + } + + public function incompleteDsnProvider(): iterable + { + yield [new Dsn('ohmysmtp+api', 'default')]; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php new file mode 100644 index 0000000000000..d0775b7fab68d --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\AbstractApiTransport; +use Symfony\Component\Mime\Email; +use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Paul Oms + */ +class OhMySmtpApiTransport extends AbstractApiTransport +{ + private const HOST = 'app.ohmysmtp.com/api/v1'; + + private $key; + + public function __construct(string $key, HttpClientInterface $client = null, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + $this->key = $key; + + parent::__construct($client, $dispatcher, $logger); + } + + public function __toString(): string + { + return sprintf('ohmysmtp+api://%s', $this->getEndpoint()); + } + + protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface + { + $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ + 'headers' => [ + 'Accept' => 'application/json', + 'OhMySMTP-Server-Token' => $this->key, + 'Content-Type' => 'application/json', + 'User-Agent' => 'OhMySMTP Symfony Mailer', + ], + 'json' => $this->getPayload($email, $envelope), + ]); + + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (DecodingExceptionInterface $e) { + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); + } catch (TransportExceptionInterface $e) { + throw new HttpTransportException('Could not reach the remote OhMySMTP endpoint.', $response, 0, $e); + } + + if (200 !== $statusCode) { + throw new HttpTransportException('Unable to send an email: '.$result['Message'].sprintf(' (code %d).', $result['ErrorCode']), $response); + } + + $sentMessage->setMessageId($result['id']); + + return $response; + } + + private function getPayload(Email $email, Envelope $envelope): array + { + $payload = [ + 'from' => $envelope->getSender()->toString(), + 'to' => implode(',', $this->stringifyAddresses($this->getRecipients($email, $envelope))), + 'cc' => implode(',', $this->stringifyAddresses($email->getCc())), + 'bcc' => implode(',', $this->stringifyAddresses($email->getBcc())), + 'replyto' => implode(',', $this->stringifyAddresses($email->getReplyTo())), + 'subject' => $email->getSubject(), + 'textbody' => $email->getTextBody(), + 'htmlbody' => $email->getHtmlBody(), + 'attachments' => $this->getAttachments($email), + 'tags' => [], + ]; + + $headersToBypass = ['from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'sender', 'reply-to']; + + foreach ($email->getHeaders()->all() as $name => $header) { + if (\in_array($name, $headersToBypass, true)) { + continue; + } + + if ($header instanceof TagHeader) { + $payload['tags'][] = $header->getValue(); + continue; + } + + $payload['Headers'][] = [ + 'Name' => $name, + 'Value' => $header->getBodyAsString(), + ]; + } + + return $payload; + } + + private function getAttachments(Email $email): array + { + $attachments = []; + foreach ($email->getAttachments() as $attachment) { + $headers = $attachment->getPreparedHeaders(); + $filename = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $disposition = $headers->getHeaderBody('Content-Disposition'); + + $att = [ + 'name' => $filename, + 'content' => $attachment->bodyToString(), + 'content_type' => $headers->get('Content-Type')->getBody(), + ]; + + if ('inline' === $disposition) { + $att['cid'] = 'cid:'.$filename; + } + + $attachments[] = $att; + } + + return $attachments; + } + + private function getEndpoint(): ?string + { + return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : ''); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php new file mode 100644 index 0000000000000..9d23baeae5724 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @author Paul Oms + */ +class OhMySmtpSmtpTransport extends EsmtpTransport +{ + public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + parent::__construct('smtp.ohmysmtp.com', 587, false, $dispatcher, $logger); + + $this->setUsername($id); + $this->setPassword($id); + } + + public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage + { + if ($message instanceof Message) { + $this->addOhMySmtpHeaders($message); + } + + return parent::send($message, $envelope); + } + + private function addOhMySmtpHeaders(Message $message): void + { + $headers = $message->getHeaders(); + + foreach ($headers->all() as $name => $header) { + if ($header instanceof TagHeader) { + if (null != $headers->get('X-OMS-Tags')) { + $existing = $headers->get('X-OMS-Tags')->getBody(); + $headers->remove('X-OMS-Tags'); + $headers->addTextHeader('X-OMS-Tags', $existing.', '.$header->getValue()); + } else { + $headers->addTextHeader('X-OMS-Tags', $header->getValue()); + } + $headers->remove($name); + } + } + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php new file mode 100644 index 0000000000000..79103815b0c25 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpTransportFactory.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\OhMySmtp\Transport; + +use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; +use Symfony\Component\Mailer\Transport\AbstractTransportFactory; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportInterface; + +/** + * @author Paul Oms + */ +final class OhMySmtpTransportFactory extends AbstractTransportFactory +{ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + + if ('ohmysmtp+api' === $scheme) { + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); + + return (new OhMySmtpApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger))->setHost($host)->setPort($port); + } + + if ('ohmysmtp+smtp' === $scheme || 'ohmysmtp+smtps' === $scheme || 'ohmysmtp' === $scheme) { + return new OhMySmtpSmtpTransport($this->getUser($dsn), $this->dispatcher, $this->logger); + } + + throw new UnsupportedSchemeException($dsn, 'ohmysmtp', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['ohmysmtp', 'ohmysmtp+api', 'ohmysmtp+smtp', 'ohmysmtp+smtps']; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json new file mode 100644 index 0000000000000..561dba7e405f0 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/ohmysmtp-mailer", + "type": "symfony-bridge", + "description": "Symfony OhMySMTP Mailer Bridge", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Paul Oms", + "homepage": "https://ohmysmtp.com" + } + ], + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1", + "symfony/mailer": "^5.3.0|^6.0" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0|^6.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\OhMySmtp\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist new file mode 100644 index 0000000000000..706e4cf3c1339 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + + From cda397c927947ead99322e08679b559f56be3f0e Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Thu, 26 Aug 2021 09:00:35 +0100 Subject: [PATCH 12/13] Fixed underline in changelog, added final to class, renamed package to oh-my-smtp-mailer, --- src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md | 2 +- .../OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php | 2 +- .../OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php | 2 +- .../OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php | 2 +- .../Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php | 2 +- .../Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php | 2 +- src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json | 2 +- .../Component/Mailer/Exception/UnsupportedSchemeException.php | 2 +- .../Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md index 37308ee9aead6..330942c194bd5 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md @@ -2,6 +2,6 @@ CHANGELOG ========= 5.4 ------ +--------- * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php index 48960f4704adf..5ed4c82f685e5 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php @@ -22,7 +22,7 @@ use Symfony\Component\Mime\Email; use Symfony\Contracts\HttpClient\ResponseInterface; -class OhMySmtpApiTransportTest extends TestCase +final class OhMySmtpApiTransportTest extends TestCase { /** * @dataProvider getTransportData diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php index 15def04559b99..20f3e48a20d5c 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpSmtpTransportTest.php @@ -16,7 +16,7 @@ use Symfony\Component\Mailer\Header\TagHeader; use Symfony\Component\Mime\Email; -class OhMySmtpSmtpTransportTest extends TestCase +final class OhMySmtpSmtpTransportTest extends TestCase { public function testCustomHeader() { diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php index 2d8a3073828e3..10445a1176234 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpTransportFactoryTest.php @@ -18,7 +18,7 @@ use Symfony\Component\Mailer\Transport\Dsn; use Symfony\Component\Mailer\Transport\TransportFactoryInterface; -class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase +final class OhMySmtpTransportFactoryTest extends TransportFactoryTestCase { public function getFactory(): TransportFactoryInterface { diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php index d0775b7fab68d..596ea71332fdf 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpApiTransport.php @@ -27,7 +27,7 @@ /** * @author Paul Oms */ -class OhMySmtpApiTransport extends AbstractApiTransport +final class OhMySmtpApiTransport extends AbstractApiTransport { private const HOST = 'app.ohmysmtp.com/api/v1'; diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php index 9d23baeae5724..2cd015a4f8ca6 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Transport/OhMySmtpSmtpTransport.php @@ -23,7 +23,7 @@ /** * @author Paul Oms */ -class OhMySmtpSmtpTransport extends EsmtpTransport +final class OhMySmtpSmtpTransport extends EsmtpTransport { public function __construct(string $id, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) { diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json index 561dba7e405f0..8ff7082908497 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/composer.json @@ -1,5 +1,5 @@ { - "name": "symfony/ohmysmtp-mailer", + "name": "symfony/oh-my-smtp-mailer", "type": "symfony-bridge", "description": "Symfony OhMySMTP Mailer Bridge", "keywords": [], diff --git a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php index 50d6346873207..452b8ba3508a8 100644 --- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php @@ -54,7 +54,7 @@ class UnsupportedSchemeException extends LogicException ], 'ohmysmtp' => [ 'class' => Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory::class, - 'package' => 'symfony/ohmysmtp-mailer', + 'package' => 'symfony/oh-my-smtp-mailer', ], ]; diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index 68b34f871b2e4..54685da7cb772 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -68,7 +68,7 @@ public function messageWhereSchemeIsPartOfSchemeToPackageMapProvider(): \Generat yield ['postmark', 'symfony/postmark-mailer']; yield ['sendgrid', 'symfony/sendgrid-mailer']; yield ['sendinblue', 'symfony/sendinblue-mailer']; - yield ['ohmysmtp', 'symfony/ohmysmtp-mailer']; + yield ['ohmysmtp', 'symfony/oh-my-smtp-mailer']; yield ['ses', 'symfony/amazon-mailer']; } From 2af88d39e8247af5c6e651cbb2ec2983d9e1b4aa Mon Sep 17 00:00:00 2001 From: Paul Oms Date: Thu, 26 Aug 2021 12:49:18 +0100 Subject: [PATCH 13/13] Fix underline & added Array type --- src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md | 2 +- .../OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md index 330942c194bd5..3a08c7ededfcd 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/CHANGELOG.md @@ -2,6 +2,6 @@ CHANGELOG ========= 5.4 ---------- +--- * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php index 5ed4c82f685e5..7f64a8c997fdb 100644 --- a/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php +++ b/src/Symfony/Component/Mailer/Bridge/OhMySmtp/Tests/Transport/OhMySmtpApiTransportTest.php @@ -32,7 +32,7 @@ public function testToString(OhMySmtpApiTransport $transport, string $expected) $this->assertSame($expected, (string) $transport); } - public function getTransportData() + public function getTransportData(): array { return [ [