Skip to content

Commit cfd2a60

Browse files
committed
Add SMTP PLAIN Authentication method
1 parent d8be763 commit cfd2a60

File tree

3 files changed

+72
-51
lines changed

3 files changed

+72
-51
lines changed

system/Email/Email.php

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*
2424
* Permits email to be sent using Mail, Sendmail, or SMTP.
2525
*
26-
* @see \CodeIgniter\Email\EmailTest
26+
* @see EmailTest
2727
*/
2828
class Email
2929
{
@@ -279,6 +279,13 @@ class Email
279279
*/
280280
protected $SMTPAuth = false;
281281

282+
/**
283+
* Which SMTP atuh method to use ('LOGIN', 'PLAIN')
284+
*
285+
* @var bool
286+
*/
287+
protected $SMTPAuthMethod = 'LOGIN';
288+
282289
/**
283290
* Whether to send a Reply-To header
284291
*
@@ -1080,10 +1087,8 @@ public function wordWrap($str, $charlim = null)
10801087

10811088
/**
10821089
* Build final headers
1083-
*
1084-
* @return void
10851090
*/
1086-
protected function buildHeaders()
1091+
protected function buildHeaders(): void
10871092
{
10881093
$this->setHeader('User-Agent', $this->userAgent);
10891094
$this->setHeader('X-Sender', $this->cleanEmail($this->headers['From']));
@@ -1095,10 +1100,8 @@ protected function buildHeaders()
10951100

10961101
/**
10971102
* Write Headers as a string
1098-
*
1099-
* @return void
11001103
*/
1101-
protected function writeHeaders()
1104+
protected function writeHeaders(): void
11021105
{
11031106
if ($this->protocol === 'mail' && isset($this->headers['Subject'])) {
11041107
$this->subject = $this->headers['Subject'];
@@ -1123,10 +1126,8 @@ protected function writeHeaders()
11231126

11241127
/**
11251128
* Build Final Body and attachments
1126-
*
1127-
* @return void
11281129
*/
1129-
protected function buildMessage()
1130+
protected function buildMessage(): void
11301131
{
11311132
if ($this->wordWrap === true && $this->mailType !== 'html') {
11321133
$this->body = $this->wordWrap($this->body);
@@ -1287,10 +1288,8 @@ protected function attachmentsHaveMultipart($type)
12871288
* @param string $body Message body to append to
12881289
* @param string $boundary Multipart boundary
12891290
* @param string|null $multipart When provided, only attachments of this type will be processed
1290-
*
1291-
* @return void
12921291
*/
1293-
protected function appendAttachments(&$body, $boundary, $multipart = null)
1292+
protected function appendAttachments(&$body, $boundary, $multipart = null): void
12941293
{
12951294
foreach ($this->attachments as $attachment) {
12961295
if (isset($multipart) && $attachment['multipart'] !== $multipart) {
@@ -1605,10 +1604,8 @@ public function send($autoClear = true)
16051604

16061605
/**
16071606
* Batch Bcc Send. Sends groups of BCCs in batches
1608-
*
1609-
* @return void
16101607
*/
1611-
public function batchBCCSend()
1608+
public function batchBCCSend(): void
16121609
{
16131610
$float = $this->BCCBatchSize - 1;
16141611
$set = '';
@@ -1651,10 +1648,8 @@ public function batchBCCSend()
16511648

16521649
/**
16531650
* Unwrap special elements
1654-
*
1655-
* @return void
16561651
*/
1657-
protected function unwrapSpecials()
1652+
protected function unwrapSpecials(): void
16581653
{
16591654
$this->finalBody = preg_replace_callback(
16601655
'/\{unwrap\}(.*?)\{\/unwrap\}/si',
@@ -1867,10 +1862,8 @@ protected function sendWithSmtp()
18671862

18681863
/**
18691864
* Shortcut to send RSET or QUIT depending on keep-alive
1870-
*
1871-
* @return void
18721865
*/
1873-
protected function SMTPEnd()
1866+
protected function SMTPEnd(): void
18741867
{
18751868
$this->sendCommand($this->SMTPKeepAlive ? 'reset' : 'quit');
18761869
}
@@ -1920,9 +1913,9 @@ protected function SMTPConnect()
19201913
$this->SMTPConnect,
19211914
true,
19221915
STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
1923-
| STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
1924-
| STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
1925-
| STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT,
1916+
| STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
1917+
| STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
1918+
| STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT,
19261919
);
19271920

19281921
if ($crypto !== true) {
@@ -2019,45 +2012,73 @@ protected function SMTPAuthenticate()
20192012
return true;
20202013
}
20212014

2022-
if ($this->SMTPUser === '' && $this->SMTPPass === '') {
2015+
// If no username or password is set
2016+
if ($this->SMTPUser === '' || $this->SMTPPass === '') {
20232017
$this->setErrorMessage(lang('Email.noSMTPAuth'));
20242018

20252019
return false;
20262020
}
20272021

2028-
$this->sendData('AUTH LOGIN');
2029-
$reply = $this->getSMTPData();
2022+
switch ($this->SMTPAuthMethod) {
2023+
case 'LOGIN':
2024+
$this->sendData('AUTH LOGIN');
2025+
$reply = $this->getSMTPData();
20302026

2031-
if (str_starts_with($reply, '503')) { // Already authenticated
2032-
return true;
2033-
}
2027+
if (str_starts_with($reply, '503')) { // Already authenticated
2028+
return true;
2029+
}
20342030

2035-
if (! str_starts_with($reply, '334')) {
2036-
$this->setErrorMessage(lang('Email.failedSMTPLogin', [$reply]));
2031+
if (! str_starts_with($reply, '334')) {
2032+
$this->setErrorMessage(lang('Email.failedSMTPLogin', [$reply]));
20372033

2038-
return false;
2039-
}
2034+
return false;
2035+
}
20402036

2041-
$this->sendData(base64_encode($this->SMTPUser));
2042-
$reply = $this->getSMTPData();
2037+
$this->sendData(base64_encode($this->SMTPUser));
2038+
$reply = $this->getSMTPData();
20432039

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

2047-
return false;
2048-
}
2043+
return false;
2044+
}
20492045

2050-
$this->sendData(base64_encode($this->SMTPPass));
2051-
$reply = $this->getSMTPData();
2046+
$this->sendData(base64_encode($this->SMTPPass));
2047+
$reply = $this->getSMTPData();
20522048

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

2056-
return false;
2052+
return false;
2053+
}
2054+
break;
2055+
2056+
case 'PLAIN':
2057+
// Generate single command for PLAIN authentication
2058+
$authString = "\0" . $this->SMTPUser . "\0" . $this->SMTPPass;
2059+
2060+
$this->sendData('AUTH PLAIN ' . base64_encode($authString));
2061+
2062+
if (str_starts_with($this->getSMTPData(), '503')) { // Already authenticated
2063+
return true;
2064+
}
2065+
2066+
if (! str_starts_with($this->getSMTPData(), '235')) {
2067+
$this->setErrorMessage(lang('Email.failedSMTPLogin', [$this->getSMTPData()]));
2068+
2069+
return false;
2070+
}
2071+
2072+
break;
2073+
2074+
default:
2075+
$this->setErrorMessage(lang('Email.noSMTPAuthMethod'));
2076+
2077+
return false;
20572078
}
20582079

20592080
if ($this->SMTPKeepAlive) {
2060-
$this->SMTPAuth = false;
2081+
$this->SMTPAuth = false; // Prevent re-authentication for keep-alive sessions
20612082
}
20622083

20632084
return true;
@@ -2192,10 +2213,8 @@ private function printDebuggerRaw(): string
21922213

21932214
/**
21942215
* @param string $msg
2195-
*
2196-
* @return void
21972216
*/
2198-
protected function setErrorMessage($msg)
2217+
protected function setErrorMessage($msg): void
21992218
{
22002219
$this->debugMessage[] = $msg . '<br>';
22012220
$this->debugMessageRaw[] = $msg;

system/Language/en/Email.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
'noHostname' => 'You did not specify a SMTP hostname.',
2828
'SMTPError' => 'The following SMTP error was encountered: {0}',
2929
'noSMTPAuth' => 'Error: You must assign an SMTP username and password.',
30+
'noSMTPAuthMethod' => 'Error: you must assign an SMTP authentication method ("LOGIN" or "PLAIN")',
3031
'failedSMTPLogin' => 'Failed to send AUTH LOGIN command. Error: {0}',
3132
'SMTPAuthUsername' => 'Failed to authenticate username. Error: {0}',
3233
'SMTPAuthPassword' => 'Failed to authenticate password. Error: {0}',

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.
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)