Issue #3165762 by znerol, Berdir, jungle, AdamPS, longwave, smustgrave, imclean, catch, dpi: Add symfony/mailer into core
parent
016718a87f
commit
16feff8e8d
|
@ -41,6 +41,7 @@
|
|||
"symfony/filesystem": "^6.3",
|
||||
"symfony/finder": "^6.3",
|
||||
"symfony/lock": "^6.3",
|
||||
"symfony/mailer": "^6.3",
|
||||
"symfony/phpunit-bridge": "^6.3",
|
||||
"symfony/var-dumper": "^6.3"
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1f03bd567e9e6a240f6bec2e76b7f448",
|
||||
"content-hash": "93842a6c87cec9f144cd50dab29818e7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
|
@ -9138,6 +9138,86 @@
|
|||
],
|
||||
"time": "2023-04-21T12:19:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
"version": "v6.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mailer.git",
|
||||
"reference": "d89611a7830d51b5e118bca38e390dea92f9ea06"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06",
|
||||
"reference": "d89611a7830d51b5e118bca38e390dea92f9ea06",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"egulias/email-validator": "^2.1.10|^3|^4",
|
||||
"php": ">=8.1",
|
||||
"psr/event-dispatcher": "^1",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/event-dispatcher": "^5.4|^6.0",
|
||||
"symfony/mime": "^6.2",
|
||||
"symfony/service-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-client-contracts": "<2.5",
|
||||
"symfony/http-kernel": "<5.4",
|
||||
"symfony/messenger": "<6.2",
|
||||
"symfony/mime": "<6.2",
|
||||
"symfony/twig-bridge": "<6.2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^5.4|^6.0",
|
||||
"symfony/http-client": "^5.4|^6.0",
|
||||
"symfony/messenger": "^6.2",
|
||||
"symfony/twig-bridge": "^6.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mailer\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Helps sending emails",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mailer/tree/v6.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-09-06T09:47:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/phpunit-bridge",
|
||||
"version": "v6.3.0",
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"symfony/filesystem": "^6.3",
|
||||
"symfony/finder": "^6.3",
|
||||
"symfony/lock": "^6.3",
|
||||
"symfony/mailer": "^6.3",
|
||||
"symfony/phpunit-bridge": "^6.3",
|
||||
"symfony/var-dumper": "^6.3"
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
"symfony/filesystem": "v6.3.0",
|
||||
"symfony/finder": "v6.3.0",
|
||||
"symfony/lock": "v6.3.0",
|
||||
"symfony/mailer": "v6.3.5",
|
||||
"symfony/phpunit-bridge": "v6.3.0",
|
||||
"symfony/polyfill-php82": "v1.27.0",
|
||||
"theseer/tokenizer": "1.2.1",
|
||||
|
|
|
@ -500,6 +500,9 @@ services:
|
|||
logger.channel.security:
|
||||
parent: logger.channel_base
|
||||
arguments: ['security']
|
||||
logger.channel.mail:
|
||||
parent: logger.channel_base
|
||||
arguments: ['mail']
|
||||
logger.channel.menu:
|
||||
parent: logger.channel_base
|
||||
arguments: ['menu']
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Core\Mail\Plugin\Mail;
|
||||
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\Core\Mail\MailInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Utility\Error;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* Defines an experimental mail backend, based on the Symfony mailer component.
|
||||
*
|
||||
* This mail plugin acts as a drop-in replacement for the current default PHP
|
||||
* mail plugin. Mail delivery is based on the Symfony mailer component. Hence,
|
||||
* all transports registered by default in the Symfony mailer transport factory
|
||||
* are available via configurable DSN.
|
||||
*
|
||||
* By default, this plugin uses `sendmail://default` as the transport DSN. I.e.,
|
||||
* it attempts to use `/usr/sbin/sendmail -bs` in order to submit a message to
|
||||
* the MTA. Sites hosted on operating systems without a working MTA (e.g.,
|
||||
* Windows) need to configure a suitable DSN.
|
||||
*
|
||||
* The DSN can be set via the `mailer_dsn` key of the `system.mailer` config.
|
||||
*
|
||||
* The following example shows how to switch the default mail plugin to the
|
||||
* experimental Symfony mailer plugin with a custom DSN using config overrides
|
||||
* in `settings.php`:
|
||||
*
|
||||
* @code
|
||||
* $config['system.mail']['interface'] = [ 'default' => 'symfony_mailer' ];
|
||||
* $config['system.mail']['mailer_dsn'] = 'smtp://user:pass@smtp.example.com:25';
|
||||
* @endcode
|
||||
*
|
||||
* Note that special characters in the mailer_dsn need to be URL encoded.
|
||||
*
|
||||
* @see https://symfony.com/doc/current/mailer.html#using-built-in-transports
|
||||
*
|
||||
* @Mail(
|
||||
* id = "symfony_mailer",
|
||||
* label = @Translation("Symfony mailer (Experimental)"),
|
||||
* )
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SymfonyMailer implements MailInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* A list of headers that can contain multiple email addresses.
|
||||
*
|
||||
* @see \Symfony\Component\Mime\Header\Headers::HEADER_CLASS_MAP
|
||||
*/
|
||||
protected const MAILBOX_LIST_HEADERS = ['from', 'to', 'reply-to', 'cc', 'bcc'];
|
||||
|
||||
/**
|
||||
* List of headers to skip copying from the message array.
|
||||
*
|
||||
* Symfony mailer sets Content-Type and Content-Transfer-Encoding according to
|
||||
* the actual body content. Note that format=flowed is not supported by
|
||||
* Symfony.
|
||||
*
|
||||
* @see \Symfony\Component\Mime\Part\TextPart
|
||||
*/
|
||||
protected const SKIP_HEADERS = ['content-type', 'content-transfer-encoding'];
|
||||
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$container->get('logger.channel.mail')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Symfony mailer constructor.
|
||||
*
|
||||
* @param \Psr\Log\LoggerInterface $logger
|
||||
* The logger service.
|
||||
* @param \Symfony\Component\Mailer\MailerInterface $mailer
|
||||
* The mailer service. Only specify an instance in unit tests, pass NULL in
|
||||
* production.
|
||||
*/
|
||||
public function __construct(
|
||||
protected LoggerInterface $logger,
|
||||
protected ?MailerInterface $mailer = NULL) {
|
||||
}
|
||||
|
||||
public function format(array $message) {
|
||||
// Convert any HTML to plain-text.
|
||||
foreach ($message['body'] as &$part) {
|
||||
if ($part instanceof MarkupInterface) {
|
||||
$part = MailFormatHelper::htmlToText($part);
|
||||
}
|
||||
else {
|
||||
$part = MailFormatHelper::wrapMail($part);
|
||||
}
|
||||
}
|
||||
|
||||
// Join the body array into one string.
|
||||
$message['body'] = implode("\n\n", $message['body']);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function mail(array $message) {
|
||||
try {
|
||||
$email = new Email();
|
||||
|
||||
$headers = $email->getHeaders();
|
||||
foreach ($message['headers'] as $name => $value) {
|
||||
if (!in_array(strtolower($name), self::SKIP_HEADERS, TRUE)) {
|
||||
if (in_array(strtolower($name), self::MAILBOX_LIST_HEADERS, TRUE)) {
|
||||
// Split values by comma, but ignore commas encapsulated in double
|
||||
// quotes.
|
||||
$value = str_getcsv($value, ',');
|
||||
}
|
||||
$headers->addHeader($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$email
|
||||
->to($message['to'])
|
||||
->subject($message['subject'])
|
||||
->text($message['body']);
|
||||
|
||||
$mailer = $this->getMailer();
|
||||
$mailer->send($email);
|
||||
return TRUE;
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
Error::logException($this->logger, $e);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a minimalistic Symfony mailer service.
|
||||
*/
|
||||
protected function getMailer(): MailerInterface {
|
||||
if (!isset($this->mailer)) {
|
||||
$dsn = \Drupal::config('system.mail')->get('mailer_dsn');
|
||||
|
||||
// Symfony Mailer and Transport classes both optionally depend on the
|
||||
// event dispatcher. When provided, a MessageEvent is fired whenever an
|
||||
// email is prepared before sending.
|
||||
//
|
||||
// The MessageEvent will likely play an important role in an upcoming mail
|
||||
// API. However, emails handled by this plugin already were processed by
|
||||
// hook_mail and hook_mail_alter. Firing the MessageEvent would leak those
|
||||
// mails into the code path (i.e., event subscribers) of the new API.
|
||||
// Therefore, this plugin deliberately refrains from injecting the event
|
||||
// dispatcher.
|
||||
$transport = Transport::fromDsn($dsn, logger: $this->logger);
|
||||
$this->mailer = new Mailer($transport);
|
||||
}
|
||||
|
||||
return $this->mailer;
|
||||
}
|
||||
|
||||
}
|
|
@ -327,6 +327,7 @@ trait FunctionalTestSetupTrait {
|
|||
// some tests expect to be able to test mail system implementations.
|
||||
$config->getEditable('system.mail')
|
||||
->set('interface.default', 'test_mail_collector')
|
||||
->set('mailer_dsn', 'null://null')
|
||||
->save();
|
||||
|
||||
// By default, verbosely display all errors and disable all production
|
||||
|
|
|
@ -65,6 +65,10 @@ abstract class MigrateUpgradeExecuteTestBase extends MigrateUpgradeTestBase {
|
|||
'value' => 'test_mail_collector',
|
||||
'required' => TRUE,
|
||||
];
|
||||
$settings['config']['system.mail']['mailer_dsn'] = (object) [
|
||||
'value' => 'null://null',
|
||||
'required' => TRUE,
|
||||
];
|
||||
$this->writeSettings($settings);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
interface:
|
||||
default: 'php_mail'
|
||||
mailer_dsn: "sendmail://default"
|
||||
|
|
|
@ -302,6 +302,9 @@ system.mail:
|
|||
sequence:
|
||||
type: string
|
||||
label: 'Interface'
|
||||
mailer_dsn:
|
||||
type: string
|
||||
label: 'Symfony mailer transport DSN'
|
||||
|
||||
system.theme.global:
|
||||
type: theme_settings
|
||||
|
|
|
@ -15,6 +15,12 @@ process:
|
|||
map:
|
||||
DefaultMailSystem: php_mail
|
||||
MailTestCase: test_mail_collector
|
||||
'mailer_dsn':
|
||||
plugin: static_map
|
||||
source: 'mail_system/default-system'
|
||||
map:
|
||||
DefaultMailSystem: 'sendmail://default'
|
||||
MailTestCase: 'null://null'
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.mail
|
||||
|
|
|
@ -158,3 +158,11 @@ function system_post_update_set_blank_log_url_to_null() {
|
|||
->save(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new default mail transport dsn.
|
||||
*/
|
||||
function system_post_update_mailer_dsn_settings() {
|
||||
$config = \Drupal::configFactory()->getEditable('system.mail');
|
||||
$config->set('mailer_dsn', 'sendmail://default')->save();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Update;
|
||||
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests creation of default mail transport dsn settings.
|
||||
*
|
||||
* @see system_post_update_mailer_dsn_settings()
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class MailDsnSettingsUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../fixtures/update/drupal-9.4.0.bare.standard.php.gz',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests system_post_update_mailer_dsn_settings().
|
||||
*/
|
||||
public function testSystemPostUpdateMailerDsnSettings() {
|
||||
$this->runUpdates();
|
||||
|
||||
// Confirm that config was created.
|
||||
$config = $this->config('system.mail');
|
||||
$this->assertEquals('sendmail://default', $config->get('mailer_dsn'));
|
||||
}
|
||||
|
||||
}
|
|
@ -59,6 +59,7 @@ class MigrateSystemConfigurationTest extends MigrateDrupal7TestBase {
|
|||
'interface' => [
|
||||
'default' => 'php_mail',
|
||||
],
|
||||
'mailer_dsn' => 'sendmail://default',
|
||||
],
|
||||
'system.maintenance' => [
|
||||
// langcode is not handled by the migration.
|
||||
|
|
|
@ -197,6 +197,7 @@ abstract class InstallerTestBase extends BrowserTestBase {
|
|||
$this->container->get('config.factory')
|
||||
->getEditable('system.mail')
|
||||
->set('interface.default', 'test_mail_collector')
|
||||
->set('mailer_dsn', 'null://null')
|
||||
->save();
|
||||
|
||||
$this->installDefaultThemeFromClassProperty($this->container);
|
||||
|
|
|
@ -430,6 +430,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
|
|||
// While this should be enforced via settings.php prior to installation,
|
||||
// some tests expect to be able to test mail system implementations.
|
||||
$GLOBALS['config']['system.mail']['interface']['default'] = 'test_mail_collector';
|
||||
$GLOBALS['config']['system.mail']['mailer_dsn'] = 'null://null';
|
||||
|
||||
// Manually configure the default file scheme so that modules that use file
|
||||
// functions don't have to install system and its configuration.
|
||||
|
|
|
@ -119,6 +119,7 @@ class MailManagerTest extends UnitTestCase {
|
|||
$this->configFactory = $this->getConfigFactoryStub([
|
||||
'system.mail' => [
|
||||
'interface' => $interface,
|
||||
'mailer_dsn' => 'null://null',
|
||||
],
|
||||
'system.site' => [
|
||||
'mail' => 'test@example.com',
|
||||
|
|
|
@ -46,6 +46,7 @@ class PhpMailTest extends UnitTestCase {
|
|||
$this->configFactory = $this->getConfigFactoryStub([
|
||||
'system.mail' => [
|
||||
'interface' => [],
|
||||
'mailer_dsn' => 'null://null',
|
||||
],
|
||||
'system.site' => [
|
||||
'mail' => 'test@example.com',
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\Mail\Plugin\Mail;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\Core\Mail\Plugin\Mail\SymfonyMailer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Mail\Plugin\Mail\SymfonyMailer
|
||||
* @group Mail
|
||||
*/
|
||||
class SymfonyMailerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that mixed plain text and html body is converted correctly.
|
||||
*
|
||||
* @covers ::format
|
||||
*/
|
||||
public function testFormatResemblesHtml() {
|
||||
// Populate global $base_path to avoid notices generated by
|
||||
// MailFormatHelper::htmlToMailUrls()
|
||||
global $base_path;
|
||||
$original_base_path = $base_path;
|
||||
$base_path = '/';
|
||||
|
||||
$variables = [
|
||||
'@form-url' => 'https://www.example.com/contact',
|
||||
'@sender-url' => 'https://www.example.com/user/123',
|
||||
'@sender-name' => $this->randomString(),
|
||||
];
|
||||
|
||||
$plain = "In HTML, ampersand must be written as &.\nI saw your house and <wow> it is great. There is too much to say about that beautiful building, it will never fit on one line of text.\nIf a<b and b<c then a<c.";
|
||||
$template = "@sender-name (@sender-url) sent a message using the contact form at @form-url.";
|
||||
$markup = new FormattableMarkup($template, $variables);
|
||||
|
||||
$message = [
|
||||
'body' => [
|
||||
$plain,
|
||||
$markup,
|
||||
],
|
||||
];
|
||||
|
||||
/** @var \Symfony\Component\Mailer\MailerInterface|\PHPUnit\Framework\MockObject\MockObject */
|
||||
$mailer = $this->getMockBuilder(MailerInterface::class)->getMock();
|
||||
|
||||
/** @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
|
||||
$logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
|
||||
|
||||
$plugin = new SymfonyMailer($logger, $mailer);
|
||||
$message = $plugin->format($message);
|
||||
|
||||
$expect = MailFormatHelper::wrapMail($plain . "\n\n" . strtr($template, $variables) . "\n");
|
||||
$this->assertEquals($expect, $message['body']);
|
||||
|
||||
$base_path = $original_base_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sending a mail using a From address with a comma in it.
|
||||
*
|
||||
* @covers ::mail
|
||||
*/
|
||||
public function testMail() {
|
||||
// Setup a mail message.
|
||||
$message = [
|
||||
'id' => 'example_key',
|
||||
'module' => 'example',
|
||||
'key' => 'key',
|
||||
'to' => 'to@example.org',
|
||||
'from' => 'from@example.org',
|
||||
'reply-to' => 'from@example.org',
|
||||
'langcode' => 'en',
|
||||
'params' => [],
|
||||
'send' => TRUE,
|
||||
'subject' => "test\r\nsubject",
|
||||
'body' => '',
|
||||
'headers' => [
|
||||
'MIME-Version' => '1.0',
|
||||
'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
|
||||
'Content-Transfer-Encoding' => '8Bit',
|
||||
'X-Mailer' => 'Drupal',
|
||||
'From' => '"Foo, Bar, and Baz" <from@example.org>',
|
||||
'Reply-to' => 'from@example.org',
|
||||
'Return-Path' => 'from@example.org',
|
||||
],
|
||||
];
|
||||
|
||||
// Verify we use line endings consistent with the PHP mail() function, which
|
||||
// changed with PHP 8. See:
|
||||
// - https://www.drupal.org/node/3270647
|
||||
// - https://bugs.php.net/bug.php?id=81158
|
||||
$line_end = "\r\n";
|
||||
|
||||
/** @var \Symfony\Component\Mailer\MailerInterface|\PHPUnit\Framework\MockObject\MockObject */
|
||||
$mailer = $this->getMockBuilder(MailerInterface::class)->getMock();
|
||||
$mailer->expects($this->once())->method('send')
|
||||
->with(
|
||||
$this->logicalAnd(
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('mime-version')->getBodyAsString() === '1.0'
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->has('content-type') === FALSE
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->has('content-transfer-encoding') === FALSE
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('x-mailer')->getBodyAsString() === 'Drupal'
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('from')->getBodyAsString() === '"Foo, Bar, and Baz" <from@example.org>'
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('reply-to')->getBodyAsString() === 'from@example.org'
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('to')->getBodyAsString() === 'to@example.org'
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getHeaders()->get('subject')->getBodyAsString() === "=?utf-8?Q?test?=$line_end =?utf-8?Q?subject?="
|
||||
),
|
||||
$this->callback(fn (Email $email) =>
|
||||
$email->getTextBody() === ''
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/** @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
|
||||
$logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
|
||||
|
||||
$plugin = new SymfonyMailer($logger, $mailer);
|
||||
$this->assertTrue($plugin->mail($message));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue