From c283d1a290588d8c513d006771c1c910b424ef6e Mon Sep 17 00:00:00 2001 From: Michal Sniatala Date: Tue, 25 Feb 2025 13:58:12 +0100 Subject: [PATCH 1/3] docs: add changelog and upgrade for v4.7.0 (#9464) --- user_guide_src/source/changelogs/index.rst | 1 + user_guide_src/source/changelogs/v4.7.0.rst | 84 +++++++++++++++++++ .../source/installation/upgrade_470.rst | 55 ++++++++++++ .../source/installation/upgrading.rst | 1 + 4 files changed, 141 insertions(+) create mode 100644 user_guide_src/source/changelogs/v4.7.0.rst create mode 100644 user_guide_src/source/installation/upgrade_470.rst diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index ee417164aa87..252d7943bdc2 100644 --- a/user_guide_src/source/changelogs/index.rst +++ b/user_guide_src/source/changelogs/index.rst @@ -12,6 +12,7 @@ See all the changes. .. toctree:: :titlesonly: + v4.7.0 v4.6.1 v4.6.0 v4.5.8 diff --git a/user_guide_src/source/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst new file mode 100644 index 000000000000..06d2a9a8ce39 --- /dev/null +++ b/user_guide_src/source/changelogs/v4.7.0.rst @@ -0,0 +1,84 @@ +############# +Version 4.7.0 +############# + +Release Date: Unreleased + +**4.7.0 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +********** +Highlights +********** + +- TBD + +******** +BREAKING +******** + +Behavior Changes +================ + +Interface Changes +================= + +Method Signature Changes +======================== + +************ +Enhancements +************ + +Commands +======== + +Testing +======= + +Database +======== + +Query Builder +------------- + +Forge +----- + +Others +------ + +Model +===== + +Libraries +========= + +Helpers and Functions +===================== + +Others +====== + +*************** +Message Changes +*************** + +******* +Changes +******* + +************ +Deprecations +************ + +********** +Bugs Fixed +********** + +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/user_guide_src/source/installation/upgrade_470.rst b/user_guide_src/source/installation/upgrade_470.rst new file mode 100644 index 000000000000..2882870a18f4 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_470.rst @@ -0,0 +1,55 @@ +############################# +Upgrading from 4.6.x to 4.7.0 +############################# + +Please refer to the upgrade instructions corresponding to your installation method. + +- :ref:`Composer Installation App Starter Upgrading ` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading ` +- :ref:`Manual Installation Upgrading ` + +.. contents:: + :local: + :depth: 2 + +********************** +Mandatory File Changes +********************** + +**************** +Breaking Changes +**************** + +********************* +Breaking Enhancements +********************* + +************* +Project Files +************* + +Some files in the **project space** (root, app, public, writable) received updates. Due to +these files being outside of the **system** scope they will not be changed without your intervention. + +.. note:: There are some third-party CodeIgniter modules available to assist + with merging changes to the project space: + `Explore on Packagist `_. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +Config +------ + +- @TODO + +All Changes +=========== + +This is a list of all files in the **project space** that received changes; +many will be simple comments or formatting that have no effect on the runtime: + +- @TODO diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index a2125cba81a3..6053d5a036fb 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -16,6 +16,7 @@ See also :doc:`./backward_compatibility_notes`. backward_compatibility_notes + upgrade_470 upgrade_461 upgrade_460 upgrade_458 From b1f2bee6ba3e530d5c0f1963242f2f2cbd65a4fa Mon Sep 17 00:00:00 2001 From: ip-qi <57226580+ip-qi@users.noreply.github.com> Date: Mon, 3 Mar 2025 08:08:12 +0000 Subject: [PATCH 2/3] feat: add email/smtp plain auth method (#9462) * -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 * Update system/Email/Email.php apply suggestion for declaring string type of $SMTPAuthMethod Co-authored-by: John Paul E. Balandan, CPA * Update user_guide_src/source/libraries/email.rst Apply Suggestion for description of SMTPAuthMethod Co-authored-by: Michal Sniatala * docs: update changelog * fix: php-cs violations * Update user_guide_src/source/changelogs/v4.7.0.rst Apply suggestions for changelog Co-authored-by: Michal Sniatala --------- Co-authored-by: John Paul E. Balandan, CPA Co-authored-by: Michal Sniatala --- app/Config/Email.php | 5 ++ system/Email/Email.php | 56 ++++++++++++++++----- system/Language/en/Email.php | 42 +++++++++------- user_guide_src/source/changelogs/v4.7.0.rst | 5 ++ user_guide_src/source/libraries/email.rst | 3 +- 5 files changed, 79 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..d5a8cc525ba1 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -279,6 +279,11 @@ class Email */ protected $SMTPAuth = false; + /** + * Which SMTP authentication method to use: login, plain + */ + protected string $SMTPAuthMethod = 'login'; + /** * Whether to send a Reply-To header * @@ -2019,45 +2024,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/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst index 06d2a9a8ce39..ae6797af7884 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 ******* diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index ec21b79ddcf2..b89d764e50f9 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. (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 18fcfb86a6a0dd00e3fc3c96dadbac3815bb6a8b Mon Sep 17 00:00:00 2001 From: Christian Berkman Date: Fri, 18 Apr 2025 00:13:02 +0300 Subject: [PATCH 3/3] feat: [I18n\Time] addCalendarMonths() --- system/I18n/TimeTrait.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/system/I18n/TimeTrait.php b/system/I18n/TimeTrait.php index 42278c960c43..405adc61d2af 100644 --- a/system/I18n/TimeTrait.php +++ b/system/I18n/TimeTrait.php @@ -749,6 +749,29 @@ public function addMonths(int $months) return $time->add(DateInterval::createFromDateString("{$months} months")); } + /** + * Returns a new Time instance with $months calendar months added to the time. + */ + public function addCalendarMonths(int $months): Time + { + $time = clone $this; + + $year = (int) $time->getYear(); + $month = (int) $time->getMonth() + $months; + $day = (int) $time->getDay(); + + // Adjust year and month for overflow + $year += intdiv($month - 1, 12); + $month = (($month - 1) % 12) + 1; + + // Find the last valid day of the target month + $lastDayOfMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); + $correctedDay = min($day, $lastDayOfMonth); + + // Return new time instance + return static::create($year, $month, $correctedDay, (int) $this->getHour(), (int) $this->getMinute(), (int) $this->getSecond(), $this->getTimezone(), $this->locale); + } + /** * Returns a new Time instance with $years added to the time. *