Commit 2604de30 authored by Benni Mack's avatar Benni Mack Committed by Georg Ringer
Browse files

[!!!][FEATURE] Replace SwiftMailer with symfony/mailer and symfony/mime

SwiftMailer is not in active development anymore
as the author created the successor symfony/mailer
and symfony/mime packages to create and send
emails.

This is a breaking change, as PHP mail() is not
supported anymore. This is now automatically
switched to "sendmail".

In addition \Symfony\Mime\Email has a different
signature than \Swift_Message, which will
cause some trouble, however we've managed
to overcome most of that functionality to
stay backwards-compatible.

Also, all extensions extending from SwiftMailer
will fail as the package is be removed
with this patch.

Spooling has been reimplemented as direct transport
methods (DelayedTransportInterface) instead of
Symfony Messaging for the time being.

Used composer commands:
 * composer require symfony/mailer symfony/mime
 * composer remove swiftmailer/swiftmailer

Resolves: #88643
Releases: master
Change-Id: Ic02db633392f1d0d7b7061e7b322435f892d2c04
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61152


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
parent b58f1f99
......@@ -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": "ab63943f41a231201a3e0b76fa2de7ef",
"content-hash": "7b9b7abce9b3a820cfda31f71cb538c2",
"packages": [
{
"name": "cogpowered/finediff",
......@@ -464,6 +464,63 @@
],
"time": "2014-09-09T13:34:57+00:00"
},
{
"name": "egulias/email-validator",
"version": "2.1.9",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
"reference": "128cc721d771ec2c46ce59698f4ca42b73f71b25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/128cc721d771ec2c46ce59698f4ca42b73f71b25",
"reference": "128cc721d771ec2c46ce59698f4ca42b73f71b25",
"shasum": ""
},
"require": {
"doctrine/lexer": "^1.0.1",
"php": ">= 5.5"
},
"require-dev": {
"dominicsayers/isemail": "dev-master",
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
"satooshi/php-coveralls": "^1.0.1"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Egulias\\EmailValidator\\": "EmailValidator"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eduardo Gulias Davis"
}
],
"description": "A library for validating emails against several RFCs",
"homepage": "https://github.com/egulias/EmailValidator",
"keywords": [
"email",
"emailvalidation",
"emailvalidator",
"validation",
"validator"
],
"time": "2019-06-23T10:14:27+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
......@@ -1188,60 +1245,6 @@
"description": "A polyfill for getallheaders.",
"time": "2016-02-11T07:05:27+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.10",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "dd71cc1638ed7aebbb33f2e2b0edd2cf6ea73d97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/dd71cc1638ed7aebbb33f2e2b0edd2cf6ea73d97",
"reference": "dd71cc1638ed7aebbb33f2e2b0edd2cf6ea73d97",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"mockery/mockery": "~0.9.1",
"symfony/phpunit-bridge": "~3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.4-dev"
}
},
"autoload": {
"files": [
"lib/swift_required.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Corbyn"
},
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "https://swiftmailer.symfony.com",
"keywords": [
"email",
"mail",
"mailer"
],
"time": "2018-07-27T08:58:59+00:00"
},
{
"name": "symfony/cache",
"version": "v4.3.1",
......@@ -1453,6 +1456,134 @@
"homepage": "https://symfony.com",
"time": "2019-06-05T13:25:51+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4e6c670af81c4fb0b6c08b035530a9915d0b691f",
"reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/event-dispatcher-contracts": "^1.1"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "1.1"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/expression-language": "~3.4|~4.0",
"symfony/http-foundation": "^3.4|^4.0",
"symfony/service-contracts": "^1.1",
"symfony/stopwatch": "~3.4|~4.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"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": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2019-05-30T16:10:05+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8fa2cf2177083dd59cf8e44ea4b6541764fbda69",
"reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"suggest": {
"psr/event-dispatcher": "",
"symfony/event-dispatcher-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\EventDispatcher\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to dispatching event",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"time": "2019-05-22T12:23:29+00:00"
},
{
"name": "symfony/expression-language",
"version": "v4.3.1",
......@@ -1686,6 +1817,127 @@
],
"time": "2019-05-30T16:10:05+00:00"
},
{
"name": "symfony/mailer",
"version": "v4.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
"reference": "623c5e5a8303a936a1a265dc08b488ac43977dce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/623c5e5a8303a936a1a265dc08b488ac43977dce",
"reference": "623c5e5a8303a936a1a265dc08b488ac43977dce",
"shasum": ""
},
"require": {
"egulias/email-validator": "^2.0",
"php": "^7.1.3",
"psr/log": "~1.0",
"symfony/event-dispatcher": "^4.3",
"symfony/mime": "^4.3"
},
"require-dev": {
"symfony/amazon-mailer": "^4.3",
"symfony/google-mailer": "^4.3",
"symfony/http-client-contracts": "^1.1",
"symfony/mailchimp-mailer": "^4.3",
"symfony/mailgun-mailer": "^4.3.2",
"symfony/postmark-mailer": "^4.3",
"symfony/sendgrid-mailer": "^4.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
},
"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": "Symfony Mailer Component",
"homepage": "https://symfony.com",
"time": "2019-06-26T08:48:20+00:00"
},
{
"name": "symfony/mime",
"version": "v4.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "ec2c5565de60e03f33d4296a655e3273f0ad1f8b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/ec2c5565de60e03f33d4296a655e3273f0ad1f8b",
"reference": "ec2c5565de60e03f33d4296a655e3273f0ad1f8b",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"egulias/email-validator": "^2.0",
"symfony/dependency-injection": "~3.4|^4.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Mime\\": ""
},
"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": "A library to manipulate MIME messages",
"homepage": "https://symfony.com",
"keywords": [
"mime",
"mime-type"
],
"time": "2019-06-04T09:22:54+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.11.0",
......@@ -5559,134 +5811,6 @@
"homepage": "https://symfony.com",
"time": "2019-05-31T18:55:30+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4e6c670af81c4fb0b6c08b035530a9915d0b691f",
"reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/event-dispatcher-contracts": "^1.1"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "1.1"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/expression-language": "~3.4|~4.0",
"symfony/http-foundation": "^3.4|^4.0",
"symfony/service-contracts": "^1.1",
"symfony/stopwatch": "~3.4|~4.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"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": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2019-05-30T16:10:05+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8fa2cf2177083dd59cf8e44ea4b6541764fbda69",
"reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"suggest": {
"psr/event-dispatcher": "",
"symfony/event-dispatcher-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\EventDispatcher\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to dispatching event",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"time": "2019-05-22T12:23:29+00:00"
},
{
"name": "symfony/filesystem",
"version": "v4.3.1",
......
......@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Backend\Security;
* The TYPO3 project - inspiring people to share!
*/
use Symfony\Component\Mime\Address;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
......@@ -83,19 +84,19 @@ class EmailLoginNotification
}
/**
* Sends an email and returns the number of recipients accepting the email.
* Sends an email.
*
* @param string $recipient
* @param string $subject
* @param string $body
* @return int number of recipients that successfully accepted the email
*/
protected function sendEmail(string $recipient, string $subject, string $body): int
protected function sendEmail(string $recipient, string $subject, string $body): void
{
return GeneralUtility::makeInstance(MailMessage::class)
->setTo($recipient)
->setSubject($subject)
->setBody($body)
$recipients = explode(',', $recipient);
GeneralUtility::makeInstance(MailMessage::class)
->to(...$recipients)
->subject($subject)
->text($body)
->send();
}
......
......@@ -20,13 +20,15 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Mail\DelayedTransportInterface;
use TYPO3\CMS\Core\Mail\FileSpool;
use TYPO3\CMS\Core\Mail\Mailer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Command for sending spooled messages.
*
* Inspired and partially taken from symfony's swiftmailer package.
* Inspired and partially taken from symfony's swiftmailer package, adapted for Symfony/Mailer.
*
* @link https://github.com/symfony/swiftmailer-bundle/blob/master/Command/SendEmailCommand.php
*/
......@@ -41,7 +43,8 @@ class SendEmailCommand extends Command
->setDescription('Sends emails from the spool')
->addOption('message-limit', null, InputOption::VALUE_REQUIRED, 'The maximum number of messages to send.')
->addOption('time-limit', null, InputOption::VALUE_REQUIRED, 'The time limit for sending messages (in seconds).')
->addOption('recover-timeout', null, InputOption::VALUE_REQUIRED, 'The timeout for recovering messages that have taken too long to send (in seconds).');
->addOption('recover-timeout', null, InputOption::VALUE_REQUIRED, 'The timeout for recovering messages that have taken too long to send (in seconds).')
->setAliases(['swiftmailer:spool:send']);
}
/**
......@@ -58,21 +61,18 @@ class SendEmailCommand extends Command
$mailer = $this->getMailer();
$transport = $mailer->getTransport();
if ($transport instanceof \Swift_Transport_SpoolTransport) {
$spool = $transport->getSpool();
if ($spool instanceof \Swift_ConfigurableSpool) {
$spool->setMessageLimit((int)$input->getOption('message-limit'));
$spool->setTimeLimit((int)$input->getOption('time-limit'));
}
if ($spool instanceof \Swift_FileSpool) {
if ($transport instanceof DelayedTransportInterface) {
if ($transport instanceof FileSpool) {
$transport->setMessageLimit((int)$input->getOption('message-limit'));
$transport->setTimeLimit((int)$input->getOption('time-limit'));
$recoverTimeout = (int)$input->getOption('recover-timeout');
if ($recoverTimeout) {
$spool->recover($recoverTimeout);
$transport->recover($recoverTimeout);
} else {
$spool->recover();
$transport->recover();
}
}
$sent = $spool->flushQueue($mailer->getRealTransport());
$sent = $transport->flushQueue($mailer->getRealTransport());
$io->comment($sent . ' emails sent');
} else {
$io->error('The Mailer Transport is not set to "spool".');
......