Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7b6d3a2

Browse filesBrowse files
committed
feature #58501 [Mailer] Add configuration for dkim and smime signers (elias-playfinder, eliasfernandez)
This PR was squashed before being merged into the 7.3 branch. Discussion ---------- [Mailer] Add configuration for dkim and smime signers | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | Fix #53941 | License | MIT DKIM is becoming a must have for emails but the current workflow to sign messages on symfony requires to do it in the controller or the application and it causes failures when the email is signed before some other listener needs to get it. This PR adds the needed configuration as part of the mailer configuration and sign all the messages if configured at the mailer level. By instance, we can add these two new blocks under mailer.yml: ```yml framework: mailer: dsn: '%env(MAILER_DSN)%' dkim_signer: key: 'file://private.key' domain: 'symfony.com' select: 's1' passphrase: '' options: ``` or ```yml framework: mailer: dsn: '%env(MAILER_DSN)%' smime_signer: key: '/path/to/certificate-private-key.key' certificate: '/path/to/certificate.crt' passphrase: '' extra_certificates: '/path/to/certificate.crt' sign_options: 1 ``` Commits ------- 244cbf1aad4 [Mailer] Add configuration for dkim and smime signers
2 parents 889f88f + 6ca2456 commit 7b6d3a2
Copy full SHA for 7b6d3a2

File tree

Expand file treeCollapse file tree

5 files changed

+223
-0
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+223
-0
lines changed

‎DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: DependencyInjection/Configuration.php
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,88 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl
22392239
->end()
22402240
->end()
22412241
->end()
2242+
->arrayNode('dkim_signer')
2243+
->addDefaultsIfNotSet()
2244+
->fixXmlConfig('option')
2245+
->canBeEnabled()
2246+
->info('DKIM signer configuration')
2247+
->children()
2248+
->scalarNode('key')
2249+
->info('Key content, or path to key (in PEM format with the `file://` prefix)')
2250+
->defaultValue('')
2251+
->cannotBeEmpty()
2252+
->end()
2253+
->scalarNode('domain')->defaultValue('')->end()
2254+
->scalarNode('select')->defaultValue('')->end()
2255+
->scalarNode('passphrase')
2256+
->info('The private key passphrase')
2257+
->defaultValue('')
2258+
->end()
2259+
->arrayNode('options')
2260+
->performNoDeepMerging()
2261+
->normalizeKeys(false)
2262+
->useAttributeAsKey('name')
2263+
->prototype('variable')->end()
2264+
->end()
2265+
->end()
2266+
->end()
2267+
->arrayNode('smime_signer')
2268+
->addDefaultsIfNotSet()
2269+
->canBeEnabled()
2270+
->info('S/MIME signer configuration')
2271+
->children()
2272+
->scalarNode('key')
2273+
->info('Path to key (in PEM format)')
2274+
->defaultValue('')
2275+
->cannotBeEmpty()
2276+
->end()
2277+
->scalarNode('certificate')
2278+
->info('Path to certificate (in PEM format without the `file://` prefix)')
2279+
->defaultValue('')
2280+
->cannotBeEmpty()
2281+
->end()
2282+
->scalarNode('passphrase')
2283+
->info('The private key passphrase')
2284+
->defaultNull()
2285+
->end()
2286+
->scalarNode('extra_certificates')->defaultNull()->end()
2287+
->integerNode('sign_options')->defaultNull()->end()
2288+
->end()
2289+
->end()
2290+
->arrayNode('smime_encrypter')
2291+
->addDefaultsIfNotSet()
2292+
->canBeEnabled()
2293+
->info('S/MIME encrypter configuration')
2294+
->children()
2295+
->scalarNode('certificate')
2296+
->info('Path to certificate (in PEM format without the `file://` prefix)')
2297+
->defaultValue('')
2298+
->cannotBeEmpty()
2299+
->end()
2300+
->integerNode('cipher')
2301+
->info('A set of algorithms used to encrypt the message')
2302+
->defaultNull()
2303+
->beforeNormalization()
2304+
->always(function ($v): ?int {
2305+
if (null === $v) {
2306+
return null;
2307+
}
2308+
if (\defined('OPENSSL_CIPHER_'.$v)) {
2309+
return \constant('OPENSSL_CIPHER_'.$v);
2310+
}
2311+
2312+
throw new \InvalidArgumentException(\sprintf('"%s" is not a valid OPENSSL cipher.', $v));
2313+
})
2314+
->end()
2315+
->validate()
2316+
->ifTrue(function ($v) {
2317+
return \extension_loaded('openssl') && null !== $v && !\defined('OPENSSL_CIPHER_'.$v);
2318+
})
2319+
->thenInvalid('You must provide a valid cipher.')
2320+
->end()
2321+
->end()
2322+
->end()
2323+
->end()
22422324
->end()
22432325
->end()
22442326
->end()

