8000 Fix 53941 Add the process to sign the message on a listener · symfony/symfony@0a0611c · GitHub
[go: up one dir, main page]

Skip to content

Commit 0a0611c

Browse files
Fix 53941 Add the process to sign the message on a listener
1 parent 5cabe45 commit 0a0611c

File tree

8 files changed

+289
-0
lines changed

8 files changed

+289
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,36 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl
22002200
->end()
22012201
->end()
22022202
->end()
2203+
->children()
2204+
->arrayNode('dkim_signer')
2205+
->fixXmlConfig('option')
2206+
->canBeEnabled()
2207+
->info('DKIM signer configuration')
2208+
->children()
2209+
->scalarNode('key')->end()
2210+
->scalarNode('domain')->end()
2211+
->scalarNode('select')->end()
2212+
->scalarNode('passphrase')->end()
2213+
->arrayNode('options')
2214+
->performNoDeepMerging()
2215+
->normalizeKeys(false)
2216+
->useAttributeAsKey('name')
2217+
->defaultValue([])
2218+
->prototype('variable')->end()
2219+
->end()
2220+
->end()
2221+
->arrayNode('smime_signer')
2222+
->canBeEnabled()
2223+
->info('SMIME signer configuration')
2224+
->children()
2225+
->scalarNode('key')->end()
2226+
->scalarNode('certificate')->end()
2227+
->scalarNode('passphrase')->end()
2228+
->scalarNode('extra_certificates')->end()
2229+
->scalarNode('sign_options')->end()
2230+
->end()
2231+
->end()
2232+
->end()
22032233
->end()
22042234
->end()
22052235
;

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,6 +2742,31 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
27422742
$container->removeDefinition('mailer.messenger_transport_listener');
27432743
}
27442744

2745+
if ($config['dkim_signer']['enabled']) {
2746+
$dkimSigner = $container->getDefinition('mailer.dkim_signer');
2747+
$dkimSigner->setArgument(0, $config['dkim_signer']['key'] ?? null);
2748+
$dkimSigner->setArgument(1, $config['dkim_signer']['domain'] ?? null);
2749+
$dkimSigner->setArgument(2, $config['dkim_signer']['select'] ?? null);
2750+
$dkimSigner->setArgument(3, $config['dkim_signer']['options'] ?? []);
2751+
$dkimSigner->setArgument(4, $config['dkim_signer']['passphrase'] ?? null);
2752+
2753+
$dkimSignerListener = $container->getDefinition('mailer.dkim_signer.listener');
2754+
$dkimSignerListener->setArgument(0, $dkimSigner ?? null);
2755+
}
2756+
2757+
if ($config['smime_signer']['enabled']) {
2758+
$smimeSigner = $container->getDefinition('mailer.smime_signer');
2759+
$smimeSigner->setArgument(0, $config['smime_signer']['key'] ?? null);
2760+
$smimeSigner->setArgument(1, $config['smime_signer']['certificate'] ?? null);
2761+
$smimeSigner->setArgument(2, $config['smime_signer']['passphrase'] ?? null);
2762+
$smimeSigner->setArgument(3, $config['smime_signer']['extra_certificates'] ?? null);
2763+
$smimeSigner->setArgument(4, $config['smime_signer']['sign_options'] ?? null);
2764+
2765+
$smimeSignerListener = $container->getDefinition('mailer.smime_signer.listener');
2766+
$smimeSignerListener->setArgument(0, $smimeSigner ?? null);
2767+
}
2768+
2769+
27452770
if ($webhookEnabled) {
27462771
$loader->load('mailer_webhook.php');
27472772
}

src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@
1212
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1313

1414
use Symfony\Component\Mailer\Command\MailerTestCommand;
15+
use Symfony\Component\Mailer\EventListener\DkimSignedMessageListener;
1516
use Symfony\Component\Mailer\EventListener\EnvelopeListener;
1617
use Symfony\Component\Mailer\EventListener\MessageListener;
1718
use Symfony\Component\Mailer\EventListener\MessageLoggerListener;
1819
use Symfony\Component\Mailer\EventListener\MessengerTransportListener;
20+
use Symfony\Component\Mailer\EventListener\SmimeSignedMessageListener;
1921
use Symfony\Component\Mailer\Mailer;
2022
use Symfony\Component\Mailer\MailerInterface;
2123
use Symfony\Component\Mailer\Messenger\MessageHandler;
2224
use Symfony\Component\Mailer\Transport;
2325
use Symfony\Component\Mailer\Transport\TransportInterface;
2426
use Symfony\Component\Mailer\Transport\Transports;
27+
use Symfony\Component\Mime\Crypto\DkimSigner;
28+
use Symfony\Component\Mime\Crypto\SMimeSigner;
2529

