diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b5d7930ac046c..d7d20d22bb838 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -2623,10 +2623,11 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace', MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', - MailerBridge\Resend\Transport\ResendTransportFactory::class => 'mailer.transport_factory.resend', + MailerBridge\Resend\Transport\SweegoTransportFactory::class => 'mailer.transport_factory.resend', MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => 'mailer.transport_factory.scaleway', MailerBridge\Sendgrid\Transport\SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', MailerBridge\Amazon\Transport\SesTransportFactory::class => 'mailer.transport_factory.amazon', + MailerBridge\Sweego\Transport\SweegoTransportFactory::class => 'mailer.transport_factory.sweego', ]; 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 5434b4c56e6b2..e861c1489ab09 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php @@ -22,7 +22,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; +use Symfony\Component\Mailer\Bridge\Resend\Transport\SweegoTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Transport\AbstractTransportFactory; @@ -56,11 +56,12 @@ 'native' => NativeTransportFactory::class, 'null' => NullTransportFactory::class, 'postmark' => PostmarkTransportFactory::class, - 'resend' => ResendTransportFactory::class, + 'resend' => SweegoTransportFactory::class, 'scaleway' => ScalewayTransportFactory::class, 'sendgrid' => SendgridTransportFactory::class, 'sendmail' => SendmailTransportFactory::class, 'smtp' => EsmtpTransportFactory::class, + 'sweego' => SweegoTransportFactory::class, ]; foreach ($factories as $name => $class) { diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/.gitattributes b/src/Symfony/Component/Mailer/Bridge/Sweego/.gitattributes new file mode 100644 index 0000000000000..14c3c35940427 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.git* export-ignore diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/.gitignore b/src/Symfony/Component/Mailer/Bridge/Sweego/.gitignore new file mode 100644 index 0000000000000..c49a5d8df5c65 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Sweego/CHANGELOG.md new file mode 100644 index 0000000000000..00149ea5ac6f5 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +7.2 +--- + + * Add the bridge diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/LICENSE b/src/Symfony/Component/Mailer/Bridge/Sweego/LICENSE new file mode 100644 index 0000000000000..e374a5c8339d3 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2024-present 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/Sweego/README.md b/src/Symfony/Component/Mailer/Bridge/Sweego/README.md new file mode 100644 index 0000000000000..a7391f4f055af --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/README.md @@ -0,0 +1,25 @@ +Sweego Bridge +============= + +Provides Sweego integration for Symfony Mailer. + +Configuration example: + +```env +# SMTP +MAILER_DSN=sweego+smtp://sweego:API_KEY@default + +# API +MAILER_DSN=sweego+api://API_KEY@default +``` + +where: + - `API_KEY` is your Sweego API Key + +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/Sweego/Tests/Transport/SweegoApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Sweego/Tests/Transport/SweegoApiTransportTest.php new file mode 100644 index 0000000000000..5a1755f997c28 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/Tests/Transport/SweegoApiTransportTest.php @@ -0,0 +1,177 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Sweego\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\JsonMockResponse; +use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoApiTransport; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Header\MetadataHeader; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Contracts\HttpClient\ResponseInterface; + +class SweegoApiTransportTest extends TestCase +{ + /** + * @dataProvider getTransportData + */ + public function testToString(SweegoApiTransport $transport, string $expected) + { + $this->assertSame($expected, (string) $transport); + } + + public static function getTransportData(): \Generator + { + yield [ + new SweegoApiTransport('ACCESS_KEY'), + 'sweego+api://api.sweego.io', + ]; + + yield [ + (new SweegoApiTransport('ACCESS_KEY'))->setHost('example.com'), + 'sweego+api://example.com', + ]; + + yield [ + (new SweegoApiTransport('ACCESS_KEY'))->setHost('example.com')->setPort(99), + 'sweego+api://example.com:99', + ]; + } + + public function testCustomHeader() + { + $params = ['param1' => 'foo', 'param2' => 'bar']; + $json = json_encode(['custom_header_1' => 'custom_value_1']); + + $email = new Email(); + $email->getHeaders() + ->add(new MetadataHeader('custom', $json)) + ->addTextHeader('templateId', 1) + ->addParameterizedHeader('params', 'params', $params) + ->addTextHeader('foo', 'bar'); + $envelope = new Envelope(new Address('alice@system.com', 'Alice'), [new Address('bob@system.com', 'Bob')]); + + $transport = new SweegoApiTransport('ACCESS_KEY'); + $method = new \ReflectionMethod(SweegoApiTransport::class, 'getPayload'); + $payload = $method->invoke($transport, $email, $envelope); + + $this->assertArrayHasKey('X-Metadata-custom', $payload['headers']); + $this->assertEquals($json, $payload['headers']['X-Metadata-custom']); + $this->assertArrayHasKey('templateId', $payload['headers']); + $this->assertEquals('1', $payload['headers']['templateId']); + $this->assertArrayHasKey('params', $payload['headers']); + $this->assertEquals('params; param1=foo; param2=bar', $payload['headers']['params']); + $this->assertArrayHasKey('foo', $payload['headers']); + $this->assertEquals('bar', $payload['headers']['foo']); + } + + public function testSendThrowsForErrorResponse() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://api.sweego.io:8984/send', $url); + $this->assertStringContainsString('Accept: */*', $options['headers'][2] ?? $options['request_headers'][1]); + + return new JsonMockResponse(['message' => 'i\'m a teapot'], [ + 'http_code' => 418, + ]); + }); + + $transport = new SweegoApiTransport('ACCESS_KEY', $client); + $transport->setPort(8984); + + $mail = new Email(); + $mail->subject('Hello!') + ->to(new Address('tony.stark@marvel.com', 'Tony Stark')) + ->from(new Address('fabpot@symfony.com', 'Fabien')) + ->text('Hello There!'); + + $this->expectException(HttpTransportException::class); + $this->expectExceptionMessage('Unable to send an email: {"message":"i\'m a teapot"} (code 418).'); + $transport->send($mail); + } + + public function testSend() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://api.sweego.io:8984/send', $url); + $this->assertStringContainsString('Accept: */*', $options['headers'][2] ?? $options['request_headers'][1]); + + return new JsonMockResponse(['id' => 'foobar'], [ + 'http_code' => 200, + ]); + }); + + $transport = new SweegoApiTransport('ACCESS_KEY', $client); + $transport->setPort(8984); + + $mail = new Email(); + $mail->subject('Hello!') + ->to(new Address('tony.stark@marvel.com', 'Tony Stark')) + ->from(new Address('fabpot@symfony.com', 'Fabien')) + ->text('Hello here!') + ->html('Hello there!') + ->addCc('foo@bar.fr') + ->addBcc('foo@bar.fr') + ; + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } + + /** + * IDN (internationalized domain names) like kältetechnik-xyz.de need to be transformed to ACE + * (ASCII Compatible Encoding) e.g.xn--kltetechnik-xyz-0kb.de, otherwise resend api answers with 400 http code. + */ + public function testSendForIdnDomains() + { + $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface { + $this->assertSame('POST', $method); + $this->assertSame('https://api.sweego.io:8984/send', $url); + $this->assertStringContainsString('Accept: */*', $options['headers'][2] ?? $options['request_headers'][1]); + + $body = json_decode($options['body'], true); + // to + $this->assertSame([ + 'email' => 'kältetechnik@xn--kltetechnik-xyz-0kb.de', + 'name' => 'Kältetechnik Xyz', + ], $body['recipients'][0]); + // sender + $this->assertStringContainsString('info@xn--kltetechnik-xyz-0kb.de', $body['from']['email']); + $this->assertStringContainsString('Kältetechnik Xyz', $body['from']['name']); + + return new JsonMockResponse(['id' => 'foobar'], [ + 'http_code' => 200, + ]); + }); + + $transport = new SweegoApiTransport('ACCESS_KEY', $client); + $transport->setPort(8984); + + $mail = new Email(); + $mail->subject('Hello!') + ->to(new Address('kältetechnik@kältetechnik-xyz.de', 'Kältetechnik Xyz')) + ->from(new Address('info@kältetechnik-xyz.de', 'Kältetechnik Xyz')) + ->text('Hello here!') + ->html('Hello there!'); + + $message = $transport->send($mail); + + $this->assertSame('foobar', $message->getMessageId()); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/Tests/Transport/SweegoTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Sweego/Tests/Transport/SweegoTransportFactoryTest.php new file mode 100644 index 0000000000000..7c2d75a441f9b --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/Tests/Transport/SweegoTransportFactoryTest.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Sweego\Tests\Transport; + +use Psr\Log\NullLogger; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoApiTransport; +use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoSmtpTransport; +use Symfony\Component\Mailer\Bridge\Sweego\Transport\SweegoTransportFactory; +use Symfony\Component\Mailer\Test\TransportFactoryTestCase; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\TransportFactoryInterface; + +class SweegoTransportFactoryTest extends TransportFactoryTestCase +{ + public function getFactory(): TransportFactoryInterface + { + return new SweegoTransportFactory(null, new MockHttpClient(), new NullLogger()); + } + + public static function supportsProvider(): iterable + { + yield [ + new Dsn('sweego', 'default'), + true, + ]; + + yield [ + new Dsn('sweego+smtp', 'default'), + true, + ]; + + yield [ + new Dsn('sweego+smtp', 'example.com'), + true, + ]; + + yield [ + new Dsn('sweego+api', 'default'), + true, + ]; + } + + public static function createProvider(): iterable + { + yield [ + new Dsn('sweego', 'default', self::USER, self::PASSWORD, 465), + new SweegoSmtpTransport('default', 465, self::USER, self::PASSWORD, null, new NullLogger()), + ]; + + yield [ + new Dsn('sweego+smtp', 'default', self::USER, self::PASSWORD, 465), + new SweegoSmtpTransport('default', 465, self::USER, self::PASSWORD, null, new NullLogger()), + ]; + + yield [ + new Dsn('sweego+smtp', 'default', self::USER, self::PASSWORD, 465), + new SweegoSmtpTransport('default', 465, self::USER, self::PASSWORD, null, new NullLogger()), + ]; + + yield [ + new Dsn('sweego+api', 'default', self::USER), + new SweegoApiTransport(self::USER, new MockHttpClient(), null, new NullLogger()), + ]; + } + + public static function unsupportedSchemeProvider(): iterable + { + yield [ + new Dsn('sweego+foo', 'default', self::USER, self::PASSWORD, 465), + 'The "sweego+foo" scheme is not supported; supported schemes for mailer "sweego" are: "sweego", "sweego+smtp", "sweego+api".', + ]; + } + + public static function incompleteDsnProvider(): iterable + { + yield [new Dsn('sweego+smtp', 'default', self::USER)]; + + yield [new Dsn('sweego+api', 'default')]; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoApiTransport.php new file mode 100644 index 0000000000000..022e978ae25b5 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoApiTransport.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Sweego\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Envelope; +use Symfony\Component\Mailer\Exception\HttpTransportException; +use Symfony\Component\Mailer\Exception\InvalidArgumentException; +use Symfony\Component\Mailer\Header\TagHeader; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\Transport\AbstractApiTransport; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Mathieu Santostefano + */ +final class SweegoApiTransport extends AbstractApiTransport +{ + public function __construct( + #[\SensitiveParameter] private readonly string $apiKey, + ?HttpClientInterface $client = null, + ?EventDispatcherInterface $dispatcher = null, + ?LoggerInterface $logger = null, + ) { + parent::__construct($client, $dispatcher, $logger); + } + + public function __toString(): string + { + return sprintf('sweego+api://%s', $this->getEndpoint()); + } + + protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface + { + $response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/send', [ + 'json' => $this->getPayload($email, $envelope), + 'headers' => [ + 'Api-Key' => $this->apiKey, + ], + ]); + + try { + $statusCode = $response->getStatusCode(); + $result = $response->toArray(false); + } catch (DecodingExceptionInterface) { + 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 Sweego server.', $response, 0, $e); + } + + if (200 !== $statusCode) { + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); + } + + $sentMessage->setMessageId($result['id']); + + return $response; + } + + /** + * @param Address[] $addresses + * + * @return list + */ + private function formatAddresses(array $addresses): array + { + return array_map(fn (Address $address) => $this->formatAddress($address), $addresses); + } + + private function getPayload(Email $email, Envelope $envelope): array + { + if (count($email->getHeaders()->toArray()) > 5) { + throw new InvalidArgumentException('Sweego API supports up to 5 headers.'); + } + + $payload = [ + 'from' => $this->formatAddress($envelope->getSender()), + 'recipients' => $this->formatAddresses($this->getRecipients($email, $envelope)), + 'subject' => $email->getSubject(), + ]; + + if ($email->getTextBody()) { + $payload['message-txt'] = $email->getTextBody(); + } + + if ($email->getHtmlBody()) { + $payload['message-html'] = $email->getHtmlBody(); + } + + if ($headers = $this->prepareHeaders($email->getHeaders())) { + $payload['headers'] = array_merge($payload, $headers); + } + + $payload['channel'] = 'email'; + $payload['provider'] = 'sweego'; + + return $payload; + } + + private function prepareHeaders(Headers $headers): array + { + $headersPrepared = []; + foreach ($headers->all() as $header) { + $headersPrepared[$header->getName()] = $header->getBodyAsString(); + } + + return $headersPrepared; + } + + private function formatAddress(Address $address): array + { + $formattedAddress = ['email' => $address->getEncodedAddress()]; + + if ($address->getName()) { + $formattedAddress['name'] = $address->getName(); + } + + return $formattedAddress; + } + + private function getEndpoint(): ?string + { + return ($this->host ?: 'api.sweego.io').($this->port ? ':'.$this->port : ''); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoSmtpTransport.php b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoSmtpTransport.php new file mode 100644 index 0000000000000..8c88790192bb9 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoSmtpTransport.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Sweego\Transport; + +use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; + +/** + * @author Mathieu Santostefano + */ +final class SweegoSmtpTransport extends EsmtpTransport +{ + public function __construct(string $host, int $port, string $login, #[\SensitiveParameter] string $password, ?EventDispatcherInterface $dispatcher = null, ?LoggerInterface $logger = null) + { + parent::__construct($host, $port, true, $dispatcher, $logger); + + $this->setUsername($login); + $this->setPassword($password); + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoTransportFactory.php new file mode 100644 index 0000000000000..7c81c4966c21a --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/Transport/SweegoTransportFactory.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Bridge\Sweego\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 Mathieu Santostefano + */ +final class SweegoTransportFactory extends AbstractTransportFactory +{ + public function create(Dsn $dsn): TransportInterface + { + return match ($dsn->getScheme()) { + 'sweego', 'sweego+smtp' => new SweegoSmtpTransport($dsn->getHost(), $dsn->getPort(), $this->getUser($dsn), $this->getPassword($dsn), $this->dispatcher, $this->logger), + 'sweego+api' => (new SweegoApiTransport($this->getUser($dsn), $this->client, $this->dispatcher, $this->logger)) + ->setHost('default' === $dsn->getHost() ? null : $dsn->getHost()) + ->setPort($dsn->getPort()), + default => throw new UnsupportedSchemeException($dsn, 'sweego', $this->getSupportedSchemes()), + }; + } + + protected function getSupportedSchemes(): array + { + return ['sweego', 'sweego+smtp', 'sweego+api']; + } +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/composer.json b/src/Symfony/Component/Mailer/Bridge/Sweego/composer.json new file mode 100644 index 0000000000000..b25c796c96c09 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/composer.json @@ -0,0 +1,37 @@ +{ + "name": "symfony/sweego-mailer", + "type": "symfony-mailer-bridge", + "description": "Symfony Sweego Mailer Bridge", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Mathieu Santostefano", + "homepage": "https://github.com/welcoMattic" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "symfony/mailer": "^6.4|^7.0" + }, + "require-dev": { + "symfony/http-client": "^6.4|^7.0", + "symfony/http-foundation": "^7.1", + "symfony/webhook": "^6.4|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Sweego\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/src/Symfony/Component/Mailer/Bridge/Sweego/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/Sweego/phpunit.xml.dist new file mode 100644 index 0000000000000..e31a5e51fcde6 --- /dev/null +++ b/src/Symfony/Component/Mailer/Bridge/Sweego/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 5ac0d3d730623..765fba1b90906 100644 --- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php +++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php @@ -61,7 +61,7 @@ class UnsupportedSchemeException extends LogicException 'package' => 'symfony/postmark-mailer', ], 'resend' => [ - 'class' => Bridge\Resend\Transport\ResendTransportFactory::class, + 'class' => Bridge\Resend\Transport\SweegoTransportFactory::class, 'package' => 'symfony/resend-mailer', ], 'scaleway' => [ diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php index 273197646d319..8cb1ab15d1e49 100644 --- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php +++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php @@ -24,7 +24,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; +use Symfony\Component\Mailer\Bridge\Resend\Transport\SweegoTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; @@ -49,7 +49,7 @@ public static function setUpBeforeClass(): void MailjetTransportFactory::class => false, MandrillTransportFactory::class => false, PostmarkTransportFactory::class => false, - ResendTransportFactory::class => false, + SweegoTransportFactory::class => false, ScalewayTransportFactory::class => false, SendgridTransportFactory::class => false, SesTransportFactory::class => false, diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php index 2a290154df6f5..c7d19958aa29f 100644 --- a/src/Symfony/Component/Mailer/Transport.php +++ b/src/Symfony/Component/Mailer/Transport.php @@ -24,7 +24,7 @@ use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory; use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory; use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory; +use Symfony\Component\Mailer\Bridge\Resend\Transport\SweegoTransportFactory; use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory; use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; use Symfony\Component\Mailer\Exception\InvalidArgumentException; @@ -58,7 +58,7 @@ final class Transport MailPaceTransportFactory::class, MandrillTransportFactory::class, PostmarkTransportFactory::class, - ResendTransportFactory::class, + SweegoTransportFactory::class, ScalewayTransportFactory::class, SendgridTransportFactory::class, SesTransportFactory::class,