Skip to content

Commit

Permalink
[Mailer] Add support for allowing some users even if recipients is …
Browse files Browse the repository at this point in the history
…defined in `EnvelopeListener`
  • Loading branch information
lyrixx committed Feb 23, 2024
1 parent f78f932 commit 876707a
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 2 deletions.
Expand Up @@ -2126,6 +2126,15 @@ private function addMailerSection(ArrayNodeDefinition $rootNode, callable $enabl
->end()
->prototype('scalar')->end()
->end()
->arrayNode('recipients_allowed')
->info('A list of regular expressions that allow recipients when "recipients" option is defined.')
->performNoDeepMerging()
->beforeNormalization()
->ifArray()
->then(fn ($v) => array_filter(array_values($v)))
->end()
->prototype('scalar')->end()
->end()
->end()
->end()
->arrayNode('headers')
Expand Down
Expand Up @@ -2669,6 +2669,7 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
$envelopeListener = $container->getDefinition('mailer.envelope_listener');
$envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null);
$envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null);
$envelopeListener->setArgument(2, $config['envelope']['recipients_allowed'] ?? []);

if ($config['headers']) {
$headers = new Definition(Headers::class);
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Mailer/CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ CHANGELOG

* Dispatch Postmark's "406 - Inactive recipient" API error code as a `PostmarkDeliveryEvent` instead of throwing an exception
* Add DSN param `auto_tls` to disable automatic STARTTLS
* Add support for allowing some users even if `recipients` is defined in `EnvelopeListener`

7.0
---
Expand Down
30 changes: 28 additions & 2 deletions src/Symfony/Component/Mailer/EventListener/EnvelopeListener.php
Expand Up @@ -20,6 +20,7 @@
* Manipulates the Envelope of a Message.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*/
class EnvelopeListener implements EventSubscriberInterface
{
Expand All @@ -30,17 +31,25 @@ class EnvelopeListener implements EventSubscriberInterface
*/
private ?array $recipients = null;

/**
* @var string[]
*/
private array $allowedRecipients;

/**
* @param array<Address|string> $recipients
* @param string[] $allowedRecipients An array of regex to match the allowed recipients
*/
public function __construct(Address|string|null $sender = null, ?array $recipients = null)
public function __construct(Address|string|null $sender = null, ?array $recipients = null, ?array $allowedRecipients = null)
{
if (null !== $sender) {
$this->sender = Address::create($sender);
}
if (null !== $recipients) {
$this->recipients = Address::createArray($recipients);
}

$this->allowedRecipients = $allowedRecipients;
}

public function onMessage(MessageEvent $event): void
Expand All @@ -57,7 +66,24 @@ public function onMessage(MessageEvent $event): void
}

if ($this->recipients) {
$event->getEnvelope()->setRecipients($this->recipients);
$recipients = $this->recipients;
if ($this->allowedRecipients) {
$recipients = [];
$addDefaults = false;
foreach ($event->getEnvelope()->getRecipients() as $recipient) {
foreach ($this->allowedRecipients as $allowedRecipient) {
if (preg_match($allowedRecipient, $recipient->getAddress())) {
$recipients[] = $recipient;
continue 2;
}
}
$addDefaults = true;
}
if ($addDefaults) {
$recipients = array_merge($recipients, $this->recipients);
}
}
$event->getEnvelope()->setRecipients($recipients);
}
}

Expand Down
@@ -0,0 +1,46 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Mailer\Tests\EventListener;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\EventListener\EnvelopeListener;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\RawMessage;

class EnvelopeListenerTest extends TestCase
{
/**
* @dataProvider provideRecipientsTests
*/
public function testRecipients(array $expected, ?array $recipients = null, array $allowedRecipients = [])
{
$listener = new EnvelopeListener(null, $recipients, $allowedRecipients);
$message = new RawMessage('message');
$envelope = new Envelope(new Address('sender@example.com'), [new Address('r1@example.com'), new Address('r2@symfony.com')]);
$event = new MessageEvent($message, $envelope, 'default');

$listener->onMessage($event);

$recipients = array_map(fn (Address $a): string => $a->getAddress(), $event->getEnvelope()->getRecipients());
$this->assertSame($expected, $recipients);
}

public static function provideRecipientsTests(): iterable
{
yield [['r1@example.com', 'r2@symfony.com'], null, []];
yield [['admin@admin.com'], ['admin@admin.com'], []];
yield [['r1@example.com', 'admin@admin.com'], ['admin@admin.com'], ['/@example.com$/']];
yield [['r1@example.com', 'r2@symfony.com'], ['admin@admin.com'], ['/@example.com$/', '/@symfony.com$/']];
}
}

0 comments on commit 876707a

Please sign in to comment.