‎DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: DependencyInjection/FrameworkExtension.php
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@
112112
use Symfony\Component\Lock\Store\StoreFactory;
113113
use Symfony\Component\Mailer\Bridge as MailerBridge;
114114
use Symfony\Component\Mailer\Command\MailerTestCommand;
115+
use Symfony\Component\Mailer\EventListener\DkimSignedMessageListener;
115116
use Symfony\Component\Mailer\EventListener\MessengerTransportListener;
117+
use Symfony\Component\Mailer\EventListener\SmimeEncryptedMessageListener;
118+
use Symfony\Component\Mailer\EventListener\SmimeSignedMessageListener;
116119
use Symfony\Component\Mailer\Mailer;
117120
use Symfony\Component\Mercure\HubRegistry;
118121
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
@@ -2861,6 +2864,48 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
28612864
$container->removeDefinition('mailer.messenger_transport_listener');
28622865
}
28632866

2867+
if ($config['dkim_signer']['enabled']) {
2868+
if (!class_exists(DkimSignedMessageListener::class)) {
2869+
throw new LogicException('DKIM signed messages support cannot be enabled as this version of the Mailer component does not support it.');
2870+
}
2871+
$dkimSigner = $container->getDefinition('mailer.dkim_signer');
2872+
$dkimSigner->setArgument(0, $config['dkim_signer']['key']);
2873+
$dkimSigner->setArgument(1, $config['dkim_signer']['domain']);
2874+
$dkimSigner->setArgument(2, $config['dkim_signer']['select']);
2875+
$dkimSigner->setArgument(3, $config['dkim_signer']['options']);
2876+
$dkimSigner->setArgument(4, $config['dkim_signer']['passphrase']);
2877+
} else {
2878+
$container->removeDefinition('mailer.dkim_signer');
2879+
$container->removeDefinition('mailer.dkim_signer.listener');
2880+
}
2881+
2882+
if ($config['smime_signer']['enabled']) {
2883+
if (!class_exists(SmimeSignedMessageListener::class)) {
2884+
throw new LogicException('SMIME signed messages support cannot be enabled as this version of the Mailer component does not support it.');
2885+
}
2886+
$smimeSigner = $container->getDefinition('mailer.smime_signer');
2887+
$smimeSigner->setArgument(0, $config['smime_signer']['key']);
2888+
$smimeSigner->setArgument(1, $config['smime_signer']['certificate']);
2889+
$smimeSigner->setArgument(2, $config['smime_signer']['passphrase']);
2890+
$smimeSigner->setArgument(3, $config['smime_signer']['extra_certificates']);
2891+
$smimeSigner->setArgument(4, $config['smime_signer']['sign_options']);
2892+
} else {
2893+
$container->removeDefinition('mailer.smime_signer');
2894+
$container->removeDefinition('mailer.smime_signer.listener');
2895+
}
2896+
2897+
if ($config['smime_encrypter']['enabled']) {
2898+
if (!class_exists(SmimeEncryptedMessageListener::class)) {
2899+
throw new LogicException('S/MIME encrypted messages support cannot be enabled as this version of the Mailer component does not support it.');
2900+
}
2901+
$smimeDecrypter = $container->getDefinition('mailer.smime_encrypter');
2902+
$smimeDecrypter->setArgument(0, $config['smime_encrypter']['certificate']);
2903+
$smimeDecrypter->setArgument(1, $config['smime_encrypter']['cipher']);
2904+
} else {
2905+
$container->removeDefinition('mailer.smime_encrypter');
2906+
$container->removeDefinition('mailer.smime_encrypter.listener');
2907+
}
2908+
28642909
if ($webhookEnabled) {
28652910
$loader->load('mailer_webhook.php');
28662911
}

‎Resources/config/mailer.php

Copy file name to clipboardExpand all lines: Resources/config/mailer.php
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,22 @@
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\SmimeEncryptedMessageListener;
21+
use Symfony\Component\Mailer\EventListener\SmimeSignedMessageListener;
1922
use Symfony\Component\Mailer\Mailer;
2023
use Symfony\Component\Mailer\MailerInterface;
2124
use Symfony\Component\Mailer\Messenger\MessageHandler;
2225
use Symfony\Component\Mailer\Transport;
2326
use Symfony\Component\Mailer\Transport\TransportInterface;
2427
use Symfony\Component\Mailer\Transport\Transports;
28+
use Symfony\Component\Mime\Crypto\DkimSigner;
29+
use Symfony\Component\Mime\Crypto\SMimeEncrypter;
30+
use Symfony\Component\Mime\Crypto\SMimeSigner;
2531

