diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 49821a043de5..35784d3ee2b4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -2642,6 +2642,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
MailerBridge\Mailomat\Transport\MailomatTransportFactory::class => 'mailer.transport_factory.mailomat',
MailerBridge\MailPace\Transport\MailPaceTransportFactory::class => 'mailer.transport_factory.mailpace',
MailerBridge\Mailchimp\Transport\MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp',
+ MailerBridge\Postal\Transport\PostalTransportFactory::class => 'mailer.transport_factory.postal',
MailerBridge\Postmark\Transport\PostmarkTransportFactory::class => 'mailer.transport_factory.postmark',
MailerBridge\Resend\Transport\ResendTransportFactory::class => 'mailer.transport_factory.resend',
MailerBridge\Scaleway\Transport\ScalewayTransportFactory::class => 'mailer.transport_factory.scaleway',
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php
index bdcd7e9c691c..34e688532c77 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php
@@ -22,6 +22,7 @@
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory;
use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory;
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory;
use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory;
@@ -57,6 +58,7 @@
'mailpace' => MailPaceTransportFactory::class,
'native' => NativeTransportFactory::class,
'null' => NullTransportFactory::class,
+ 'postal' => PostalTransportFactory::class,
'postmark' => PostmarkTransportFactory::class,
'resend' => ResendTransportFactory::class,
'scaleway' => ScalewayTransportFactory::class,
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/.gitattributes b/src/Symfony/Component/Mailer/Bridge/Postal/.gitattributes
new file mode 100644
index 000000000000..14c3c3594042
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/.gitattributes
@@ -0,0 +1,3 @@
+/Tests export-ignore
+/phpunit.xml.dist export-ignore
+/.git* export-ignore
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/.gitignore b/src/Symfony/Component/Mailer/Bridge/Postal/.gitignore
new file mode 100644
index 000000000000..c49a5d8df5c6
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/CHANGELOG.md b/src/Symfony/Component/Mailer/Bridge/Postal/CHANGELOG.md
new file mode 100644
index 000000000000..00149ea5ac6f
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/CHANGELOG.md
@@ -0,0 +1,7 @@
+CHANGELOG
+=========
+
+7.2
+---
+
+ * Add the bridge
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/LICENSE b/src/Symfony/Component/Mailer/Bridge/Postal/LICENSE
new file mode 100644
index 000000000000..e374a5c8339d
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/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/Postal/README.md b/src/Symfony/Component/Mailer/Bridge/Postal/README.md
new file mode 100644
index 000000000000..f16ac7d6b0a1
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/README.md
@@ -0,0 +1,24 @@
+Postal Mailer
+=============
+
+Provides [Postal Email](https://docs.postalserver.io/) integration for Symfony Mailer.
+
+Configuration example:
+
+```env
+# API
+MAILER_DSN=postal+api://API_TOKEN@BASE_URL
+```
+
+where:
+ - `API_TOKEN` is your Postal Email API Key
+ - `BASE_URL` is your Postal installation base URL
+
+Resources
+---------
+
+ * [Postal API Docs](https://docs.postalserver.io/developer/api)
+ * [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)
\ No newline at end of file
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalApiTransportTest.php b/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalApiTransportTest.php
new file mode 100644
index 000000000000..6332218249a6
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalApiTransportTest.php
@@ -0,0 +1,107 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Bridge\Postal\Tests\Transport;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\HttpClient\Response\JsonMockResponse;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalApiTransport;
+use Symfony\Component\Mailer\Exception\HttpTransportException;
+use Symfony\Component\Mime\Address;
+use Symfony\Component\Mime\Email;
+use Symfony\Component\Mime\Part\DataPart;
+use Symfony\Contracts\HttpClient\ResponseInterface;
+
+class PostalApiTransportTest extends TestCase
+{
+ /**
+ * @dataProvider getTransportData
+ */
+ public function testToString(PostalApiTransport $transport, string $expected)
+ {
+ $this->assertSame($expected, (string) $transport);
+ }
+
+ public static function getTransportData(): array
+ {
+ return [
+ [
+ (new PostalApiTransport('TOKEN', 'postal.localhost')),
+ 'postal+api://postal.localhost',
+ ],
+ [
+ (new PostalApiTransport('TOKEN', 'postal.localhost'))->setPort(99),
+ 'postal+api://postal.localhost:99',
+ ],
+ ];
+ }
+
+ public function testSend()
+ {
+ $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface {
+ $this->assertSame('POST', $method);
+ $this->assertSame('https://postal.localhost:8984/api/v1/send/message', $url);
+ $this->assertStringContainsString('X-Server-API-Key: TOKEN', $options['headers'][0] ?? $options['request_headers'][0]);
+
+ $body = json_decode($options['body'], true);
+ $this->assertSame('fabpot@symfony.com', $body['from']);
+ $this->assertSame('saif.gmati@symfony.com', $body['to'][0]);
+ $this->assertSame('Hello!', $body['subject']);
+ $this->assertSame('Hello There!', $body['plain_body']);
+ $this->assertSame('
Hello There!
', $body['html_body']);
+ $this->assertCount(1, $body['attachments']);
+ $this->assertSame('attachment.txt', $body['attachments'][0]['name']);
+ $this->assertSame('text/plain', $body['attachments'][0]['content_type']);
+ $this->assertSame(base64_encode('some attachment'), $body['attachments'][0]['data']);
+ $this->assertSame('foo@bar.fr', $body['reply_to']);
+
+ return new JsonMockResponse(['message_id' => 'foobar'], [
+ 'http_code' => 200,
+ ]);
+ });
+ $transport = new PostalApiTransport('TOKEN', 'postal.localhost', $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'))
+ ->replyTo(new Address('foo@bar.fr', 'Foo'))
+ ->text('Hello There!')
+ ->html('Hello There!
')
+ ->addPart(new DataPart('some attachment', 'attachment.txt', 'text/plain'));
+
+ $message = $transport->send($mail);
+
+ $this->assertSame('foobar', $message->getMessageId());
+ }
+
+ public function testSendThrowsForErrorResponse()
+ {
+ $client = new MockHttpClient(function (string $method, string $url, array $options): ResponseInterface {
+ return new JsonMockResponse(['message' => 'i\'m a teapot'], [
+ 'http_code' => 418,
+ ]);
+ });
+ $transport = new PostalApiTransport('TOKEN', 'postal.localhost', $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!');
+
+ $this->expectException(HttpTransportException::class);
+ $this->expectExceptionMessage('Unable to send an email: i\'m a teapot (code 418).');
+ $transport->send($mail);
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalTransportFactoryTest.php b/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalTransportFactoryTest.php
new file mode 100644
index 000000000000..87f181a5e2ef
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/Tests/Transport/PostalTransportFactoryTest.php
@@ -0,0 +1,69 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Bridge\Postal\Tests\Transport;
+
+use Psr\Log\NullLogger;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalApiTransport;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory;
+use Symfony\Component\Mailer\Test\TransportFactoryTestCase;
+use Symfony\Component\Mailer\Transport\Dsn;
+use Symfony\Component\Mailer\Transport\TransportFactoryInterface;
+
+class PostalTransportFactoryTest extends TransportFactoryTestCase
+{
+ public function getFactory(): TransportFactoryInterface
+ {
+ return new PostalTransportFactory(null, new MockHttpClient(), new NullLogger());
+ }
+
+ public static function supportsProvider(): iterable
+ {
+ yield [
+ new Dsn('postal+api', 'postal.localhost'),
+ true,
+ ];
+
+ yield [
+ new Dsn('postal', 'postal.localhost'),
+ true,
+ ];
+ }
+
+ public static function createProvider(): iterable
+ {
+ $logger = new NullLogger();
+
+ yield [
+ new Dsn('postal+api', 'postal.localhost', null, self::PASSWORD),
+ (new PostalApiTransport(self::PASSWORD, 'postal.localhost', new MockHttpClient(), null, $logger)),
+ ];
+
+ yield [
+ new Dsn('postal', 'postal.localhost', null, self::PASSWORD),
+ (new PostalApiTransport(self::PASSWORD, 'postal.localhost', new MockHttpClient(), null, $logger)),
+ ];
+ }
+
+ public static function unsupportedSchemeProvider(): iterable
+ {
+ yield [
+ new Dsn('postal+foo', 'postal.localhost', null, self::PASSWORD),
+ 'The "postal+foo" scheme is not supported; supported schemes for mailer "postal" are: "postal", "postal+api".',
+ ];
+ }
+
+ public static function incompleteDsnProvider(): iterable
+ {
+ yield [new Dsn('postal+api', 'postal.localhost', null)];
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalApiTransport.php
new file mode 100644
index 000000000000..39e087051114
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalApiTransport.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\Postal\Transport;
+
+use Psr\EventDispatcher\EventDispatcherInterface;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Mailer\Envelope;
+use Symfony\Component\Mailer\Exception\HttpTransportException;
+use Symfony\Component\Mailer\SentMessage;
+use Symfony\Component\Mailer\Transport\AbstractApiTransport;
+use Symfony\Component\Mime\Address;
+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;
+
+final class PostalApiTransport extends AbstractApiTransport
+{
+ public function __construct(
+ #[\SensitiveParameter] private string $apiToken,
+ private string $hostName,
+ ?HttpClientInterface $client = null,
+ ?EventDispatcherInterface $dispatcher = null,
+ ?LoggerInterface $logger = null,
+ ) {
+ parent::__construct($client, $dispatcher, $logger);
+ $this->setHost($hostName);
+ }
+
+ public function __toString(): string
+ {
+ return \sprintf('postal+api://%s', $this->getEndpoint());
+ }
+
+ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
+ {
+ $path = \sprintf('/api/v1/send/message');
+
+ $response = $this->client->request('POST', 'https://'.$this->getEndpoint().$path, [
+ 'json' => $this->getPayload($email, $envelope),
+ 'headers' => [
+ 'X-Server-API-Key' => $this->apiToken,
+ ],
+ ]);
+
+ 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 Postal server.', $response, 0, $e);
+ }
+
+ if (200 !== $statusCode) {
+ throw new HttpTransportException('Unable to send an email: '.$result['message'].\sprintf(' (code %d).', $statusCode), $response);
+ }
+
+ $sentMessage->setMessageId($result['message_id']);
+
+ return $response;
+ }
+
+ private function getPayload(Email $email, Envelope $envelope): array
+ {
+ $payload = [
+ 'from' => $envelope->getSender()->getAddress(),
+ 'to' => array_map(fn (Address $address) => $address->getAddress(), $this->getRecipients($email, $envelope)),
+ 'subject' => $email->getSubject(),
+ ];
+ if ($emails = $email->getCc()) {
+ $payload['cc'] = array_map(fn (Address $address) => $address->getAddress(), $emails);
+ }
+ if ($emails = $email->getBcc()) {
+ $payload['bcc'] = array_map(fn (Address $address) => $address->getAddress(), $emails);
+ }
+ if ($email->getTextBody()) {
+ $payload['plain_body'] = $email->getTextBody();
+ }
+ if ($email->getHtmlBody()) {
+ $payload['html_body'] = $email->getHtmlBody();
+ }
+ if ($attachments = $this->prepareAttachments($email)) {
+ $payload['attachments'] = $attachments;
+ }
+ if ($headers = $this->getCustomHeaders($email)) {
+ $payload['headers'] = $headers;
+ }
+ if ($emails = $email->getReplyTo()) {
+ $payload['reply_to'] = $emails[0]->getAddress();
+ }
+
+ return $payload;
+ }
+
+ private function prepareAttachments(Email $email): array
+ {
+ $attachments = [];
+ foreach ($email->getAttachments() as $attachment) {
+ $attachments[] = [
+ 'name' => $attachment->getFilename(),
+ 'content_type' => $attachment->getContentType(),
+ 'data' => base64_encode($attachment->getBody()),
+ ];
+ }
+
+ return $attachments;
+ }
+
+ private function getCustomHeaders(Email $email): array
+ {
+ $headers = [];
+ $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;
+ }
+
+ $headers[] = [
+ 'key' => $header->getName(),
+ 'value' => $header->getBodyAsString(),
+ ];
+ }
+
+ return $headers;
+ }
+
+ private function getEndpoint(): string
+ {
+ return $this->host.($this->port ? ':'.$this->port : '');
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalTransportFactory.php b/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalTransportFactory.php
new file mode 100644
index 000000000000..6467db1cf83c
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/Transport/PostalTransportFactory.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Bridge\Postal\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;
+
+final class PostalTransportFactory extends AbstractTransportFactory
+{
+ public function create(Dsn $dsn): TransportInterface
+ {
+ $scheme = $dsn->getScheme();
+
+ if (!\in_array($scheme, $this->getSupportedSchemes(), true)) {
+ throw new UnsupportedSchemeException($dsn, 'postal', $this->getSupportedSchemes());
+ }
+
+ $host = $dsn->getHost();
+ $port = $dsn->getPort();
+ $apiToken = $this->getPassword($dsn);
+
+ return (new PostalApiTransport($apiToken, $host, $this->client, $this->dispatcher, $this->logger))->setPort($port);
+ }
+
+ protected function getSupportedSchemes(): array
+ {
+ return ['postal', 'postal+api'];
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/composer.json b/src/Symfony/Component/Mailer/Bridge/Postal/composer.json
new file mode 100644
index 000000000000..8c3d3dfe8eda
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/composer.json
@@ -0,0 +1,32 @@
+{
+ "name": "symfony/postal-mailer",
+ "type": "symfony-mailer-bridge",
+ "description": "Symfony Postal Mailer Bridge",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Jonas Claes",
+ "homepage": "https://github.com/jonasclaes"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=8.2",
+ "symfony/mailer": "^7.2"
+ },
+ "require-dev": {
+ "symfony/http-client": "^6.4|^7.0"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Mailer\\Bridge\\Postal\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev"
+}
diff --git a/src/Symfony/Component/Mailer/Bridge/Postal/phpunit.xml.dist b/src/Symfony/Component/Mailer/Bridge/Postal/phpunit.xml.dist
new file mode 100644
index 000000000000..8e264cdc7d0f
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Bridge/Postal/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 07c0ce6cccbe..999477c0360a 100644
--- a/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php
+++ b/src/Symfony/Component/Mailer/Exception/UnsupportedSchemeException.php
@@ -60,6 +60,10 @@ class UnsupportedSchemeException extends LogicException
'class' => Bridge\Mailchimp\Transport\MandrillTransportFactory::class,
'package' => 'symfony/mailchimp-mailer',
],
+ 'postal' => [
+ 'class' => Bridge\Postal\Transport\PostalTransportFactory::class,
+ 'package' => 'symfony/postal-mailer',
+ ],
'postmark' => [
'class' => Bridge\Postmark\Transport\PostmarkTransportFactory::class,
'package' => 'symfony/postmark-mailer',
diff --git a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php
index e28422735eac..1a783d9c9d05 100644
--- a/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php
+++ b/src/Symfony/Component/Mailer/Tests/Exception/UnsupportedSchemeExceptionTest.php
@@ -24,6 +24,7 @@
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory;
use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory;
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory;
use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory;
@@ -50,6 +51,7 @@ public static function setUpBeforeClass(): void
MailjetTransportFactory::class => false,
MailomatTransportFactory::class => false,
MandrillTransportFactory::class => false,
+ PostalTransportFactory::class => false,
PostmarkTransportFactory::class => false,
ResendTransportFactory::class => false,
ScalewayTransportFactory::class => false,
@@ -83,6 +85,7 @@ public static function messageWhereSchemeIsPartOfSchemeToPackageMapProvider(): \
yield ['mailomat', 'symfony/mailomat-mailer'];
yield ['mailpace', 'symfony/mail-pace-mailer'];
yield ['mandrill', 'symfony/mailchimp-mailer'];
+ yield ['postal', 'symfony/postal-mailer'];
yield ['postmark', 'symfony/postmark-mailer'];
yield ['resend', 'symfony/resend-mailer'];
yield ['scaleway', 'symfony/scaleway-mailer'];
diff --git a/src/Symfony/Component/Mailer/Transport.php b/src/Symfony/Component/Mailer/Transport.php
index b2820b029d66..93fc0ba2e6ca 100644
--- a/src/Symfony/Component/Mailer/Transport.php
+++ b/src/Symfony/Component/Mailer/Transport.php
@@ -24,6 +24,7 @@
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
use Symfony\Component\Mailer\Bridge\Mailomat\Transport\MailomatTransportFactory;
use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory;
+use Symfony\Component\Mailer\Bridge\Postal\Transport\PostalTransportFactory;
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
use Symfony\Component\Mailer\Bridge\Resend\Transport\ResendTransportFactory;
use Symfony\Component\Mailer\Bridge\Scaleway\Transport\ScalewayTransportFactory;
@@ -59,6 +60,7 @@ final class Transport
MailomatTransportFactory::class,
MailPaceTransportFactory::class,
MandrillTransportFactory::class,
+ PostalTransportFactory::class,
PostmarkTransportFactory::class,
ResendTransportFactory::class,
ScalewayTransportFactory::class,