diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md index 7e7e758dac910..d7057a5bc82ba 100644 --- a/src/Symfony/Component/Mailer/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * Added possibility to register custom transport for dsn by implementing `Symfony\Component\Mailer\Transport\TransportFactoryInterface` and tagging with `mailer.transport_factory` tag in DI. * Added `Symfony\Component\Mailer\Test\TransportFactoryTestCase` to ease testing custom transport factories. + * Added the File transport 4.3.0 ----- diff --git a/src/Symfony/Component/Mailer/Tests/Transport/FileTransportFactoryTest.php b/src/Symfony/Component/Mailer/Tests/Transport/FileTransportFactoryTest.php new file mode 100644 index 0000000000000..c933678a8c0af --- /dev/null +++ b/src/Symfony/Component/Mailer/Tests/Transport/FileTransportFactoryTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Tests\Transport; + +use Symfony\Component\Mailer\Tests\TransportFactoryTestCase; +use Symfony\Component\Mailer\Transport\Dsn; +use Symfony\Component\Mailer\Transport\FileTransport; +use Symfony\Component\Mailer\Transport\FileTransportFactory; +use Symfony\Component\Mailer\Transport\TransportFactoryInterface; + +class FileTransportFactoryTest extends TransportFactoryTestCase +{ + public function getFactory(): TransportFactoryInterface + { + return new FileTransportFactory($this->getDispatcher(), $this->getClient(), $this->getLogger()); + } + + public function supportsProvider(): iterable + { + yield [ + new Dsn('smtp', 'null', null, null, null, ['path' => sys_get_temp_dir().'/symfony/emails']), + true, + ]; + + yield [ + new Dsn('smtp', 'null'), + false, + ]; + + yield [ + new Dsn('smtp', 'example.com'), + false, + ]; + } + + public function createProvider(): iterable + { + $path = sys_get_temp_dir().'/symfony/emails'; + + yield [ + new Dsn('file', 'null', null, null, null, ['path' => $path]), + new FileTransport($path, $this->getDispatcher(), $this->getLogger()), + ]; + } + + public function unsupportedSchemeProvider(): iterable + { + yield [new Dsn('foo', 'null')]; + } +} diff --git a/src/Symfony/Component/Mailer/Tests/Transport/FileTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/FileTransportTest.php new file mode 100644 index 0000000000000..ba58c6226c0d6 --- /dev/null +++ b/src/Symfony/Component/Mailer/Tests/Transport/FileTransportTest.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\Tests\Transport; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Component\Mailer\SmtpEnvelope; +use Symfony\Component\Mailer\Transport\FileTransport; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\RawMessage; + +/** + * @group time-sensitive + */ +class FileTransportTest extends TestCase +{ + public function testSend() + { + $path = sys_get_temp_dir().'/symfony/emails'; + (new Filesystem())->remove($path); + + $transport = new FileTransport($path); + $message = new RawMessage(''); + $envelope = new SmtpEnvelope(new Address('fabien@example.com'), [new Address('helene@example.com')]); + $transport->send($message, $envelope); + + $file = glob($path.'/*')[0]; + /** @var SentMessage $sentMessage */ + $sentMessage = unserialize(file_get_contents($file)); + + $this->assertInstanceOf(SentMessage::class, $sentMessage); + $this->assertEquals($envelope->getSender(), $sentMessage->getEnvelope()->getSender()); + $this->assertEquals($envelope->getRecipients(), $sentMessage->getEnvelope()->getRecipients()); + $this->assertEquals($message, $sentMessage->getMessage()); + } +} diff --git a/src/Symfony/Component/Mailer/Transport/FileTransport.php b/src/Symfony/Component/Mailer/Transport/FileTransport.php new file mode 100644 index 0000000000000..234ac63e27e8f --- /dev/null +++ b/src/Symfony/Component/Mailer/Transport/FileTransport.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\Transport; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Mailer\SentMessage; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * Pretends messages have been sent, but just ignores them. + * + * @author Hugo Alliaume <@kocal> + */ +final class FileTransport extends AbstractTransport +{ + private $path; + + public function __construct(string $path, EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null) + { + parent::__construct($dispatcher, $logger); + $this->path = $path; + if (!file_exists($this->path)) { + if (!mkdir($this->path, 0777, true)) { + throw new \RuntimeException(sprintf('Unable to create path "%s".', $this->path)); + } + } + } + + protected function doSend(SentMessage $message): void + { + $file = $this->path.'/'.uniqid().'.message'; + $serializedMessage = serialize($message); + if (false === file_put_contents($file, $serializedMessage)) { + throw new \RuntimeException(sprintf('Unable to write sent message in file "%s".', $file)); + } + } +} diff --git a/src/Symfony/Component/Mailer/Transport/FileTransportFactory.php b/src/Symfony/Component/Mailer/Transport/FileTransportFactory.php new file mode 100644 index 0000000000000..aa0031646e493 --- /dev/null +++ b/src/Symfony/Component/Mailer/Transport/FileTransportFactory.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\Transport; + +use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; + +/** + * @author Hugo Alliaume <@kocal> + */ +final class FileTransportFactory extends AbstractTransportFactory +{ + public function create(Dsn $dsn): TransportInterface + { + if ('file' === $dsn->getScheme()) { + return new FileTransport($dsn->getOption('path'), $this->dispatcher, $this->logger); + } + + throw new UnsupportedSchemeException($dsn); + } + + public function supports(Dsn $dsn): bool + { + return 'null' === $dsn->getHost() && null !== $dsn->getOption('path'); + } +} diff --git a/src/Symfony/Component/Mailer/composer.json b/src/Symfony/Component/Mailer/composer.json index 5c4ad672a7bc8..eb61c09d8e78d 100644 --- a/src/Symfony/Component/Mailer/composer.json +++ b/src/Symfony/Component/Mailer/composer.json @@ -24,6 +24,7 @@ }, "require-dev": { "symfony/amazon-mailer": "^4.4|^5.0", + "symfony/filesystem": "^4.4|^5.0", "symfony/google-mailer": "^4.4|^5.0", "symfony/http-client-contracts": "^1.1", "symfony/mailgun-mailer": "^4.4|^5.0",