Replaced swift mailer with symfony mailer

This commit is contained in:
Igor Scheller 2021-12-20 21:07:00 +01:00 committed by msquare
parent f6c86285d9
commit 6a79aaeeaa
18 changed files with 453 additions and 597 deletions

View File

@ -40,9 +40,8 @@
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.1",
"respect/validation": "^1.1",
"swiftmailer/swiftmailer": "^6.2",
"symfony/http-foundation": "^6.0",
"symfony/mime": "^6.0",
"symfony/mailer": "^6.0",
"symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.3",
"vlucas/phpdotenv": "^5.4"

444
composer.lock generated
View File

@ -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": "6382e7e9ba81aa4f0146649008ae6f2d",
"content-hash": "427d326e0e3e19debb1d2c885f2cfbea",
"packages": [
{
"name": "composer/package-versions-deprecated",
@ -2208,6 +2208,56 @@
},
"time": "2021-11-05T16:50:12+00:00"
},
{
"name": "psr/event-dispatcher",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/event-dispatcher.git",
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
"shasum": ""
},
"require": {
"php": ">=7.2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\EventDispatcher\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Standard interfaces for event handling.",
"keywords": [
"events",
"psr",
"psr-14"
],
"support": {
"issues": "https://github.com/php-fig/event-dispatcher/issues",
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
},
"time": "2019-01-08T18:20:26+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
@ -2694,82 +2744,6 @@
},
"time": "2019-05-28T06:10:06+00:00"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v6.3.0",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c",
"reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c",
"shasum": ""
},
"require": {
"egulias/email-validator": "^2.0|^3.1",
"php": ">=7.0.0",
"symfony/polyfill-iconv": "^1.0",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"symfony/phpunit-bridge": "^4.4|^5.4"
},
"suggest": {
"ext-intl": "Needed to support internationalized email addresses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-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"
],
"support": {
"issues": "https://github.com/swiftmailer/swiftmailer/issues",
"source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer",
"type": "tidelift"
}
],
"abandoned": "symfony/mailer",
"time": "2021-10-18T15:26:12+00:00"
},
{
"name": "symfony/console",
"version": "v5.4.1",
@ -2936,6 +2910,168 @@
],
"time": "2021-11-01T23:48:49+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v6.0.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "4f06d19a5f78087061f9de6df3269c139c3d289d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4f06d19a5f78087061f9de6df3269c139c3d289d",
"reference": "4f06d19a5f78087061f9de6df3269c139c3d289d",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"symfony/event-dispatcher-contracts": "^2|^3"
},
"conflict": {
"symfony/dependency-injection": "<5.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/error-handler": "^5.4|^6.0",
"symfony/expression-language": "^5.4|^6.0",
"symfony/http-foundation": "^5.4|^6.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/stopwatch": "^5.4|^6.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v6.0.1"
},
"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": "2021-12-08T15:13:44+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "aa5422287b75594b90ee9cd807caf8f0df491385"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/aa5422287b75594b90ee9cd807caf8f0df491385",
"reference": "aa5422287b75594b90ee9cd807caf8f0df491385",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"psr/event-dispatcher": "^1"
},
"suggest": {
"symfony/event-dispatcher-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"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"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.0"
},
"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": "2021-07-15T12:33:35+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v6.0.1",
@ -3008,6 +3144,80 @@
],
"time": "2021-12-09T12:47:37+00:00"
},
{
"name": "symfony/mailer",
"version": "v6.0.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
"reference": "d0547edd8de59bb30c3fe9db14473ed1fee5ef8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/d0547edd8de59bb30c3fe9db14473ed1fee5ef8a",
"reference": "d0547edd8de59bb30c3fe9db14473ed1fee5ef8a",
"shasum": ""
},
"require": {
"egulias/email-validator": "^2.1.10|^3",
"php": ">=8.0.2",
"psr/event-dispatcher": "^1",
"psr/log": "^1|^2|^3",
"symfony/event-dispatcher": "^5.4|^6.0",
"symfony/mime": "^5.4|^6.0",
"symfony/service-contracts": "^1.1|^2|^3"
},
"conflict": {
"symfony/http-kernel": "<5.4"
},
"require-dev": {
"symfony/http-client-contracts": "^1.1|^2|^3",
"symfony/messenger": "^5.4|^6.0"
},
"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.0.1"
},
"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": "2021-12-08T15:13:44+00:00"
},
{
"name": "symfony/mime",
"version": "v6.0.1",
@ -3168,86 +3378,6 @@
],
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-iconv",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-iconv.git",
"reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/63b5bb7db83e5673936d6e3b8b3e022ff6474933",
"reference": "63b5bb7db83e5673936d6e3b8b3e022ff6474933",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-iconv": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Iconv\\": ""
},
"files": [
"bootstrap.php"
]
},
"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": "Symfony polyfill for the Iconv extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"iconv",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-iconv/tree/v1.23.0"
},
"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": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.23.1",

View File

@ -49,7 +49,7 @@ return [
// Email config
'email' => [
// Can be mail, smtp, sendmail or log
// Can be mail, smtp, sendmail or log or an symfony mailer dsn string like smtps://[usr]:[pass]@smtp.foo.bar:465
'driver' => env('MAIL_DRIVER', 'mail'),
'from' => [
// From address of all emails
@ -59,8 +59,8 @@ return [
'host' => env('MAIL_HOST', 'localhost'),
'port' => env('MAIL_PORT', 587),
// Transport encryption like tls (for starttls) or ssl
'encryption' => env('MAIL_ENCRYPTION', null),
// If tls transport encryption should be used
'tls' => env('MAIL_TLS', null),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'sendmail' => env('MAIL_SENDMAIL', '/usr/sbin/sendmail -bs'),

View File

@ -3,7 +3,7 @@
use Engelsystem\Mail\EngelsystemMailer;
use Engelsystem\Models\User\User;
use Psr\Log\LoggerInterface;
use Swift_SwiftException as SwiftException;
use Symfony\Component\Mailer\Exception\TransportException;
/**
* Display a hint for team/angeltype supporters if there are unconfirmed users for his angeltype.
@ -206,7 +206,7 @@ function user_angeltype_confirm_email(User $user, array $angeltype): void
'emails/angeltype-confirmed',
['name' => $angeltype['name'], 'angeltype' => $angeltype, 'username' => $user->name]
);
} catch (SwiftException $e) {
} catch (TransportException $e) {
/** @var LoggerInterface $logger */
$logger = app('logger');
$logger->error(
@ -236,7 +236,7 @@ function user_angeltype_add_email(User $user, array $angeltype): void
'emails/angeltype-added',
['name' => $angeltype['name'], 'angeltype' => $angeltype, 'username' => $user->name]
);
} catch (SwiftException $e) {
} catch (TransportException $e) {
/** @var LoggerInterface $logger */
$logger = app('logger');
$logger->error(

View File

@ -22,19 +22,20 @@ function engelsystem_email_to_user($recipientUser, $title, $message, $notIfItsMe
$translator = app()->get('translator');
$locale = $translator->getLocale();
$status = true;
try {
/** @var EngelsystemMailer $mailer */
$mailer = app('mailer');
$translator->setLocale($recipientUser->settings->language);
$status = $mailer->sendView(
$mailer->sendView(
$recipientUser->contact->email ? $recipientUser->contact->email : $recipientUser->email,
$title,
'emails/mail',
['username' => $recipientUser->name, 'message' => $message]
);
} catch (Exception $e) {
$status = 0;
$status = false;
engelsystem_log(sprintf(
'An exception occurred while sending a mail to %s in %s:%u: %s',
$recipientUser->name,
@ -51,5 +52,5 @@ function engelsystem_email_to_user($recipientUser, $title, $message, $notIfItsMe
engelsystem_log(sprintf('User %s could not be notified by email due to an error.', $recipientUser->name));
}
return (bool)$status;
return $status;
}

View File

@ -8,7 +8,7 @@ use Engelsystem\Models\User\Settings as UserSettings;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Collection;
use Psr\Log\LoggerInterface;
use Swift_SwiftException as SwiftException;
use Symfony\Component\Mailer\Exception\TransportException;
class News
{
@ -67,7 +67,7 @@ class News
$template,
['title' => $news->title, 'news' => $news, 'username' => $user->name]
);
} catch (SwiftException $e) {
} catch (TransportException $e) {
$this->log->error(
'Unable to send email "{title}" to user {user} with {exception}',
['title' => $subject, 'user' => $user->name, 'exception' => $e]

View File

@ -5,7 +5,7 @@ namespace Engelsystem\Mail;
use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Models\User\User;
use Engelsystem\Renderer\Renderer;
use Swift_Mailer as SwiftMailer;
use Symfony\Component\Mailer\MailerInterface;
class EngelsystemMailer extends Mailer
{
@ -19,11 +19,11 @@ class EngelsystemMailer extends Mailer
protected $subjectPrefix = null;
/**
* @param SwiftMailer $mailer
* @param Renderer $view
* @param Translator $translation
* @param MailerInterface $mailer
* @param Renderer|null $view
* @param Translator|null $translation
*/
public function __construct(SwiftMailer $mailer, Renderer $view = null, Translator $translation = null)
public function __construct(MailerInterface $mailer, Renderer $view = null, Translator $translation = null)
{
parent::__construct($mailer);
@ -37,7 +37,6 @@ class EngelsystemMailer extends Mailer
* @param string $template
* @param array $data
* @param string|null $locale
* @return int
*/
public function sendViewTranslated(
$to,
@ -45,7 +44,7 @@ class EngelsystemMailer extends Mailer
string $template,
array $data = [],
?string $locale = null
): int {
): void {
if ($to instanceof User) {
$locale = $locale ?: $to->settings->language;
$to = $to->contact->email ? $to->contact->email : $to->email;
@ -62,13 +61,11 @@ class EngelsystemMailer extends Mailer
}
$subject = $this->translation ? $this->translation->translate($subject, $data) : $subject;
$sentMails = $this->sendView($to, $subject, $template, $data);
$this->sendView($to, $subject, $template, $data);
if ($activeLocale) {
$this->translation->setLocale($activeLocale);
}
return $sentMails;
}
/**
@ -78,13 +75,12 @@ class EngelsystemMailer extends Mailer
* @param string $subject
* @param string $template
* @param array $data
* @return int
*/
public function sendView($to, string $subject, string $template, array $data = []): int
public function sendView($to, string $subject, string $template, array $data = []): void
{
$body = $this->view->render($template, $data);
return $this->send($to, $subject, $body);
$this->send($to, $subject, $body);
}
/**
@ -93,15 +89,14 @@ class EngelsystemMailer extends Mailer
* @param string|string[] $to
* @param string $subject
* @param string $body
* @return int
*/
public function send($to, string $subject, string $body): int
public function send($to, string $subject, string $body): void
{
if ($this->subjectPrefix) {
$subject = sprintf('[%s] %s', $this->subjectPrefix, trim($subject));
}
return parent::send($to, $subject, $body);
parent::send($to, $subject, $body);
}
/**

View File

@ -2,12 +2,12 @@
namespace Engelsystem\Mail;
use Swift_Mailer as SwiftMailer;
use Swift_Message as SwiftMessage;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
class Mailer
{
/** @var SwiftMailer */
/** @var MailerInterface */
protected $mailer;
/** @var string */
@ -16,7 +16,7 @@ class Mailer
/** @var string */
protected $fromName = null;
public function __construct(SwiftMailer $mailer)
public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}
@ -27,18 +27,16 @@ class Mailer
* @param string|string[] $to
* @param string $subject
* @param string $body
* @return int
*/
public function send($to, string $subject, string $body): int
public function send($to, string $subject, string $body): void
{
/** @var SwiftMessage $message */
$message = $this->mailer->createMessage();
$message->setTo((array)$to)
->setFrom($this->fromAddress, $this->fromName)
->setSubject($subject)
->setBody($body);
$message = (new Email())
->to(...(array)$to)
->from(sprintf('%s <%s>', $this->fromName, $this->fromAddress))
->subject($subject)
->text($body);
return $this->mailer->send($message);
$this->mailer->send($message);
}
/**

View File

@ -5,11 +5,13 @@ namespace Engelsystem\Mail;
use Engelsystem\Config\Config;
use Engelsystem\Container\ServiceProvider;
use Engelsystem\Mail\Transport\LogTransport;
use InvalidArgumentException;
use Swift_Mailer as SwiftMailer;
use Swift_SendmailTransport as SendmailTransport;
use Swift_SmtpTransport as SmtpTransport;
use Swift_Transport as Transport;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Transport\SendmailTransport;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
use Symfony\Component\Mailer\Transport\TransportInterface;
use Symfony\Component\Mailer\Mailer as SymfonyMailer;
class MailerServiceProvider extends ServiceProvider
{
@ -20,13 +22,14 @@ class MailerServiceProvider extends ServiceProvider
$mailConfig = $config->get('email');
$transport = $this->getTransport($mailConfig['driver'], $mailConfig);
$this->app->instance(Transport::class, $transport);
$this->app->instance(TransportInterface::class, $transport);
$this->app->instance('mailer.transport', $transport);
/** @var SwiftMailer $swiftMailer */
$swiftMailer = $this->app->make(SwiftMailer::class);
$this->app->instance(SwiftMailer::class, $swiftMailer);
$this->app->instance('mailer.swift', $swiftMailer);
/** @var SymfonyMailer $symfonyMailer */
$symfonyMailer = $this->app->make(SymfonyMailer::class);
$this->app->instance(SymfonyMailer::class, $symfonyMailer);
$this->app->instance(MailerInterface::class, $symfonyMailer);
$this->app->instance('mailer.symfony', $symfonyMailer);
/** @var EngelsystemMailer $mailer */
$mailer = $this->app->make(EngelsystemMailer::class);
@ -44,7 +47,7 @@ class MailerServiceProvider extends ServiceProvider
/**
* @param string $transport
* @param array $config
* @return Transport
* @return TransportInterface
*/
protected function getTransport($transport, $config)
{
@ -53,12 +56,12 @@ class MailerServiceProvider extends ServiceProvider
return $this->app->make(LogTransport::class);
case 'mail':
case 'sendmail':
return $this->app->make(SendmailTransport::class, ['command' => $config['sendmail']]);
return $this->app->make(SendmailTransport::class, ['command' => $config['sendmail'] ?? null]);
case 'smtp':
return $this->getSmtpTransport($config);
default:
return Transport::fromDsn($transport ?? '');
}
throw new InvalidArgumentException(sprintf('Mail driver "%s" not found', $transport));
}
/**
@ -67,18 +70,18 @@ class MailerServiceProvider extends ServiceProvider
*/
protected function getSmtpTransport(array $config)
{
/** @var SmtpTransport $transport */
$transport = $this->app->make(SmtpTransport::class, [
'host' => $config['host'],
'port' => $config['port'],
'encryption' => $config['encryption'],
/** @var EsmtpTransport $transport */
$transport = $this->app->make(EsmtpTransport::class, [
'host' => $config['host'] ?? 'localhost',
'port' => $config['port'] ?? 0,
'tls' => $config['tls'] ?? null,
]);
if ($config['username']) {
if (!empty($config['username'])) {
$transport->setUsername($config['username']);
}
if ($config['password']) {
if (!empty($config['password'])) {
$transport->setPassword($config['password']);
}

View File

@ -3,9 +3,10 @@
namespace Engelsystem\Mail\Transport;
use Psr\Log\LoggerInterface;
use Swift_Mime_SimpleMessage as SimpleMessage;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
class LogTransport extends Transport
class LogTransport extends AbstractTransport
{
/** @var LoggerInterface */
protected $logger;
@ -13,32 +14,37 @@ class LogTransport extends Transport
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
parent::__construct();
}
/**
* Send the given Message.
* Send the message to log
*
* Recipient/sender data will be retrieved from the Message API.
* The return value is the number of recipients
*
* @param SimpleMessage $message
* @param string[] $failedRecipients An array of failures by-reference
*
* @return int
* @param SentMessage $message
*/
public function send(
SimpleMessage $message,
&$failedRecipients = null
): int {
protected function doSend(SentMessage $message): void
{
$recipients = [];
$messageRecipients = $message->getEnvelope()->getRecipients();
foreach ($messageRecipients as $recipient) {
$recipients[] = $recipient->toString();
}
$this->logger->debug(
'Mail: Send mail "{title}" to "{recipients}":' . PHP_EOL . PHP_EOL . '{content}',
'Mail: Send mail to "{recipients}":' . PHP_EOL . PHP_EOL . '{content}',
[
'title' => $message->getSubject(),
'recipients' => $this->getTo($message),
'recipients' => implode(', ', $recipients),
'content' => $message->toString(),
]
);
}
return count($this->allRecipients($message));
/**
* @return string
*/
public function __toString(): string
{
return 'log://';
}
}

View File

@ -1,109 +0,0 @@
<?php
namespace Engelsystem\Mail\Transport;
use Swift_Events_EventListener;
use Swift_Mime_SimpleMessage as SimpleMessage;
use Swift_Transport as SwiftTransport;
abstract class Transport implements SwiftTransport
{
/**
* Test if this Transport mechanism has started.
*
* @return bool
*/
public function isStarted(): bool
{
return true;
}
/**
* Start this Transport mechanism.
*/
public function start()
{
}
/**
* Stop this Transport mechanism.
*/
public function stop()
{
}
/**
* Check if this Transport mechanism is alive.
*
* If a Transport mechanism session is no longer functional, the method
* returns FALSE. It is the responsibility of the developer to handle this
* case and restart the Transport mechanism manually.
*
* @example
*
* if (!$transport->ping()) {
* $transport->stop();
* $transport->start();
* }
*
* The Transport mechanism will be started, if it is not already.
*
* It is undefined if the Transport mechanism attempts to restart as long as
* the return value reflects whether the mechanism is now functional.
*
* @return bool TRUE if the transport is alive
*/
public function ping(): bool
{
return true;
}
/**
* Register a plugin in the Transport.
*
* @param Swift_Events_EventListener $plugin
*/
public function registerPlugin(Swift_Events_EventListener $plugin)
{
}
/**
* Returns a unified list of all recipients
*
* @param SimpleMessage $message
* @return array
*/
protected function allRecipients(SimpleMessage $message): array
{
return array_merge(
(array)$message->getTo(),
(array)$message->getCc(),
(array)$message->getBcc()
);
}
/**
* Returns a concatenated list of mail recipients
*
* @param SimpleMessage $message
* @return string
*/
protected function getTo(SimpleMessage $message): string
{
return $this->formatTo($this->allRecipients($message));
}
/**
* @param array $recipients
* @return string
*/
protected function formatTo(array $recipients)
{
$list = [];
foreach ($recipients as $address => $name) {
$list[] = $name ? sprintf('%s <%s>', $name, $address) : $address;
}
return implode(',', $list);
}
}

View File

@ -12,7 +12,7 @@ use Engelsystem\Test\Unit\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Psr\Log\Test\TestLogger;
use Swift_SwiftException as SwiftException;
use Symfony\Component\Mailer\Exception\TransportException;
class NewsTest extends TestCase
{
@ -46,11 +46,9 @@ class NewsTest extends TestCase
$this->assertEquals('emails/news-new', $template);
$this->assertEquals('Foo', array_values($data)[0]);
if ($i++ > 0) {
throw new SwiftException('Oops');
if ($i++ > 0) { // On second run
throw new TransportException('Oops');
}
return 1;
});
/** @var News $listener */

View File

@ -11,8 +11,9 @@ use Engelsystem\Renderer\Renderer;
use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Swift_Mailer as SwiftMailer;
use Swift_Message as SwiftMessage;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\RawMessage;
class EngelsystemMailerTest extends TestCase
{
@ -26,18 +27,17 @@ class EngelsystemMailerTest extends TestCase
{
/** @var Renderer|MockObject $view */
$view = $this->createMock(Renderer::class);
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
/** @var MailerInterface|MockObject $symfonyMailer */
$symfonyMailer = $this->getMockForAbstractClass(MailerInterface::class);
/** @var EngelsystemMailer|MockObject $mailer */
$mailer = $this->getMockBuilder(EngelsystemMailer::class)
->setConstructorArgs(['mailer' => $swiftMailer, 'view' => $view])
->setConstructorArgs(['mailer' => $symfonyMailer, 'view' => $view])
->onlyMethods(['send'])
->getMock();
$this->setExpects($mailer, 'send', ['foo@bar.baz', 'Lorem dolor', 'Rendered Stuff!'], 1);
$this->setExpects($mailer, 'send', ['foo@bar.baz', 'Lorem dolor', 'Rendered Stuff!']);
$this->setExpects($view, 'render', ['test/template.tpl', ['dev' => true]], 'Rendered Stuff!');
$return = $mailer->sendView('foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]);
$this->assertEquals(1, $return);
$mailer->sendView('foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]);
}
/**
@ -54,18 +54,18 @@ class EngelsystemMailerTest extends TestCase
/** @var Renderer|MockObject $view */
$view = $this->createMock(Renderer::class);
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
/** @var MailerInterface|MockObject $symfonyMailer */
$symfonyMailer = $this->createMock(MailerInterface::class);
/** @var Translator|MockObject $translator */
$translator = $this->createMock(Translator::class);
/** @var EngelsystemMailer|MockObject $mailer */
$mailer = $this->getMockBuilder(EngelsystemMailer::class)
->setConstructorArgs(['mailer' => $swiftMailer, 'view' => $view, 'translation' => $translator])
->setConstructorArgs(['mailer' => $symfonyMailer, 'view' => $view, 'translation' => $translator])
->onlyMethods(['sendView'])
->getMock();
$this->setExpects($mailer, 'sendView', ['foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]], 1);
$this->setExpects($mailer, 'sendView', ['foo@bar.baz', 'Lorem dolor', 'test/template.tpl', ['dev' => true]]);
$this->setExpects($translator, 'getLocales', null, ['de_DE' => 'de_DE', 'en_US' => 'en_US']);
$this->setExpects($translator, 'getLocale', null, 'en_US');
$this->setExpects($translator, 'translate', ['translatable.text', ['dev' => true]], 'Lorem dolor');
@ -73,14 +73,13 @@ class EngelsystemMailerTest extends TestCase
->method('setLocale')
->withConsecutive(['de_DE'], ['en_US']);
$return = $mailer->sendViewTranslated(
$mailer->sendViewTranslated(
$user,
'translatable.text',
'test/template.tpl',
['dev' => true],
'de_DE'
);
$this->assertEquals(1, $return);
}
/**
@ -90,25 +89,26 @@ class EngelsystemMailerTest extends TestCase
*/
public function testSend()
{
/** @var SwiftMessage|MockObject $message */
$message = $this->createMock(SwiftMessage::class);
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
$this->setExpects($swiftMailer, 'createMessage', null, $message);
$this->setExpects($swiftMailer, 'send', null, 1);
$this->setExpects($message, 'setTo', [['to@xam.pel']], $message);
$this->setExpects($message, 'setFrom', ['foo@bar.baz', 'Lorem Ipsum'], $message);
$this->setExpects($message, 'setSubject', ['[Mail test] Foo Bar'], $message);
$this->setExpects($message, 'setBody', ['Lorem Ipsum!'], $message);
/** @var MailerInterface|MockObject $symfonyMailer */
$symfonyMailer = $this->createMock(MailerInterface::class);
$mailer = new EngelsystemMailer($swiftMailer);
$symfonyMailer->expects($this->once())
->method('send')
->willReturnCallback(function (RawMessage $message, Envelope $envelope = null) {
$this->assertStringContainsString('foo@bar.baz', $message->toString());
$this->assertStringContainsString('Foo Bar', $message->toString());
$this->assertStringContainsString('Mail test', $message->toString());
$this->assertStringContainsString('to@xam.pel', $message->toString());
$this->assertStringContainsString('Lorem Ipsum!', $message->toString());
});
$mailer = new EngelsystemMailer($symfonyMailer);
$mailer->setFromAddress('foo@bar.baz');
$mailer->setFromName('Lorem Ipsum');
$mailer->setFromName('Foo Bar');
$mailer->setSubjectPrefix('Mail test');
$this->assertEquals('Mail test', $mailer->getSubjectPrefix());
$return = $mailer->send('to@xam.pel', 'Foo Bar ', 'Lorem Ipsum!');
$this->assertEquals(1, $return);
$mailer->send('to@xam.pel', 'Foo Bar ', 'Lorem Ipsum!');
}
}

View File

@ -11,10 +11,10 @@ use Engelsystem\Mail\Transport\LogTransport;
use Engelsystem\Test\Unit\ServiceProviderTest;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Swift_Mailer as SwiftMailer;
use Swift_SendmailTransport as SendmailTransport;
use Swift_SmtpTransport as SmtpTransport;
use Swift_Transport as Transport;
use Symfony\Component\Mailer\Mailer as SymfonyMailer;
use Symfony\Component\Mailer\Transport\SendmailTransport;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mailer\Transport\TransportInterface;
class MailerServiceProviderTest extends ServiceProviderTest
{
@ -37,7 +37,7 @@ class MailerServiceProviderTest extends ServiceProviderTest
'driver' => 'smtp',
'host' => 'mail.foo.bar',
'port' => 587,
'encryption' => 'tls',
'tls' => true,
'username' => 'foobar',
'password' => 'LoremIpsum123',
],
@ -53,8 +53,8 @@ class MailerServiceProviderTest extends ServiceProviderTest
$serviceProvider = new MailerServiceProvider($app);
$serviceProvider->register();
$this->assertExistsInContainer(['mailer.transport', Transport::class], $app);
$this->assertExistsInContainer(['mailer.swift', SwiftMailer::class], $app);
$this->assertExistsInContainer(['mailer.transport', TransportInterface::class], $app);
$this->assertExistsInContainer(['mailer.symfony', SymfonyMailer::class], $app);
$this->assertExistsInContainer(['mailer', EngelsystemMailer::class, Mailer::class], $app);
/** @var EngelsystemMailer $mailer */
@ -65,7 +65,7 @@ class MailerServiceProviderTest extends ServiceProviderTest
/** @var SendmailTransport $transport */
$transport = $app->get('mailer.transport');
$this->assertEquals($this->defaultConfig['email']['sendmail'], $transport->getCommand());
$this->assertInstanceOf(SendmailTransport::class, $transport);
}
/**
@ -78,7 +78,7 @@ class MailerServiceProviderTest extends ServiceProviderTest
[SendmailTransport::class, ['email' => ['driver' => 'mail']]],
[SendmailTransport::class, ['email' => ['driver' => 'sendmail']]],
[
SmtpTransport::class,
EsmtpTransport::class,
$this->smtpConfig,
],
];
@ -123,12 +123,9 @@ class MailerServiceProviderTest extends ServiceProviderTest
$serviceProvider = new MailerServiceProvider($app);
$serviceProvider->register();
/** @var SmtpTransport $transport */
/** @var EsmtpTransport $transport */
$transport = $app->get('mailer.transport');
$this->assertEquals($this->smtpConfig['email']['host'], $transport->getHost());
$this->assertEquals($this->smtpConfig['email']['port'], $transport->getPort());
$this->assertEquals($this->smtpConfig['email']['encryption'], $transport->getEncryption());
$this->assertEquals($this->smtpConfig['email']['username'], $transport->getUsername());
$this->assertEquals($this->smtpConfig['email']['password'], $transport->getPassword());
}

View File

@ -5,8 +5,9 @@ namespace Engelsystem\Test\Unit\Mail;
use Engelsystem\Mail\Mailer;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swift_Mailer as SwiftMailer;
use Swift_Message as SwiftMessage;
use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\RawMessage;
class MailerTest extends TestCase
{
@ -19,10 +20,10 @@ class MailerTest extends TestCase
*/
public function testInitAndSettersAndGetters()
{
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
/** @var MailerInterface|MockObject $symfonyMailer */
$symfonyMailer = $this->createMock(MailerInterface::class);
$mailer = new Mailer($swiftMailer);
$mailer = new Mailer($symfonyMailer);
$mailer->setFromName('From Name');
$this->assertEquals('From Name', $mailer->getFromName());
@ -36,42 +37,22 @@ class MailerTest extends TestCase
*/
public function testSend()
{
/** @var SwiftMessage|MockObject $message */
$message = $this->createMock(SwiftMessage::class);
/** @var SwiftMailer|MockObject $swiftMailer */
$swiftMailer = $this->createMock(SwiftMailer::class);
$swiftMailer->expects($this->once())
->method('createMessage')
->willReturn($message);
$swiftMailer->expects($this->once())
/** @var MailerInterface|MockObject $symfonyMailer */
$symfonyMailer = $this->createMock(MailerInterface::class);
$symfonyMailer->expects($this->once())
->method('send')
->willReturn(1);
->willReturnCallback(function (RawMessage $message, Envelope $envelope = null) {
$this->assertStringContainsString('to@xam.pel', $message->toString());
$this->assertStringContainsString('foo@bar.baz', $message->toString());
$this->assertStringContainsString('Test Tester', $message->toString());
$this->assertStringContainsString('Foo Bar', $message->toString());
$this->assertStringContainsString('Lorem Ipsum!', $message->toString());
});
$message->expects($this->once())
->method('setTo')
->with(['to@xam.pel'])
->willReturn($message);
$message->expects($this->once())
->method('setFrom')
->with('foo@bar.baz', 'Lorem Ipsum')
->willReturn($message);
$message->expects($this->once())
->method('setSubject')
->with('Foo Bar')
->willReturn($message);
$message->expects($this->once())
->method('setBody')
->with('Lorem Ipsum!')
->willReturn($message);
$mailer = new Mailer($swiftMailer);
$mailer = new Mailer($symfonyMailer);
$mailer->setFromAddress('foo@bar.baz');
$mailer->setFromName('Lorem Ipsum');
$mailer->setFromName('Test Tester');
$return = $mailer->send('to@xam.pel', 'Foo Bar', 'Lorem Ipsum!');
$this->assertEquals(1, $return);
$mailer->send('to@xam.pel', 'Foo Bar', 'Lorem Ipsum!');
}
}

View File

@ -6,52 +6,39 @@ use Engelsystem\Mail\Transport\LogTransport;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Swift_Mime_SimpleMessage as SimpleMessage;
use Psr\Log\Test\TestLogger;
use Symfony\Component\Mime\Email;
class LogTransportTest extends TestCase
{
/**
* @covers \Engelsystem\Mail\Transport\LogTransport::__construct
* @covers \Engelsystem\Mail\Transport\LogTransport::send
* @covers \Engelsystem\Mail\Transport\LogTransport::doSend
*/
public function testSend()
{
$logger = new TestLogger();
$email = (new Email())
->from('some@email.host')
->to('foo@bar.baz', 'Test Tester <test@example.local>')
->subject('Testing')
->text('Message body');
$transport = new LogTransport($logger);
$transport->send($email);
$this->assertTrue($logger->hasDebugThatContains('Send mail to'));
}
/**
* @covers \Engelsystem\Mail\Transport\LogTransport::__toString
*/
public function testToString()
{
/** @var LoggerInterface|MockObject $logger */
$logger = $this->getMockForAbstractClass(LoggerInterface::class);
/** @var SimpleMessage|MockObject $message */
$message = $this->createMock(SimpleMessage::class);
$message->expects($this->once())
->method('getSubject')
->willReturn('Some subject');
$message->expects($this->once())
->method('toString')
->willReturn("Head: er\n\nMessage body");
$logger->expects($this->once())
->method('debug')
->willReturnCallback(function ($message, $context = []) {
foreach (array_keys($context) as $key) {
$this->assertStringContainsString(sprintf('{%s}', $key), $message);
}
$this->assertEquals('Some subject', $context['title']);
$this->assertEquals('foo@bar.batz,Lorem Ipsum <lor@em.ips>', $context['recipients']);
$this->assertStringContainsString('Head: er', $context['content']);
$this->assertStringContainsString('Message body', $context['content']);
});
/** @var LogTransport|MockObject $transport */
$transport = $this->getMockBuilder(LogTransport::class)
->setConstructorArgs(['logger' => $logger])
->onlyMethods(['allRecipients'])
->getMock();
$transport->expects($this->exactly(2))
->method('allRecipients')
->with($message)
->willReturn(['foo@bar.batz' => null, 'lor@em.ips' => 'Lorem Ipsum']);
$return = $transport->send($message);
$this->assertEquals(2, $return);
$transport = new LogTransport($logger);
$this->assertEquals('log://', (string)$transport);
}
}

View File

@ -1,35 +0,0 @@
<?php
namespace Engelsystem\Test\Unit\Mail\Transport\Stub;
use Engelsystem\Mail\Transport\Transport;
use Swift_Mime_SimpleMessage as SimpleMessage;
class TransportImplementation extends Transport
{
/**
* {@inheritdoc}
*/
public function send(SimpleMessage $message, &$failedRecipients = null)
{
return 0;
}
/**
* @param SimpleMessage $message
* @return array
*/
public function getAllRecipients(SimpleMessage $message)
{
return $this->allRecipients($message);
}
/**
* @param SimpleMessage $message
* @return string
*/
public function getGetTo(SimpleMessage $message)
{
return $this->getTo($message);
}
}

View File

@ -1,95 +0,0 @@
<?php
namespace Engelsystem\Test\Unit\Mail\Transport;
use Engelsystem\Test\Unit\Mail\Transport\Stub\TransportImplementation;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swift_Events_EventListener;
use Swift_Mime_SimpleMessage as SimpleMessage;
class TransportTest extends TestCase
{
/**
* @covers \Engelsystem\Mail\Transport\Transport::isStarted
* @covers \Engelsystem\Mail\Transport\Transport::ping
* @covers \Engelsystem\Mail\Transport\Transport::registerPlugin
* @covers \Engelsystem\Mail\Transport\Transport::start
* @covers \Engelsystem\Mail\Transport\Transport::stop
*/
public function testMethods()
{
/** @var Swift_Events_EventListener|MockObject $plugin */
$plugin = $this->getMockForAbstractClass(Swift_Events_EventListener::class);
$transport = new TransportImplementation();
$transport->start();
$transport->registerPlugin($plugin);
$this->assertTrue($transport->isStarted());
$this->assertTrue($transport->ping());
$transport->stop();
}
/**
* @covers \Engelsystem\Mail\Transport\Transport::allRecipients
*/
public function testAllRecipients()
{
/** @var SimpleMessage|MockObject $message */
$message = $this->createMock(SimpleMessage::class);
$transport = new TransportImplementation();
$message->expects($this->once())
->method('getTo')
->willReturn([
'foo@bar.batz' => 'Foo Bar',
'lorem@ipsum.dolor' => null,
]);
$message->expects($this->once())
->method('getCc')
->willReturn([
'to@bar.batz' => null,
]);
$message->expects($this->once())
->method('getBcc')
->willReturn([
'secret@bar.batz' => 'I\'m secret!',
]);
$this->assertEquals(
[
'foo@bar.batz' => 'Foo Bar',
'lorem@ipsum.dolor' => null,
'to@bar.batz' => null,
'secret@bar.batz' => 'I\'m secret!',
],
$transport->getAllRecipients($message)
);
}
/**
* @covers \Engelsystem\Mail\Transport\Transport::formatTo
* @covers \Engelsystem\Mail\Transport\Transport::getTo
*/
public function testGetTo()
{
/** @var SimpleMessage|MockObject $message */
$message = $this->createMock(SimpleMessage::class);
/** @var TransportImplementation|MockObject $transport */
$transport = $this->getMockBuilder(TransportImplementation::class)
->onlyMethods(['allRecipients'])
->getMock();
$transport->expects($this->once())
->method('allRecipients')
->with($message)
->willReturn([
'foo@bar.batz' => null,
'lorem@ipsum.dolor' => 'Developer',
]);
$return = $transport->getGetTo($message);
$this->assertEquals('foo@bar.batz,Developer <lorem@ipsum.dolor>', $return);
}
}