2632
return static function (ContainerConfigurator $container) {
2733
$container->services()
@@ -78,6 +84,48 @@
7884
->set('mailer.messenger_transport_listener', MessengerTransportListener::class)
7985
->tag('kernel.event_subscriber')
8086

87+
->set('mailer.dkim_signer', DkimSigner::class)
88+
->args([
89+
abstract_arg('key'),
90+
abstract_arg('domain'),
91+
abstract_arg('select'),
92+
abstract_arg('options'),
93+
abstract_arg('passphrase'),
94+
])
95+
96+
->set('mailer.smime_signer', SMimeSigner::class)
97+
->args([
98+
abstract_arg('key'),
99+
abstract_arg('certificate'),
100+
abstract_arg('passphrase'),
101+
abstract_arg('extraCertificates'),
102+
abstract_arg('signOptions'),
103+
])
104+
105+
->set('mailer.smime_encrypter', SMimeEncrypter::class)
106+
->args([
107+
abstract_arg('certificate'),
108+
abstract_arg('cipher'),
109+
])
110+
111+
->set('mailer.dkim_signer.listener', DkimSignedMessageListener::class)
112+
->args([
113+
service(DkimSigner::class),
114+
])
115+
->tag('kernel.event_subscriber')
116+
117+
->set('mailer.smime_signer.listener', SmimeSignedMessageListener::class)
118+
->args([
119+
service('mailer.smime_signer'),
120+
])
121+
->tag('kernel.event_subscriber')
122+
123+
->set('mailer.smime_encrypter.listener', SmimeEncryptedMessageListener::class)
124+
->args([
125+
service('mailer.smime_encrypter'),
126+
])
127+
->tag('kernel.event_subscriber')
128+
81129
->set('console.command.mailer_test', MailerTestCommand::class)
82130
->args([
83131
service('mailer.transports'),

‎Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: Resources/config/schema/symfony-1.0.xsd
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,9 @@
790790
<xsd:element name="transport" type="mailer_transport" minOccurs="0" maxOccurs="unbounded" />
791791
<xsd:element name="envelope" type="mailer_envelope" minOccurs="0" maxOccurs="1" />
792792
<xsd:element name="header" type="header" minOccurs="0" maxOccurs="unbounded" />
793+
<xsd:element name="dkim-signer" type="mailer_dkim_signer" minOccurs="0" />
794+
<xsd:element name="smime-signer" type="mailer_smime_signer" minOccurs="0" />
795+
<xsd:element name="smime-encrypter" type="mailer_smime_encrypter" minOccurs="0" />
793796
</xsd:sequence>
794797
<xsd:attribute name="enabled" type="xsd:boolean" />
795798
<xsd:attribute name="dsn" type="xsd:string" />
@@ -812,6 +815,30 @@
812815
</xsd:sequence>
813816
</xsd:complexType>
814817

818+
819+
<xsd:complexType name="mailer_dkim_signer">
820+
<xsd:sequence>
821+
<xsd:element name="option" type="metadata" minOccurs="0" maxOccurs="unbounded" />
822+
</xsd:sequence>
823+
<xsd:attribute name="key" type="xsd:string"/>
824+
<xsd:attribute name="domain" type="xsd:string"/>
825+
<xsd:attribute name="select" type="xsd:string"/>
826+
<xsd:attribute name="passphrase" type="xsd:string" />
827+
</xsd:complexType>
828+
829+
<xsd:complexType name="mailer_smime_signer">
830+
<xsd:attribute name="key" type="xsd:string"/>
831+
<xsd:attribute name="certificate" type="xsd:string"/>
832+
<xsd:attribute name="passphrase" type="xsd:string" />
833+
<xsd:attribute name="extraCertificates" type="xsd:string" />
834+
<xsd:attribute name="signOptions" type="xsd:integer" />
835+
</xsd:complexType>
836+
837+
<xsd:complexType name="mailer_smime_encrypter">
838+
<xsd:attribute name="certificate" type="xsd:string"/>
839+
<xsd:attribute name="cipher" type="xsd:integer" />
840+
</xsd:complexType>
841+
815842
<xsd:complexType name="http_cache">
816843
<xsd:sequence>
817844
<xsd:element name="private-header" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />

‎Tests/DependencyInjection/ConfigurationTest.php

Copy file name to clipboardExpand all lines: Tests/DependencyInjection/ConfigurationTest.php
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,27 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
923923
'enabled' => !class_exists(FullStack::class) && class_exists(Mailer::class),
924924
'message_bus' => null,
925925
'headers' => [],
926+
'dkim_signer' => [
927+
'enabled' => false,
928+
'options' => [],
929+
'key' => '',
930+
'domain' => '',
931+
'select' => '',
932+
'passphrase' => '',
933+
],
934+
'smime_signer' => [
935+
'enabled' => false,
936+
'key' => '',
937+
'certificate' => '',
938+
'passphrase' => null,
939+
'extra_certificates' => null,
940+
'sign_options' => null,
941+
],
942+
'smime_encrypter' => [
943+
'enabled' => false,
944+
'certificate' => '',
945+
'cipher' => null,
946+
],
926947
],
927948
'notifier' => [
928949
'enabled' => !class_exists(FullStack::class) && class_exists(Notifier::class),

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.