2630
return static function (ContainerConfigurator $container) {
2731
$container->services()
@@ -78,6 +82,36 @@
7882
->set('mailer.messenger_transport_listener', MessengerTransportListener::class)
7983
->tag('kernel.event_subscriber')
8084

85+
->set('mailer.dkim_signer', DkimSigner::class)
86+
->args([
87+
abstract_arg('key'),
88+
abstract_arg('domain'),
89+
abstract_arg('select'),
90+
abstract_arg('options'),
91+
abstract_arg('passphrase'),
92+
])
93+
94+
->set('mailer.smime_signer', SMimeSigner::class)
95+
->args([
96+
abstract_arg('key'),
97+
abstract_arg('certificate'),
98+
abstract_arg('passphrase'),
99+
abstract_arg('extraCertificates'),
100+
abstract_arg('signOptions'),
101+
])
102+
103+
->set('mailer.dkim_signer.listener', DkimSignedMessageListener::class)
104+
->args([
105+
service('mailer.dkim_signer')->ignoreOnUninitialized(),
106+
])
107+
->tag('kernel.event_subscriber')
108+
109+
->set('mailer.smime_signer.listener', SmimeSignedMessageListener::class)
110+
->args([
111+
service('mailer.smime_signer')->ignoreOnUninitialized(),
112+
])
113+
->tag('kernel.event_subscriber')
114+
81115
->set('console.command.mailer_test', MailerTestCommand::class)
82116
->args([
83117
service('mailer.transports'),

src/Symfony/Component/Mailer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ CHANGELOG
1111

1212
* Make `TransportFactoryTestCase` compatible with PHPUnit 10+
1313
* Support unicode email addresses such as "dømi@dømi.fo"
14+
* Allow adding DKIM or SMIME signer configuration to the mailer
15+
1416

1517
7.1
1618
---
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\Mailer\Event\MessageEvent;
16+
use Symfony\Component\Mime\Crypto\DkimSigner;
17+
use Symfony\Component\Mime\Message;
18+
19+
/**
20+
* Signs the message.
21+
*
22+
* @author Fabien Potencier <fabien@symfony.com>
23+
* @author Elías Fernández
24+
*/
25+
class DkimSignedMessageListener implements EventSubscriberInterface
26+
{
27+
public function __construct(private ?DkimSigner $signer)
28+
{
29+
}
30+
31+
public function onMessage(MessageEvent $event): void
32+
{
33+
$message = $event->getMessage();
34+
if (!$this->signer || !$message instanceof Message) {
35+
return;
36+
}
37+
$event->setMessage($this->signer->sign($message));
38+
}
39+
40+
public static function getSubscribedEvents(): array
41+
{
42+
return [
43+
MessageEvent::class => ['onMessage', -128],
44+
];
45+
}
46+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\Mailer\Event\MessageEvent;
16+
use Symfony\Component\Mime\Crypto\SMimeSigner;
17+
use Symfony\Component\Mime\Message;
18+
19+
/**
20+
* Signs the message.
21+
*
22+
* @author Fabien Potencier <fabien@symfony.com>
23+
* @author Elías Fernández
24+
*/
25+
class SmimeSignedMessageListener implements EventSubscriberInterface
26+
{
27+
public function __construct(private ?SmimeSigner $signer)
28+
{
29+
}
30+
31+
public function onMessage(MessageEvent $event): void
32+
{
33+
$message = $event->getMessage();
34+
if (!$this->signer || !$message instanceof Message) {
35+
return;
36+
}
37+
38+
$event->setMessage($this->signer->sign($message));
39+
}
40+
41+
public static function getSubscribedEvents(): array
42+
{
43+
return [
44+
MessageEvent::class => ['onMessage', -128],
45+
];
46+
}
47+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Tests\EventListener;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Mailer\Envelope;
16+
use Symfony\Component\Mailer\Event\MessageEvent;
17+
use Symfony\Component\Mailer\EventListener\DkimSignedMessageListener;
18+
use Symfony\Component\Mime\Crypto\DkimSigner;
19+
use Symfony\Component\Mime\Address;
20+
use Symfony\Component\Mime\Header\Headers;
21+
use Symfony\Component\Mime\Header\MailboxListHeader;
22+
use Symfony\Component\Mime\Message;
23+
use Symfony\Component\Mime\Part\TextPart;
24+
25+
class DkimSignedMessageListenerTest extends TestCase
26+
{
27+
public function testMessageEqualsWhenNoSigner()
28+
{
29+
$listener = new DkimSignedMessageListener(null);
30+
$message = new Message();
31+
$envelope = new Envelope(new Address('sender@example.com'), [new Address('r1@example.com')]);
32+
$event = new MessageEvent($message, $envelope, 'default');
33+
34+
$listener->onMessage($event);
35+
36+
$this->assertSame($message, $event->getMessage());
37+
}
38+
39+
public function testDkimMessageSigningProcess()
40+
{
41+
$signer = new DkimSigner(<<<HEREDOC
42+
-----BEGIN RSA PRIVATE KEY-----
43+
MIICXAIBAAKBgQDbESTusnjpHAlqnU/zIcNcI1dskQBEG8N4mQo408n33M5FGLxo
44+
WoCQyqnnyujc2gkpG8aiPJFFnToWkbE8H+ursRRLBgdrCQOJh+akPEt4aNqiD/JK
45+
HxLr+1ar9zVUvvPuT4nbrJK44ixEyFbpV+xgiSWWIb8xtsRtoXEoH9yYrQIDAQAB
46+
AoGAGHi00HldamT4ZFGIcdeOtEc6Z+VWy0TytBEchDacdDTVUgCuY1Xg0Mvi6QLQ
47+
uoMczNvOd6ceb1FeANFrpBTIxaM68K/lIUn2fYrtcBpGtbXbSf5hTZhApFiEnQ1u
48+
H2TV+ItW6OYFLtZNY+Vym5/7HrXx/ADHSlMqA3KS8UEN/v0CQQD5RGhrwy92M0wh
49+
2UdSuL5IepjMvpeHcpbJlxtY8jhygnSDmvJtSdgFbP/VSzkYqnlFwXztRRt5F4XT
50+
aUQepFk/AkEA4PvpowzEZk6YnYMQV7qFYARJIB5nLpwCxPbvIooi8adiCuUBwxxe
51+
hRwRM9vHp641safMUaE/T/OovLVEezbHEwJBAOVn0t5SjWywO0HvsRdtlRopUlUk
52+
l1p92E6Bdha/HbotW8P/J1vzmQ8tSKpph4uu4NuU/j9z2ZvxTSXLfHji8osCQCUD
53+
jNaUXSNvvs/7Jg8o0pSPX/B20AbtB8+byI/oJgOXxBuCvZ1551sC2RmtCNXfZVoK
54+
/yRW4PGoZpRVRiT3SB0CQCkSOXB6YoLDagS3X10RInlGkB5pfBd1cG1pQS7YEFjX
55+
Y4x0EYVpNU9oHyeMlLgyevy07udFZXvHItT6WgbspQQ=
56+
-----END RSA PRIVATE KEY-----
57+
HEREDOC, 'symfony.com', 's1');
58+
$listener = new DkimSignedMessageListener($signer);
59+
$message = new Message(
60+
new Headers(
61+
new MailboxListHeader('From', [new Address('sender@example.com')])
62+
),
63+
new TextPart('hello')
64+
);
65+
$envelope = new Envelope(new Address('sender@example.com'), [new Address('r1@example.com')]);
66+
$event = new MessageEvent($message, $envelope, 'default');
67+
68+
$listener->onMessage($event);
69+
$this->assertNotEquals($message, $event->getMessage());
70+
}
71+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Tests\EventListener;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Mailer\Envelope;
16+
use Symfony\Component\Mailer\Event\MessageEvent;
17+
use Symfony\Component\Mailer\EventListener\SmimeSignedMessageListener;
18+
use Symfony\Component\Mime\Address;
19+
use Symfony\Component\Mime\Message;
20+
21+
class SmimeSignedMessageListenerTest extends TestCase
22+
{
23+
public function testMessageEqualsWhenNoSigner()
24+
{
25+
$listener = new SmimeSignedMessageListener(null);
26+
$message = new Message();
27+
$envelope = new Envelope(new Address('sender@example.com'), [new Address('r1@example.com')]);
28+
$event = new Mess 5E99 ageEvent($message, $envelope, 'default');
29+
30+
$listener->onMessage($event);
31+
32+
$this->assertSame($message, $event->getMessage());
33+
}
34+
}

0 commit comments

Comments
 (0)
0