diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ca20f15a49619..7507ae392aea1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -2314,8 +2314,8 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl ->canBeEnabled() ->info('S/MIME encrypter configuration') ->children() - ->scalarNode('certificate') - ->info('Path to certificate (in PEM format without the `file://` prefix)') + ->scalarNode('repository') + ->info('Path to the S/MIME certificate repository. Shall implement the `Symfony\Component\Mailer\EventListener\SmimeCertificateRepositoryInterface`.') ->defaultValue('') ->cannotBeEmpty() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4c36bf4dc8f24..331005d634d15 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -2893,11 +2893,9 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co if (!class_exists(SmimeEncryptedMessageListener::class)) { throw new LogicException('S/MIME encrypted messages support cannot be enabled as this version of the Mailer component does not support it.'); } - $smimeDecrypter = $container->getDefinition('mailer.smime_encrypter'); - $smimeDecrypter->setArgument(0, $config['smime_encrypter']['certificate']); - $smimeDecrypter->setArgument(1, $config['smime_encrypter']['cipher']); + $container->setAlias('mailer.smime_encrypter.repository', $config['smime_encrypter']['repository']); + $container->setParameter('mailer.smime_encrypter.cipher', $config['smime_encrypter']['cipher']); } else { - $container->removeDefinition('mailer.smime_encrypter'); $container->removeDefinition('mailer.smime_encrypter.listener'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php index 25b3fefdbfb00..71a43b9c81c3c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php @@ -26,7 +26,6 @@ use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mailer\Transport\Transports; use Symfony\Component\Mime\Crypto\DkimSigner; -use Symfony\Component\Mime\Crypto\SMimeEncrypter; use Symfony\Component\Mime\Crypto\SMimeSigner; return static function (ContainerConfigurator $container) { @@ -102,12 +101,6 @@ abstract_arg('signOptions'), ]) - ->set('mailer.smime_encrypter', SMimeEncrypter::class) - ->args([ - abstract_arg('certificate'), - abstract_arg('cipher'), - ]) - ->set('mailer.dkim_signer.listener', DkimSignedMessageListener::class) ->args([ service(DkimSigner::class), @@ -122,7 +115,8 @@ ->set('mailer.smime_encrypter.listener', SmimeEncryptedMessageListener::class) ->args([ - service('mailer.smime_encrypter'), + service('mailer.smime_encrypter.repository'), + param('mailer.smime_encrypter.cipher'), ]) ->tag('kernel.event_subscriber') diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index b47de331a4775..d961ca97cfd41 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -836,7 +836,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 607049274c7da..c4b273dc83823 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -941,7 +941,7 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor ], 'smime_encrypter' => [ 'enabled' => false, - 'certificate' => '', + 'repository' => '', 'cipher' => null, ], ], diff --git a/src/Symfony/Component/Mailer/EventListener/SmimeCertificateRepositoryInterface.php b/src/Symfony/Component/Mailer/EventListener/SmimeCertificateRepositoryInterface.php new file mode 100644 index 0000000000000..b5d9081a283d6 --- /dev/null +++ b/src/Symfony/Component/Mailer/EventListener/SmimeCertificateRepositoryInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mailer\EventListener; + +/** + * Encrypts messages using S/MIME. + * + * @author Florent Morselli + */ +interface SmimeCertificateRepositoryInterface +{ + /** + * @return ?string The path to the certificate. null if not found + */ + public function findCertificatePathFor(string $email): ?string; +} diff --git a/src/Symfony/Component/Mailer/EventListener/SmimeEncryptedMessageListener.php b/src/Symfony/Component/Mailer/EventListener/SmimeEncryptedMessageListener.php index 3b01c1d1c999b..24bc574e83fbe 100644 --- a/src/Symfony/Component/Mailer/EventListener/SmimeEncryptedMessageListener.php +++ b/src/Symfony/Component/Mailer/EventListener/SmimeEncryptedMessageListener.php @@ -21,10 +21,11 @@ * * @author Elías Fernández */ -class SmimeEncryptedMessageListener implements EventSubscriberInterface +final class SmimeEncryptedMessageListener implements EventSubscriberInterface { public function __construct( - private SMimeEncrypter $encrypter, + private readonly SmimeCertificateRepositoryInterface $smimeRepository, + private readonly ?int $cipher = null, ) { } @@ -34,8 +35,24 @@ public function onMessage(MessageEvent $event): void if (!$message instanceof Message) { return; } + if (!$message->getHeaders()->has('X-SMime-Encrypt')) { + return; + } + $message->getHeaders()->remove('X-SMime-Encrypt'); + $certificatePaths = []; + foreach ($event->getEnvelope()->getRecipients() as $recipient) { + $certificatePath = $this->smimeRepository->findCertificatePathFor($recipient->getAddress()); + if (null === $certificatePath) { + return; + } + $certificatePaths[] = $certificatePath; + } + if (0 === \count($certificatePaths)) { + return; + } + $encrypter = new SMimeEncrypter($certificatePaths, $this->cipher); - $event->setMessage($this->encrypter->encrypt($message)); + $event->setMessage($encrypter->encrypt($message)); } public static function getSubscribedEvents(): array diff --git a/src/Symfony/Component/Mailer/Tests/EventListener/SmimeEncryptedMessageListenerTest.php b/src/Symfony/Component/Mailer/Tests/EventListener/SmimeEncryptedMessageListenerTest.php index 365b55a47dfec..a4c4af73625dd 100644 --- a/src/Symfony/Component/Mailer/Tests/EventListener/SmimeEncryptedMessageListenerTest.php +++ b/src/Symfony/Component/Mailer/Tests/EventListener/SmimeEncryptedMessageListenerTest.php @@ -14,11 +14,12 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Event\MessageEvent; +use Symfony\Component\Mailer\EventListener\SmimeCertificateRepositoryInterface; use Symfony\Component\Mailer\EventListener\SmimeEncryptedMessageListener; use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Crypto\SMimeEncrypter; use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\Part\SMimePart; use Symfony\Component\Mime\Part\TextPart; @@ -28,13 +29,15 @@ class SmimeEncryptedMessageListenerTest extends TestCase /** * @requires extension openssl */ - public function testSmimeMessageSigningProcess() + public function testSmimeMessageEncryptionProcess() { - $encrypter = new SMimeEncrypter(\dirname(__DIR__).'/Fixtures/sign.crt'); - $listener = new SmimeEncryptedMessageListener($encrypter); + $repository = $this->createMock(SmimeCertificateRepositoryInterface::class); + $repository->method('findCertificatePathFor')->willReturn(\dirname(__DIR__).'/Fixtures/sign.crt'); + $listener = new SmimeEncryptedMessageListener($repository); $message = new Message( new Headers( - new MailboxListHeader('From', [new Address('sender@example.com')]) + new MailboxListHeader('From', [new Address('sender@example.com')]), + new UnstructuredHeader('X-SMime-Encrypt', 'true'), ), new TextPart('hello') ); @@ -45,5 +48,59 @@ public function testSmimeMessageSigningProcess() $this->assertNotSame($message, $event->getMessage()); $this->assertInstanceOf(TextPart::class, $message->getBody()); $this->assertInstanceOf(SMimePart::class, $event->getMessage()->getBody()); + $this->assertFalse($event->getMessage()->getHeaders()->has('X-SMime-Encrypt')); + } + + /** + * @requires extension openssl + */ + public function testMessageNotEncryptedWhenOneRecipientCertificateIsMissing() + { + $repository = $this->createMock(SmimeCertificateRepositoryInterface::class); + $repository->method('findCertificatePathFor')->willReturnOnConsecutiveCalls(\dirname(__DIR__).'/Fixtures/sign.crt', null); + $listener = new SmimeEncryptedMessageListener($repository); + $message = new Message( + new Headers( + new MailboxListHeader('From', [new Address('sender@example.com')]), + new UnstructuredHeader('X-SMime-Encrypt', 'true'), + ), + new TextPart('hello') + ); + $envelope = new Envelope(new Address('sender@example.com'), [ + new Address('r1@example.com'), + new Address('r2@example.com'), + ]); + $event = new MessageEvent($message, $envelope, 'default'); + + $listener->onMessage($event); + $this->assertSame($message, $event->getMessage()); + $this->assertInstanceOf(TextPart::class, $message->getBody()); + $this->assertInstanceOf(TextPart::class, $event->getMessage()->getBody()); + } + + /** + * @requires extension openssl + */ + public function testMessageNotExplicitlyAskedForNonEncryption() + { + $repository = $this->createMock(SmimeCertificateRepositoryInterface::class); + $repository->method('findCertificatePathFor')->willReturn(\dirname(__DIR__).'/Fixtures/sign.crt'); + $listener = new SmimeEncryptedMessageListener($repository); + $message = new Message( + new Headers( + new MailboxListHeader('From', [new Address('sender@example.com')]), + ), + new TextPart('hello') + ); + $envelope = new Envelope(new Address('sender@example.com'), [ + new Address('r1@example.com'), + new Address('r2@example.com'), + ]); + $event = new MessageEvent($message, $envelope, 'default'); + + $listener->onMessage($event); + $this->assertSame($message, $event->getMessage()); + $this->assertInstanceOf(TextPart::class, $message->getBody()); + $this->assertInstanceOf(TextPart::class, $event->getMessage()->getBody()); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy