From 46d8a7333b9b77ccc440afd0a3c3fe7c5bc3901c Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Thu, 7 Nov 2024 11:02:17 +0100 Subject: [PATCH 1/4] feat(Mailer): implement caching Currently $this->instance is never set, so the code is no-op. This brings back caching of the instance. Caching broke with be7db1573dc8c6e7309ec9db124a7a74b8b41199 Swift to \Swift_Mailer as abstraction Signed-off-by: Thomas Lehmann --- lib/private/Mail/Mailer.php | 4 +++- tests/lib/Mail/MailerTest.php | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php index da3fcd3588871..b0c08815f1ef0 100644 --- a/lib/private/Mail/Mailer.php +++ b/lib/private/Mail/Mailer.php @@ -267,7 +267,9 @@ protected function getInstance(): MailerInterface { break; } - return new SymfonyMailer($transport); + $this->instance = new SymfonyMailer($transport); + + return $this->instance; } /** diff --git a/tests/lib/Mail/MailerTest.php b/tests/lib/Mail/MailerTest.php index f215e385e3f75..84015f38d242c 100644 --- a/tests/lib/Mail/MailerTest.php +++ b/tests/lib/Mail/MailerTest.php @@ -337,4 +337,10 @@ public function testLocalDomainInvalidUrl(): void { self::assertInstanceOf(EsmtpTransport::class, $transport); self::assertEquals('[127.0.0.1]', $transport->getLocalDomain()); } + + public function testCaching(): void { + $symfonyMailer1 = self::invokePrivate($this->mailer, 'getInstance'); + $symfonyMailer2 = self::invokePrivate($this->mailer, 'getInstance'); + self::assertSame($symfonyMailer1, $symfonyMailer2); + } } From 40211f3d0748983c294dcfffa56f4022bd69d28e Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Thu, 7 Nov 2024 11:05:11 +0100 Subject: [PATCH 2/4] chore(Mailer): remove no-op local variable initilization The IDE hinted the value is immediately overwritten. Signed-off-by: Thomas Lehmann --- lib/private/Mail/Mailer.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php index b0c08815f1ef0..b660ee0c02fd2 100644 --- a/lib/private/Mail/Mailer.php +++ b/lib/private/Mail/Mailer.php @@ -255,8 +255,6 @@ protected function getInstance(): MailerInterface { return $this->instance; } - $transport = null; - switch ($this->config->getSystemValueString('mail_smtpmode', 'smtp')) { case 'sendmail': $transport = $this->getSendMailInstance(); From e4c013d86d0802865aa2bac8fdda354cd2642788 Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Tue, 29 Oct 2024 11:53:18 +0100 Subject: [PATCH 3/4] feat(Mailer): add "null" SMTP transport mode == Goal Allow disabling mail delivery altogether. == Usecase If mails ought to be send by other means than rendering messages from templates and sending them via SMTP-like protocols. Example: listening to specific Nextcloud events and pass parameters to a centralized (i.e. REST-based) API that sends e-mails. Signed-off-by: Thomas Lehmann --- config/config.sample.php | 5 ++++- lib/private/Mail/Mailer.php | 4 ++++ tests/lib/Mail/MailerTest.php | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/config/config.sample.php b/config/config.sample.php index d5a3f0ee01775..96377b7dbf0ba 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -521,7 +521,7 @@ 'mail_smtpdebug' => false, /** - * Which mode to use for sending mail: ``sendmail``, ``smtp`` or ``qmail``. + * Which mode to use for sending mail: ``sendmail``, ``smtp``, ``qmail`` or ``null``. * * If you are using local or remote SMTP, set this to ``smtp``. * @@ -531,6 +531,9 @@ * For ``qmail`` the binary is /var/qmail/bin/sendmail, and it must be installed * on your Unix system. * + * Use the string ``null`` to send no mails (disable mail delivery). This can be + * useful if mails should be sent via APIs and rendering messages is not necessary. + * * Defaults to ``smtp`` */ 'mail_smtpmode' => 'smtp', diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php index b660ee0c02fd2..18636e183d0dc 100644 --- a/lib/private/Mail/Mailer.php +++ b/lib/private/Mail/Mailer.php @@ -27,6 +27,7 @@ use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Mailer\Mailer as SymfonyMailer; use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mailer\Transport\NullTransport; use Symfony\Component\Mailer\Transport\SendmailTransport; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; @@ -256,6 +257,9 @@ protected function getInstance(): MailerInterface { } switch ($this->config->getSystemValueString('mail_smtpmode', 'smtp')) { + case 'null': + $transport = new NullTransport(); + break; case 'sendmail': $transport = $this->getSendMailInstance(); break; diff --git a/tests/lib/Mail/MailerTest.php b/tests/lib/Mail/MailerTest.php index 84015f38d242c..02a2605fc77e2 100644 --- a/tests/lib/Mail/MailerTest.php +++ b/tests/lib/Mail/MailerTest.php @@ -114,6 +114,26 @@ public function testGetSendmailInstanceSendMailQmail($sendmailMode, $binaryParam $this->assertEquals($sendmail, self::invokePrivate($this->mailer, 'getSendMailInstance')); } + public function testEventForNullTransport(): void { + $this->config + ->expects($this->exactly(1)) + ->method('getSystemValueString') + ->with('mail_smtpmode', 'smtp') + ->willReturn('null'); + + $message = $this->createMock(Message::class); + $message->expects($this->once()) + ->method('getSymfonyEmail') + ->willReturn((new Email())->to('foo@bar.com')->from('bar@foo.com')->text('')); + + $event = new BeforeMessageSent($message); + $this->dispatcher->expects($this->once()) + ->method('dispatchTyped') + ->with($this->equalTo($event)); + + $this->mailer->send($message); + } + public function testGetInstanceDefault(): void { $this->config ->method('getSystemValue') From 3f6c969d83faa23379d79ac678c75c22926a5fe1 Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Thu, 14 Nov 2024 12:15:02 +0100 Subject: [PATCH 4/4] feat(Mailer): hide admin settings for "null" transport When the mail transport is configured as null transport, the configuration UI would not work. == Background The null transport is meant for situations where operators implement mail delivery via custom mechanisms like REST APIs. Signed-off-by: Thomas Lehmann --- .../settings/templates/settings/admin/additional-mail.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/settings/templates/settings/admin/additional-mail.php b/apps/settings/templates/settings/admin/additional-mail.php index ecc2973f085f6..6d6c036e81300 100644 --- a/apps/settings/templates/settings/admin/additional-mail.php +++ b/apps/settings/templates/settings/admin/additional-mail.php @@ -34,6 +34,13 @@ ?>
+ +

t('Email server'));?>

+ +

+ t('Mail delivery is disabled by instance config "%s".', ['mail_smtpmode'])); ?> +

+

t('Email server'));?>

t('Test and verify email settings')); ?> +