From f3b64ed1ee8794d59de5c1454e27eb9be736217c Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:50:46 +0100 Subject: [PATCH 1/6] -revert: auto corrected (composer cs-fix) comments and auto added function return types -comment: add depreceation comment for failedSMTPLogin email error message -refactor: improve authorization validation flow and email error response messages -added $SMTPAuthMethod in Config\Email file with default value of login --- app/Config/Email.php | 5 ++ system/Email/Email.php | 58 ++++++++++++++++++----- system/Language/en/Email.php | 42 ++++++++-------- user_guide_src/source/libraries/email.rst | 3 +- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/app/Config/Email.php b/app/Config/Email.php index 4dce650b32ec..77c573ad3acb 100644 --- a/app/Config/Email.php +++ b/app/Config/Email.php @@ -30,6 +30,11 @@ class Email extends BaseConfig */ public string $SMTPHost = ''; + /** + * Which SMTP authentication method to use: login, plain + */ + public string $SMTPAuthMethod = 'login'; + /** * SMTP Username */ diff --git a/system/Email/Email.php b/system/Email/Email.php index 24c3af4cd376..d9c963b2d289 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -279,6 +279,13 @@ class Email */ protected $SMTPAuth = false; + /** + * Which SMTP authentication method to use: login, plain + * + * @var string + */ + protected $SMTPAuthMethod = 'login'; + /** * Whether to send a Reply-To header * @@ -2019,45 +2026,72 @@ protected function SMTPAuthenticate() return true; } - if ($this->SMTPUser === '' && $this->SMTPPass === '') { + // If no username or password is set + if ($this->SMTPUser === '' || $this->SMTPPass === '') { $this->setErrorMessage(lang('Email.noSMTPAuth')); return false; } - $this->sendData('AUTH LOGIN'); + // normalize in case user entered capital words LOGIN/PLAIN + $this->SMTPAuthMethod = strtolower($this->SMTPAuthMethod); + + // Validate supported authentication methods + $validMethods = ['login', 'plain']; + if (! in_array($this->SMTPAuthMethod, $validMethods, true)) { + $this->setErrorMessage(lang('Email.invalidSMTPAuthMethod', [$this->SMTPAuthMethod])); + + return false; + } + + // send initial 'AUTH' command + $this->sendData('AUTH ' . strtoupper($this->SMTPAuthMethod)); $reply = $this->getSMTPData(); if (str_starts_with($reply, '503')) { // Already authenticated return true; } + // if 'AUTH' command is unsuported by the server if (! str_starts_with($reply, '334')) { - $this->setErrorMessage(lang('Email.failedSMTPLogin', [$reply])); + $this->setErrorMessage(lang('Email.failureSMTPAuthMethod', [strtoupper($this->SMTPAuthMethod)])); return false; } - $this->sendData(base64_encode($this->SMTPUser)); - $reply = $this->getSMTPData(); + switch ($this->SMTPAuthMethod) { + case 'login': + $this->sendData(base64_encode($this->SMTPUser)); + $reply = $this->getSMTPData(); - if (! str_starts_with($reply, '334')) { - $this->setErrorMessage(lang('Email.SMTPAuthUsername', [$reply])); + if (! str_starts_with($reply, '334')) { + $this->setErrorMessage(lang('Email.SMTPAuthUsername', [$reply])); - return false; + return false; + } + + $this->sendData(base64_encode($this->SMTPPass)); + break; + + case 'plain': + // send credentials as the single second command + $authString = "\0" . $this->SMTPUser . "\0" . $this->SMTPPass; + + $this->sendData(base64_encode($authString)); + break; } - $this->sendData(base64_encode($this->SMTPPass)); $reply = $this->getSMTPData(); + if (! str_starts_with($reply, '235')) { // Authentication failed + $errorMessage = $this->SMTPAuthMethod === 'plain' ? 'Email.SMTPAuthCredentials' : 'Email.SMTPAuthPassword'; - if (! str_starts_with($reply, '235')) { - $this->setErrorMessage(lang('Email.SMTPAuthPassword', [$reply])); + $this->setErrorMessage(lang($errorMessage, [$reply])); return false; } if ($this->SMTPKeepAlive) { - $this->SMTPAuth = false; + $this->SMTPAuth = false; // Prevent re-authentication for keep-alive sessions } return true; diff --git a/system/Language/en/Email.php b/system/Language/en/Email.php index 23a97a75f23c..44d4c03cae3e 100644 --- a/system/Language/en/Email.php +++ b/system/Language/en/Email.php @@ -13,23 +13,27 @@ // Email language settings return [ - 'mustBeArray' => 'The email validation method must be passed an array.', - 'invalidAddress' => 'Invalid email address: "{0}"', - 'attachmentMissing' => 'Unable to locate the following email attachment: "{0}"', - 'attachmentUnreadable' => 'Unable to open this attachment: "{0}"', - 'noFrom' => 'Cannot send mail with no "From" header.', - 'noRecipients' => 'You must include recipients: To, Cc, or Bcc', - 'sendFailurePHPMail' => 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.', - 'sendFailureSendmail' => 'Unable to send email using Sendmail. Your server might not be configured to send mail using this method.', - 'sendFailureSmtp' => 'Unable to send email using SMTP. Your server might not be configured to send mail using this method.', - 'sent' => 'Your message has been successfully sent using the following protocol: {0}', - 'noSocket' => 'Unable to open a socket to Sendmail. Please check settings.', - 'noHostname' => 'You did not specify a SMTP hostname.', - 'SMTPError' => 'The following SMTP error was encountered: {0}', - 'noSMTPAuth' => 'Error: You must assign an SMTP username and password.', - 'failedSMTPLogin' => 'Failed to send AUTH LOGIN command. Error: {0}', - 'SMTPAuthUsername' => 'Failed to authenticate username. Error: {0}', - 'SMTPAuthPassword' => 'Failed to authenticate password. Error: {0}', - 'SMTPDataFailure' => 'Unable to send data: {0}', - 'exitStatus' => 'Exit status code: {0}', + 'mustBeArray' => 'The email validation method must be passed an array.', + 'invalidAddress' => 'Invalid email address: "{0}"', + 'attachmentMissing' => 'Unable to locate the following email attachment: "{0}"', + 'attachmentUnreadable' => 'Unable to open this attachment: "{0}"', + 'noFrom' => 'Cannot send mail with no "From" header.', + 'noRecipients' => 'You must include recipients: To, Cc, or Bcc', + 'sendFailurePHPMail' => 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.', + 'sendFailureSendmail' => 'Unable to send email using Sendmail. Your server might not be configured to send mail using this method.', + 'sendFailureSmtp' => 'Unable to send email using SMTP. Your server might not be configured to send mail using this method.', + 'sent' => 'Your message has been successfully sent using the following protocol: {0}', + 'noSocket' => 'Unable to open a socket to Sendmail. Please check settings.', + 'noHostname' => 'You did not specify a SMTP hostname.', + 'SMTPError' => 'The following SMTP error was encountered: {0}', + 'noSMTPAuth' => 'Error: You must assign an SMTP username and password.', + 'invalidSMTPAuthMethod' => 'Error: SMTP authorization method "{0}" is not supported in codeigniter, set either "login" or "plain" authorization method', + 'failureSMTPAuthMethod' => 'Unable to initiate AUTH command. Your server might not be configured to use AUTH {0} authentication method.', + 'SMTPAuthCredentials' => 'Failed to authenticate user credentials. Error: {0}', + 'SMTPAuthUsername' => 'Failed to authenticate username. Error: {0}', + 'SMTPAuthPassword' => 'Failed to authenticate password. Error: {0}', + 'SMTPDataFailure' => 'Unable to send data: {0}', + 'exitStatus' => 'Exit status code: {0}', + // @deprecated + 'failedSMTPLogin' => 'Failed to send AUTH LOGIN command. Error: {0}', ]; diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index ec21b79ddcf2..92a658e43535 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -39,7 +39,7 @@ Here is a basic example demonstrating how you might send email: Setting Email Preferences ========================= -There are 21 different preferences available to tailor how your email +There are 22 different preferences available to tailor how your email messages are sent. You can either set them manually as described here, or automatically via preferences stored in your config file, described in `Email Preferences`_. @@ -120,6 +120,7 @@ Preference Default Value Options Description or ``smtp`` **mailPath** /usr/sbin/sendmail The server path to Sendmail. **SMTPHost** SMTP Server Hostname. +**SMTPAuthMethod** login ``login``, ``plain`` SMTP Authentication Method. **SMTPUser** SMTP Username. **SMTPPass** SMTP Password. **SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection From 37cf1bf0e69386d5bcd5b119fa6816731128f3ef Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:34:22 +0100 Subject: [PATCH 2/6] Update system/Email/Email.php apply suggestion for declaring string type of $SMTPAuthMethod Co-authored-by: John Paul E. Balandan, CPA --- system/Email/Email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Email/Email.php b/system/Email/Email.php index d9c963b2d289..828fcfcc855c 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -284,7 +284,7 @@ class Email * * @var string */ - protected $SMTPAuthMethod = 'login'; + protected string $SMTPAuthMethod = 'login'; /** * Whether to send a Reply-To header From f9f6bc0b6de52e077440a5085023655a598f1b69 Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:35:07 +0100 Subject: [PATCH 3/6] Update user_guide_src/source/libraries/email.rst Apply Suggestion for description of SMTPAuthMethod Co-authored-by: Michal Sniatala --- user_guide_src/source/libraries/email.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 92a658e43535..b89d764e50f9 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -120,7 +120,7 @@ Preference Default Value Options Description or ``smtp`` **mailPath** /usr/sbin/sendmail The server path to Sendmail. **SMTPHost** SMTP Server Hostname. -**SMTPAuthMethod** login ``login``, ``plain`` SMTP Authentication Method. +**SMTPAuthMethod** login ``login``, ``plain`` SMTP Authentication Method. (Available since 4.7.0) **SMTPUser** SMTP Username. **SMTPPass** SMTP Password. **SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection From 62d2ed0cd264644769afb459fd7b021acc1ab797 Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:36:14 +0100 Subject: [PATCH 4/6] docs: update changelog --- user_guide_src/source/changelogs/v4.7.0.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user_guide_src/source/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst index 06d2a9a8ce39..e9482241518b 100644 --- a/user_guide_src/source/changelogs/v4.7.0.rst +++ b/user_guide_src/source/changelogs/v4.7.0.rst @@ -57,6 +57,8 @@ Model Libraries ========= +**Email:** Added support for choosing the SMTP authorization method. You can change it via Config\Email::$SMTPAuthMethod option + Helpers and Functions ===================== @@ -67,6 +69,9 @@ Others Message Changes *************** +- Added ``Email.invalidSMTPAuthMethod`` and ``Email.failureSMTPAuthMethod`` +- Deprecated ``Email.failedSMTPLogin`` + ******* Changes ******* From e0a2c666785c898453f38731951ef1cdb1e2a3b5 Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:43:42 +0100 Subject: [PATCH 5/6] fix: php-cs violations --- system/Email/Email.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/Email/Email.php b/system/Email/Email.php index 828fcfcc855c..d5a8cc525ba1 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -281,8 +281,6 @@ class Email /** * Which SMTP authentication method to use: login, plain - * - * @var string */ protected string $SMTPAuthMethod = 'login'; From a58c2264ec7da1f1235818565b895034d5279678 Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:54:47 +0100 Subject: [PATCH 6/6] Update user_guide_src/source/changelogs/v4.7.0.rst Apply suggestions for changelog Co-authored-by: Michal Sniatala --- user_guide_src/source/changelogs/v4.7.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst index e9482241518b..ae6797af7884 100644 --- a/user_guide_src/source/changelogs/v4.7.0.rst +++ b/user_guide_src/source/changelogs/v4.7.0.rst @@ -57,7 +57,7 @@ Model Libraries ========= -**Email:** Added support for choosing the SMTP authorization method. You can change it via Config\Email::$SMTPAuthMethod option +**Email:** Added support for choosing the SMTP authorization method. You can change it via ``Config\Email::$SMTPAuthMethod`` option Helpers and Functions =====================