From dbb6c87580fba98686076d4351b17987bd2710bf Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 24 Jun 2023 11:27:18 +0100 Subject: [PATCH] Mail Config: Updated how TLS is configured After full review of current MAIL_ENCRYPTION usage in laravel and smyfony mailer, this updates the options in BookStack to be simplified and specific in usage: - Removed mail.mailers.smtp.encryption option since it did not actually affect anything in the current state of dependancies. - Updated MAIL_ENCRYPTION so values of tls OR ssl will force-enable tls via 'scheme' option with laravel passes to the SMTP transfport, which Smyfony uses as an indicator to force TLS. When MAIL_ENCRYPTION is not used, STARTTLS will still be attempted by symfony mailer. Updated .env files to refer to BookStack docs (which was updated for this) and to reflect correct default port. Related to #4342 --- .env.example | 4 +++- .env.example.complete | 10 +++------- app/Config/mail.php | 6 +++++- tests/Unit/ConfigTest.php | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index a0a1b72e6..4dee3b334 100644 --- a/.env.example +++ b/.env.example @@ -37,8 +37,10 @@ MAIL_FROM=bookstack@example.com # SMTP mail options # These settings can be checked using the "Send a Test Email" # feature found in the "Settings > Maintenance" area of the system. +# For more detailed documentation on mail options, refer to: +# https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration MAIL_HOST=localhost -MAIL_PORT=1025 +MAIL_PORT=587 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null diff --git a/.env.example.complete b/.env.example.complete index 7071846a3..96a3b448f 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -69,23 +69,19 @@ DB_PASSWORD=database_user_password # certificate itself (Common Name or Subject Alternative Name). MYSQL_ATTR_SSL_CA="/path/to/ca.pem" -# Mail system to use -# Can be 'smtp' or 'sendmail' +# Mail configuration +# Refer to https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration MAIL_DRIVER=smtp - -# Mail sending options MAIL_FROM=mail@bookstackapp.com MAIL_FROM_NAME=BookStack -# SMTP mail options MAIL_HOST=localhost -MAIL_PORT=1025 +MAIL_PORT=587 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_VERIFY_SSL=true -# Command to use when email is sent via sendmail MAIL_SENDMAIL_COMMAND="/usr/sbin/sendmail -bs" # Cache & Session driver to use diff --git a/app/Config/mail.php b/app/Config/mail.php index 87514aa40..e8ec9cc15 100644 --- a/app/Config/mail.php +++ b/app/Config/mail.php @@ -8,6 +8,10 @@ * Do not edit this file unless you're happy to maintain any changes yourself. */ +// Configured mail encryption method. +// STARTTLS should still be attempted, but tls/ssl forces TLS usage. +$mailEncryption = env('MAIL_ENCRYPTION', null); + return [ // Mail driver to use. @@ -27,9 +31,9 @@ return [ 'mailers' => [ 'smtp' => [ 'transport' => 'smtp', + 'scheme' => ($mailEncryption === 'tls' || $mailEncryption === 'ssl') ? 'smtps' : null, 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 'port' => env('MAIL_PORT', 587), - 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'verify_peer' => env('MAIL_VERIFY_SSL', true), diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index 103767516..bfd35c6b1 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -5,6 +5,7 @@ namespace Tests\Unit; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream; use Tests\TestCase; /** @@ -122,6 +123,45 @@ class ConfigTest extends TestCase }); } + public function test_non_null_mail_encryption_options_enforce_smtp_scheme() + { + $this->checkEnvConfigResult('MAIL_ENCRYPTION', 'tls', 'mail.mailers.smtp.scheme', 'smtps'); + $this->checkEnvConfigResult('MAIL_ENCRYPTION', 'ssl', 'mail.mailers.smtp.scheme', 'smtps'); + $this->checkEnvConfigResult('MAIL_ENCRYPTION', 'null', 'mail.mailers.smtp.scheme', null); + } + + public function test_smtp_scheme_and_certain_port_forces_tls_usage() + { + $isMailTlsForcedEnabled = function () { + $transport = Mail::mailer('smtp')->getSymfonyTransport(); + /** @var SocketStream $stream */ + $stream = $transport->getStream(); + Mail::purge('smtp'); + return $stream->isTLS(); + }; + + config()->set([ + 'mail.mailers.smtp.scheme' => null, + 'mail.mailers.smtp.port' => 587, + ]); + + $this->assertFalse($isMailTlsForcedEnabled()); + + config()->set([ + 'mail.mailers.smtp.scheme' => 'smtps', + 'mail.mailers.smtp.port' => 587, + ]); + + $this->assertTrue($isMailTlsForcedEnabled()); + + config()->set([ + 'mail.mailers.smtp.scheme' => '', + 'mail.mailers.smtp.port' => 465, + ]); + + $this->assertTrue($isMailTlsForcedEnabled()); + } + /** * Set an environment variable of the given name and value * then check the given config key to see if it matches the given result.