Skip to content

Commit b1f2bee

Browse files
ip-qipaulbalandanmichalsn
authored
feat: add email/smtp plain auth method (codeigniter4#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 <[email protected]> * Update user_guide_src/source/libraries/email.rst Apply Suggestion for description of SMTPAuthMethod Co-authored-by: Michal Sniatala <[email protected]> * 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 <[email protected]> --------- Co-authored-by: John Paul E. Balandan, CPA <[email protected]> Co-authored-by: Michal Sniatala <[email protected]>
1 parent c283d1a commit b1f2bee

File tree

5 files changed

+79
-32
lines changed

5 files changed

+79
-32
lines changed

app/Config/Email.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class Email extends BaseConfig
3030
*/
3131
public string $SMTPHost = '';
3232

33+
/**
34+
* Which SMTP authentication method to use: login, plain
35+
*/
36+
public string $SMTPAuthMethod = 'login';
37+
3338
/**
3439
* SMTP Username
3540
*/

system/Email/Email.php

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ class Email
279279
*/
280280
protected $SMTPAuth = false;
281281

282+
/**
283+
* Which SMTP authentication method to use: login, plain
284+
*/
285+
protected string $SMTPAuthMethod = 'login';
286+
282287
/**
283288
* Whether to send a Reply-To header
284289
*
@@ -2019,45 +2024,72 @@ protected function SMTPAuthenticate()
20192024
return true;
20202025
}
20212026

2022-
if ($this->SMTPUser === '' && $this->SMTPPass === '') {
2027+
// If no username or password is set
2028+
if ($this->SMTPUser === '' || $this->SMTPPass === '') {
20232029
$this->setErrorMessage(lang('Email.noSMTPAuth'));
20242030

20252031
return false;
20262032
}
20272033

2028-
$this->sendData('AUTH LOGIN');
2034+
// normalize in case user entered capital words LOGIN/PLAIN
2035+
$this->SMTPAuthMethod = strtolower($this->SMTPAuthMethod);
2036+
2037+
// Validate supported authentication methods
2038+
$validMethods = ['login', 'plain'];
2039+
if (! in_array($this->SMTPAuthMethod, $validMethods, true)) {
2040+
$this->setErrorMessage(lang('Email.invalidSMTPAuthMethod', [$this->SMTPAuthMethod]));
2041+
2042+
return false;
2043+
}
2044+
2045+
// send initial 'AUTH' command
2046+
$this->sendData('AUTH ' . strtoupper($this->SMTPAuthMethod));
20292047
$reply = $this->getSMTPData();
20302048

20312049
if (str_starts_with($reply, '503')) { // Already authenticated
20322050
return true;
20332051
}
20342052

2053+
// if 'AUTH' command is unsuported by the server
20352054
if (! str_starts_with($reply, '334')) {
2036-
$this->setErrorMessage(lang('Email.failedSMTPLogin', [$reply]));
2055+
$this->setErrorMessage(lang('Email.failureSMTPAuthMethod', [strtoupper($this->SMTPAuthMethod)]));
20372056

20382057
return false;
20392058
}
20402059

2041-
$this->sendData(base64_encode($this->SMTPUser));
2042-
$reply = $this->getSMTPData();
2060+
switch ($this->SMTPAuthMethod) {
2061+
case 'login':
2062+
$this->sendData(base64_encode($this->SMTPUser));
2063+
$reply = $this->getSMTPData();
20432064

2044-
if (! str_starts_with($reply, '334')) {
2045-
$this->setErrorMessage(lang('Email.SMTPAuthUsername', [$reply]));
2065+
if (! str_starts_with($reply, '334')) {
2066+
$this->setErrorMessage(lang('Email.SMTPAuthUsername', [$reply]));
20462067

2047-
return false;
2068+
return false;
2069+
}
2070+
2071+
$this->sendData(base64_encode($this->SMTPPass));
2072+
break;
2073+
2074+
case 'plain':
2075+
// send credentials as the single second command
2076+
$authString = "\0" . $this->SMTPUser . "\0" . $this->SMTPPass;
2077+
2078+
$this->sendData(base64_encode($authString));
2079+
break;
20482080
}
20492081

2050-
$this->sendData(base64_encode($this->SMTPPass));
20512082
$reply = $this->getSMTPData();
2083+
if (! str_starts_with($reply, '235')) { // Authentication failed
2084+
$errorMessage = $this->SMTPAuthMethod === 'plain' ? 'Email.SMTPAuthCredentials' : 'Email.SMTPAuthPassword';
20522085

2053-
if (! str_starts_with($reply, '235')) {
2054-
$this->setErrorMessage(lang('Email.SMTPAuthPassword', [$reply]));
2086+
$this->setErrorMessage(lang($errorMessage, [$reply]));
20552087

20562088
return false;
20572089
}
20582090

20592091
if ($this->SMTPKeepAlive) {
2060-
$this->SMTPAuth = false;
2092+
$this->SMTPAuth = false; // Prevent re-authentication for keep-alive sessions
20612093
}
20622094

20632095
return true;

system/Language/en/Email.php

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,27 @@
1313

1414
// Email language settings
1515
return [
16-
'mustBeArray' => 'The email validation method must be passed an array.',
17-
'invalidAddress' => 'Invalid email address: "{0}"',
18-
'attachmentMissing' => 'Unable to locate the following email attachment: "{0}"',
19-
'attachmentUnreadable' => 'Unable to open this attachment: "{0}"',
20-
'noFrom' => 'Cannot send mail with no "From" header.',
21-
'noRecipients' => 'You must include recipients: To, Cc, or Bcc',
22-
'sendFailurePHPMail' => 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.',
23-
'sendFailureSendmail' => 'Unable to send email using Sendmail. Your server might not be configured to send mail using this method.',
24-
'sendFailureSmtp' => 'Unable to send email using SMTP. Your server might not be configured to send mail using this method.',
25-
'sent' => 'Your message has been successfully sent using the following protocol: {0}',
26-
'noSocket' => 'Unable to open a socket to Sendmail. Please check settings.',
27-
'noHostname' => 'You did not specify a SMTP hostname.',
28-
'SMTPError' => 'The following SMTP error was encountered: {0}',
29-
'noSMTPAuth' => 'Error: You must assign an SMTP username and password.',
30-
'failedSMTPLogin' => 'Failed to send AUTH LOGIN command. Error: {0}',
31-
'SMTPAuthUsername' => 'Failed to authenticate username. Error: {0}',
32-
'SMTPAuthPassword' => 'Failed to authenticate password. Error: {0}',
33-
'SMTPDataFailure' => 'Unable to send data: {0}',
34-
'exitStatus' => 'Exit status code: {0}',
16+
'mustBeArray' => 'The email validation method must be passed an array.',
17+
'invalidAddress' => 'Invalid email address: "{0}"',
18+
'attachmentMissing' => 'Unable to locate the following email attachment: "{0}"',
19+
'attachmentUnreadable' => 'Unable to open this attachment: "{0}"',
20+
'noFrom' => 'Cannot send mail with no "From" header.',
21+
'noRecipients' => 'You must include recipients: To, Cc, or Bcc',
22+
'sendFailurePHPMail' => 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.',
23+
'sendFailureSendmail' => 'Unable to send email using Sendmail. Your server might not be configured to send mail using this method.',
24+
'sendFailureSmtp' => 'Unable to send email using SMTP. Your server might not be configured to send mail using this method.',
25+
'sent' => 'Your message has been successfully sent using the following protocol: {0}',
26+
'noSocket' => 'Unable to open a socket to Sendmail. Please check settings.',
27+
'noHostname' => 'You did not specify a SMTP hostname.',
28+
'SMTPError' => 'The following SMTP error was encountered: {0}',
29+
'noSMTPAuth' => 'Error: You must assign an SMTP username and password.',
30+
'invalidSMTPAuthMethod' => 'Error: SMTP authorization method "{0}" is not supported in codeigniter, set either "login" or "plain" authorization method',
31+
'failureSMTPAuthMethod' => 'Unable to initiate AUTH command. Your server might not be configured to use AUTH {0} authentication method.',
32+
'SMTPAuthCredentials' => 'Failed to authenticate user credentials. Error: {0}',
33+
'SMTPAuthUsername' => 'Failed to authenticate username. Error: {0}',
34+
'SMTPAuthPassword' => 'Failed to authenticate password. Error: {0}',
35+
'SMTPDataFailure' => 'Unable to send data: {0}',
36+
'exitStatus' => 'Exit status code: {0}',
37+
// @deprecated
38+
'failedSMTPLogin' => 'Failed to send AUTH LOGIN command. Error: {0}',
3539
];

user_guide_src/source/changelogs/v4.7.0.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ Model
5757
Libraries
5858
=========
5959

60+
**Email:** Added support for choosing the SMTP authorization method. You can change it via ``Config\Email::$SMTPAuthMethod`` option
61+
6062
Helpers and Functions
6163
=====================
6264

@@ -67,6 +69,9 @@ Others
6769
Message Changes
6870
***************
6971

72+
- Added ``Email.invalidSMTPAuthMethod`` and ``Email.failureSMTPAuthMethod``
73+
- Deprecated ``Email.failedSMTPLogin``
74+
7075
*******
7176
Changes
7277
*******

user_guide_src/source/libraries/email.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Here is a basic example demonstrating how you might send email:
3939
Setting Email Preferences
4040
=========================
4141

42-
There are 21 different preferences available to tailor how your email
42+
There are 22 different preferences available to tailor how your email
4343
messages are sent. You can either set them manually as described here,
4444
or automatically via preferences stored in your config file, described
4545
in `Email Preferences`_.
@@ -120,6 +120,7 @@ Preference Default Value Options Description
120120
or ``smtp``
121121
**mailPath** /usr/sbin/sendmail The server path to Sendmail.
122122
**SMTPHost** SMTP Server Hostname.
123+
**SMTPAuthMethod** login ``login``, ``plain`` SMTP Authentication Method. (Available since 4.7.0)
123124
**SMTPUser** SMTP Username.
124125
**SMTPPass** SMTP Password.
125126
**SMTPPort** 25 SMTP Port. (If set to ``465``, TLS will be used for the connection

0 commit comments

Comments
 (0)