From 613c2a1af8aa2a3e309fabf026d08c84555fa9df Mon Sep 17 00:00:00 2001 From: matidau <65836048+matidau@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:50:13 +1000 Subject: [PATCH 1/4] update PEAR Mail to v2.0.0 using diff from https://github.com/pear/Mail/compare/v1.4.1...v2.0.0#diff-b33edd554729e512ce1dd11e99fbcabf114a32eb6f74b397df969b3a58b419e5R449 --- src/backend/imap/Mail/mail.php | 12 ---- src/backend/imap/Mail/smtp.php | 117 ++++++++++++++++++++++++++++++--- src/include/z_RFC822.php | 21 ++++-- 3 files changed, 125 insertions(+), 25 deletions(-) diff --git a/src/backend/imap/Mail/mail.php b/src/backend/imap/Mail/mail.php index f1bf80a6..53a30c08 100644 --- a/src/backend/imap/Mail/mail.php +++ b/src/backend/imap/Mail/mail.php @@ -87,18 +87,6 @@ public function __construct($params = null) } else { $this->_params = $params; } - - /* Because the mail() function may pass headers as command - * line arguments, we can't guarantee the use of the standard - * "\r\n" separator. Instead, we use the system's native line - * separator. - * Fixed in PHP 8.0. - */ - if (defined('PHP_EOL') && version_compare(PHP_VERSION, '8.0.0', '<')) { - $this->sep = PHP_EOL; - } elseif (version_compare(PHP_VERSION, '8.0.0', '<')) { - $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; - } } /** diff --git a/src/backend/imap/Mail/smtp.php b/src/backend/imap/Mail/smtp.php index e5881a06..9ec242bb 100644 --- a/src/backend/imap/Mail/smtp.php +++ b/src/backend/imap/Mail/smtp.php @@ -6,7 +6,7 @@ * * LICENSE: * - * Copyright (c) 2010-2017, Chuck Hagenbuch & Jon Parise + * Copyright (c) 2010-2021, Chuck Hagenbuch & Jon Parise * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,9 +38,9 @@ * * @category HTTP * @package HTTP_Request - * @author Jon Parise + * @author Jon Parise * @author Chuck Hagenbuch - * @copyright 2010-2017 Chuck Hagenbuch + * @copyright 2010-2021 Chuck Hagenbuch * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ @@ -116,6 +116,25 @@ class Mail_smtp extends Mail { */ var $port = 25; + /** + * Should STARTTLS connection be used? + * + * This value may be set to true or false. + * + * If the value is set to true, the Net_SMTP package will attempt to use + * a STARTTLS encrypted connection. + * + * If the value is set to false, the Net_SMTP package will avoid + * a STARTTLS encrypted connection. + * + * NULL indicates only STARTTLS if $auth is set. + * + * PEAR/Net_SMTP >= 1.10.0 required. + * + * @var boolean + */ + var $starttls = null; + /** * Should SMTP authentication be used? * @@ -165,6 +184,22 @@ class Mail_smtp extends Mail { */ var $debug = false; + /** + * Set debug_handler on Net_SMTP + * + * @var callable $debug_handler + */ + var $debug_handler = null; + + /** + * we need the greeting; from it we can extract the authorative name of the mail + * server we've really connected to. ideal if we're connecting to a round-robin + * of relay servers and need to track which exact one took the email + * + * @var string + */ + var $greeting = null; + /** * Indicates whether or not the SMTP connection should persist over * multiple calls to the send() method. @@ -189,6 +224,27 @@ class Mail_smtp extends Mail { */ var $socket_options = array(); + /** + * SMTP response message + * + * @var string + * @since 1.6.0 + */ + var $response = null; + + /** + * If the message ends up in the queue, on the recipient server, + * the response will be saved here. + * Some successfully delivered emails will include a “queued” + * notation in the SMTP response, such as "250 OK; queued as 12345". + * This indicates that the email was delivered to the recipient + * as expected, but may require additional processing before it + * lands in the recipient’s inbox. + * + * @var string + */ + var $queued_as = null; + /** * Require verification of SSL certificate used. Default is TRUE. * @@ -217,7 +273,8 @@ class Mail_smtp extends Mail { * passed in. It looks for the following parameters: * host The server to connect to. Defaults to localhost. * port The port to connect to. Defaults to 25. - * auth SMTP authentication. Defaults to none. + * auth SMTP authentication. Defaults to none. + * starttls Should STARTTLS connection be used? No default. PEAR/Net_SMTP >= 1.10.0 required. * username The username to use for SMTP auth. No default. * password The password to use for SMTP auth. No default. * localhost The local hostname / domain. Defaults to localhost. @@ -225,8 +282,10 @@ class Mail_smtp extends Mail { * verp Whether to use VERP or not. Defaults to false. * DEPRECATED as of 1.2.0 (use setMailParams()). * debug Activate SMTP debug mode? Defaults to false. + * debug_handler Set SMTP debug handler function. Defaults to null. * persist Should the SMTP connection persist? * pipelining Use SMTP command pipelining + * socket_options Socket stream_context_create() options. * verify_peer Require verification of SSL certificate used. * verify_peer_name Require verification of peer name. * allow_self_signed Allow self-signed certificates. Requires verify_peer. @@ -242,11 +301,13 @@ public function __construct($params) if (isset($params['host'])) $this->host = $params['host']; if (isset($params['port'])) $this->port = $params['port']; if (isset($params['auth'])) $this->auth = $params['auth']; + if (isset($params['starttls'])) $this->starttls = $params['starttls']; if (isset($params['username'])) $this->username = $params['username']; if (isset($params['password'])) $this->password = $params['password']; if (isset($params['localhost'])) $this->localhost = $params['localhost']; if (isset($params['timeout'])) $this->timeout = $params['timeout']; if (isset($params['debug'])) $this->debug = (bool)$params['debug']; + if (isset($params['debug_handler'])) $this->debug_handler = $params['debug_handler']; if (isset($params['persist'])) $this->persist = (bool)$params['persist']; if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining']; if (isset($params['socket_options'])) $this->socket_options = $params['socket_options']; @@ -339,7 +400,7 @@ protected function send_or_fail($recipients, $headers, $body) PEAR_MAIL_SMTP_ERROR_FROM); } - $params = null; + $params = ''; if (!empty($this->_extparams)) { foreach ($this->_extparams as $key => $val) { $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); @@ -371,7 +432,10 @@ protected function send_or_fail($recipients, $headers, $body) /* Send the message's headers and the body as SMTP data. */ $res = $this->_smtp->data($body, $textHeaders); - list(,$args) = $this->_smtp->getResponse(); + + list($code, $args) = $this->_smtp->getResponse(); + + $this->response = $code . ' ' . $args; if (preg_match("/ queued as (.*)/", $args, $queued)) { $this->queued_as = $queued[1]; @@ -425,7 +489,7 @@ public function getSMTPObject() /* Configure the SMTP connection. */ if ($this->debug) { - $this->_smtp->setDebug(true); + $this->_smtp->setDebug(true, $this->debug_handler); } /* Attempt to connect to the configured SMTP server. */ @@ -441,9 +505,12 @@ public function getSMTPObject() if ($this->auth) { $method = is_string($this->auth) ? $this->auth : ''; + $tls = $this->starttls === false ? false : true; + //if (PEAR::isError($res = $this->_smtp->auth($this->username, // $this->password, - // $method))) { + // $method, + // $tls))) { if (($res = $this->_smtp->auth($this->username, $this->password, $method)) === false) { $error = $this->_error("$method authentication failure", $res); @@ -452,6 +519,16 @@ public function getSMTPObject() } } + /* Attempt to establish a TLS encrypted connection. PEAR/Net_SMTP >= 1.10.0 required. */ + if ($this->starttls && !$this->auth) { + $starttls = $this->_smtp->starttls(); + if (PEAR::isError($starttls)) { + return PEAR::raiseError($starttls); + } elseif ($starttls === false) { + return PEAR::raiseError('STARTTLS failed'); + } + } + return $this->_smtp; } @@ -486,6 +563,30 @@ public function disconnect() return ($this->_smtp === null); } + /** + * Returns the SMTP response message after sending. + * + * @return string SMTP response message or NULL. + * + * @since 1.6.0 + */ + public function getResponse() + { + return $this->response; + } + + /** + * Returns the SMTP response message if includes "queue" after sending. + * + * @return string SMTP queue message or NULL. + * + * @since 1.6.0 + */ + public function getQueuedAs() + { + return $this->queued_as; + } + /** * Build a standardized string describing the current SMTP error. * diff --git a/src/include/z_RFC822.php b/src/include/z_RFC822.php index de86a0a8..ba26d88a 100644 --- a/src/include/z_RFC822.php +++ b/src/include/z_RFC822.php @@ -60,7 +60,8 @@ * How do I use it? * * $address_string = 'My Group: "Richard" (A comment), ted@example.com (Ted Bloggs), Barney;'; - * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true) + * $parser = new Mail_RFC822(); + * $structure = $parser->parseAddressList($address_string, 'example.com', true); * print_r($structure); * * @author Richard Heyes @@ -172,9 +173,13 @@ public function __construct($address = null, $default_domain = null, $nest_group */ public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { - if (!isset($this) || !isset($this->mailRFC822)) { - $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); - return $obj->parseAddressList(); + if (version_compare(PHP_VERSION, '8.0.0', '<')) { + if (!isset($this) || !isset($this->mailRFC822)) { + $warn = "Calling non-static methods statically is no longer supported since PHP 8"; + trigger_error($warn, E_USER_NOTICE); + $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); + return $obj->parseAddressList(); + } } if (isset($address)) $this->address = $address; @@ -229,6 +234,9 @@ public function parseAddressList($address = null, $default_domain = null, $nest_ */ protected function _splitAddresses($address) { + $is_group = false; + $split_char = ','; + if (!empty($this->limit) && count($this->addresses) == $this->limit) { return ''; } @@ -439,6 +447,7 @@ protected function _hasUnclosedBracketsSub($string, &$num, $char) */ protected function _validateAddress($address) { + $structure = null; $is_group = false; $addresses = array(); @@ -479,7 +488,7 @@ protected function _validateAddress($address) } // Trim the whitespace from all of the address strings. - array_map('trim', $addresses); + $addresses = array_map('trim', $addresses); // Validate each mailbox. // Format could be one of: name @@ -616,6 +625,7 @@ public function validateMailbox(&$mailbox) $phrase = ''; $comment = ''; $comments = array(); + $addr_spec = null; // Catch any RFC822 comments and store them separately. $_mailbox = $mailbox; @@ -773,6 +783,7 @@ protected function _validateDomain($domain) { // Note the different use of $subdomains and $sub_domains $subdomains = explode('.', $domain); + $sub_domains = array(); while (count($subdomains) > 0) { $sub_domains[] = $this->_splitCheck($subdomains, '.'); From 2b5151b903f09bbf2c86d5b272966d536523d057 Mon Sep 17 00:00:00 2001 From: matidau <65836048+matidau@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:52:50 +1000 Subject: [PATCH 2/4] Update comments on Z-push changes Clearly state changes between Z-Push version and Pear/Mail version. --- src/backend/imap/Mail/mail.php | 6 +++++- src/backend/imap/Mail/sendmail.php | 10 +++++++++- src/backend/imap/Mail/smtp.php | 24 +++++++++++++++++++++++- src/include/z_RFC822.php | 22 +++++++++++++++++++++- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/backend/imap/Mail/mail.php b/src/backend/imap/Mail/mail.php index 53a30c08..13103869 100644 --- a/src/backend/imap/Mail/mail.php +++ b/src/backend/imap/Mail/mail.php @@ -51,7 +51,7 @@ * removed PEAR dependency by implementing own raiseError() * * Reference implementation used: - * http://download.pear.php.net/package/Mail-1.4.1.tgz + * https://github.com/pear/Mail/tree/v2.0.0 * * */ @@ -116,10 +116,12 @@ public function __construct($params = null) public function send($recipients, $headers, $body) { if (!is_array($headers)) { + // Z-Push change: rasiseError dependancy return Mail_mail::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($result, 'PEAR_Error')) { if ($result === false) { return $result; @@ -144,6 +146,7 @@ public function send($recipients, $headers, $body) // Flatten the headers out. $headerElements = $this->prepareHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($headerElements, 'PEAR_Error')) { if ($headerElements === false) { return $headerElements; @@ -162,6 +165,7 @@ public function send($recipients, $headers, $body) // If the mail() function returned failure, we need to create a // PEAR_Error object and return it instead of the boolean result. if ($result === false) { + // Z-Push change: rasiseError dependancy $result = Mail_mail::raiseError('mail() returned failure'); } diff --git a/src/backend/imap/Mail/sendmail.php b/src/backend/imap/Mail/sendmail.php index 08004150..b4cd092e 100644 --- a/src/backend/imap/Mail/sendmail.php +++ b/src/backend/imap/Mail/sendmail.php @@ -52,7 +52,7 @@ * removed PEAR dependency by implementing own raiseError() * * Reference implementation used: - * http://download.pear.php.net/package/Mail-1.4.1.tgz + * https://github.com/pear/Mail/tree/v2.0.0 * * */ @@ -144,16 +144,19 @@ public function __construct($params) public function send($recipients, $headers, $body) { if (!is_array($headers)) { + // Z-Push change: rasiseError dependancy return Mail_sendmail::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($result, 'PEAR_Error')) { if ($result === false) { return $result; } $recipients = $this->parseRecipients($recipients); + // Z-Push change: rasiseError dependancy //if (is_a($recipients, 'PEAR_Error')) { if ($recipients === false) { return $recipients; @@ -161,6 +164,7 @@ public function send($recipients, $headers, $body) $recipients = implode(' ', array_map('escapeshellarg', $recipients)); $headerElements = $this->prepareHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($headerElements, 'PEAR_Error')) { if ($headerElements === false) { return $headerElements; @@ -175,11 +179,13 @@ public function send($recipients, $headers, $body) } if (!isset($from)) { + // Z-Push change: rasiseError dependancy return Mail_sendmail::raiseError('No from address given.'); } elseif (strpos($from, ' ') !== false || strpos($from, ';') !== false || strpos($from, '&') !== false || strpos($from, '`') !== false) { + // Z-Push change: rasiseError dependancy return Mail_sendmail::raiseError('From address specified with dangerous characters.'); } @@ -187,6 +193,7 @@ public function send($recipients, $headers, $body) $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); if (!$mail) { + // Z-Push change: rasiseError dependancy return Mail_sendmail::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.'); } @@ -203,6 +210,7 @@ public function send($recipients, $headers, $body) } if ($result != 0) { + // Z-Push change: rasiseError dependancy return Mail_sendmail::raiseError('sendmail returned error code ' . $result, $result); } diff --git a/src/backend/imap/Mail/smtp.php b/src/backend/imap/Mail/smtp.php index 9ec242bb..5b5c260a 100644 --- a/src/backend/imap/Mail/smtp.php +++ b/src/backend/imap/Mail/smtp.php @@ -50,9 +50,10 @@ * Z-Push changes * * removed PEAR dependency by implementing own raiseError() + * verify_peer, verify_peer_name, allow_self_signed * * Reference implementation used: - * http://download.pear.php.net/package/Mail-1.4.1.tgz + * https://github.com/pear/Mail/tree/v2.0.0 * * */ @@ -245,6 +246,7 @@ class Mail_smtp extends Mail { */ var $queued_as = null; + // Z-Push addition: verify_peer, verify_peer_name, allow_self_signed /** * Require verification of SSL certificate used. Default is TRUE. * @@ -286,6 +288,7 @@ class Mail_smtp extends Mail { * persist Should the SMTP connection persist? * pipelining Use SMTP command pipelining * socket_options Socket stream_context_create() options. + * // Z-Push addition: verify_peer, verify_peer_name, allow_self_signed * verify_peer Require verification of SSL certificate used. * verify_peer_name Require verification of peer name. * allow_self_signed Allow self-signed certificates. Requires verify_peer. @@ -311,6 +314,7 @@ public function __construct($params) if (isset($params['persist'])) $this->persist = (bool)$params['persist']; if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining']; if (isset($params['socket_options'])) $this->socket_options = $params['socket_options']; + // Z-Push addition: verify_peer, verify_peer_name, allow_self_signed if (isset($params['verify_peer'])) $this->verify_peer = $params['verify_peer']; if (isset($params['verify_peer_name'])) $this->verify_peer_name = $params['verify_peer_name']; if (isset($params['allow_self_signed'])) $this->allow_self_signed = $params['allow_self_signed']; @@ -368,18 +372,21 @@ protected function send_or_fail($recipients, $headers, $body) { /* If we don't already have an SMTP object, create one. */ $result = $this->getSMTPObject(); + // Z-Push change: rasiseError dependancy //if (PEAR::isError($result)) { if ($this->_smtp === false) { return $result; } if (!is_array($headers)) { + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError('$headers must be an array'); } $this->_sanitizeHeaders($headers); $headerElements = $this->prepareHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($headerElements, 'PEAR_Error')) { if ($headerElements === false) { $this->_smtp->rset(); @@ -396,6 +403,7 @@ protected function send_or_fail($recipients, $headers, $body) if (!isset($from)) { $this->_smtp->rset(); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError('No From: address has been provided', PEAR_MAIL_SMTP_ERROR_FROM); } @@ -406,14 +414,17 @@ protected function send_or_fail($recipients, $headers, $body) $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); } } + // Z-Push change: rasiseError dependancy //if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) { if (($res = $this->_smtp->mailFrom($from, ltrim($params))) === false) { $error = $this->_error("Failed to set sender: $from", $res); $this->_smtp->rset(); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER); } $recipients = $this->parseRecipients($recipients); + // Z-Push change: rasiseError dependancy //if (is_a($recipients, 'PEAR_Error')) { if ($recipients === false) { $this->_smtp->rset(); @@ -422,10 +433,12 @@ protected function send_or_fail($recipients, $headers, $body) foreach ($recipients as $recipient) { $res = $this->_smtp->rcptTo($recipient); + // Z-Push change: rasiseError dependancy //if (is_a($res, 'PEAR_Error')) { if ($res === false) { $error = $this->_error("Failed to add recipient: $recipient", $res); $this->_smtp->rset(); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT); } } @@ -445,10 +458,12 @@ protected function send_or_fail($recipients, $headers, $body) * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */ $this->greeting = $this->_smtp->getGreeting(); + // Z-Push change: rasiseError dependancy //if (is_a($res, 'PEAR_Error')) { if ($res === false) { $error = $this->_error('Failed to send data', $res); $this->_smtp->rset(); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA); } @@ -476,6 +491,7 @@ public function getSMTPObject() $this->localhost, $this->pipelining, 0, + // Z-Push change: verify_peer, verify_peer_name, allow_self_signed $this->socket_options, $this->verify_peer, $this->verify_peer_name, @@ -483,6 +499,7 @@ public function getSMTPObject() /* If we still don't have an SMTP object at this point, fail. */ if (is_object($this->_smtp) === false) { + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError('Failed to create a Net_SMTP object', PEAR_MAIL_SMTP_ERROR_CREATE); } @@ -493,11 +510,13 @@ public function getSMTPObject() } /* Attempt to connect to the configured SMTP server. */ + // Z-Push change: rasiseError dependancy //if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) { if (($res = $this->_smtp->connect($this->timeout)) === false) { $error = $this->_error('Failed to connect to ' . $this->host . ':' . $this->port, $res); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT); } @@ -507,6 +526,7 @@ public function getSMTPObject() $tls = $this->starttls === false ? false : true; + // Z-Push change: rasiseError dependancy //if (PEAR::isError($res = $this->_smtp->auth($this->username, // $this->password, // $method, @@ -515,6 +535,7 @@ public function getSMTPObject() $error = $this->_error("$method authentication failure", $res); $this->_smtp->rset(); + // Z-Push change: rasiseError dependancy return Mail_smtp::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH); } } @@ -604,6 +625,7 @@ protected function _error($text, $error) /* Build our standardized error string. */ return $text + // Z-Push change: rasiseError dependancy //. ' [SMTP: ' . $error->getMessage() . ' [SMTP: ' . " (code: $code, response: $response)]"; diff --git a/src/include/z_RFC822.php b/src/include/z_RFC822.php index ba26d88a..bb5f7d82 100644 --- a/src/include/z_RFC822.php +++ b/src/include/z_RFC822.php @@ -46,6 +46,20 @@ * @link http://pear.php.net/package/Mail/ */ + /** + * Z-Push changes + * + * removed PEAR dependency by implementing own raiseError() + * cast $address to string for explode() for PHP 8.x compatibility + * removed public access to num_groups + * change indetatation for parseAddressList + * + * Reference implementation used: + * https://github.com/pear/Mail/tree/v2.0.0 + * + * + */ + /** * RFC 822 Email address list validation Utility * @@ -70,7 +84,6 @@ * @license BSD * @package Mail */ - class Mail_RFC822 { /** @@ -124,6 +137,7 @@ class Mail_RFC822 { /** * The number of groups that have been found in the address list. * @var integer $num_groups + * // Z-Push removal: access public */ var $num_groups = 0; @@ -173,6 +187,7 @@ public function __construct($address = null, $default_domain = null, $nest_group */ public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { + // Z-Push Change: indentation if (version_compare(PHP_VERSION, '8.0.0', '<')) { if (!isset($this) || !isset($this->mailRFC822)) { $warn = "Calling non-static methods statically is no longer supported since PHP 8"; @@ -202,6 +217,7 @@ public function parseAddressList($address = null, $default_domain = null, $nest_ while ($this->address = $this->_splitAddresses($this->address)); if ($this->address === false || isset($this->error)) { + // Z-Push change rasiseError dependancy //require_once 'PEAR.php'; return $this->raiseError($this->error); } @@ -212,6 +228,7 @@ public function parseAddressList($address = null, $default_domain = null, $nest_ $valid = $this->_validateAddress($address); if ($valid === false || isset($this->error)) { + // Z-Push change: rasiseError dependancy //require_once 'PEAR.php'; return $this->raiseError($this->error); } @@ -252,6 +269,7 @@ protected function _splitAddresses($address) } // Split the string based on the above ten or so lines. + // Z-Push change: (string) cast $parts = explode($split_char, (string) $address); $string = $this->_splitCheck($parts, $split_char); @@ -284,6 +302,7 @@ protected function _splitAddresses($address) // Remove the now stored address from the initial line, the +1 // is to account for the explode character. + // Z-Push change: (string) cast $address = trim(substr((string) $address, strlen($string) + 1)); // If the next char is a comma and this was a group, then @@ -313,6 +332,7 @@ protected function _splitAddresses($address) protected function _isGroup($address) { // First comma not in quotes, angles or escaped: + // Z-Push change: (string) cast $parts = explode(',', (string) $address); $string = $this->_splitCheck($parts, ','); From 7101d16afd80d3e2974ec31e819762e79d688a1a Mon Sep 17 00:00:00 2001 From: matidau <65836048+matidau@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:24:54 +1000 Subject: [PATCH 3/4] Update Mail.php to v2.0.0 from <1.3.0 --- src/backend/imap/Mail.php | 66 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/backend/imap/Mail.php b/src/backend/imap/Mail.php index b1ba915b..e56cd38a 100644 --- a/src/backend/imap/Mail.php +++ b/src/backend/imap/Mail.php @@ -1,32 +1,34 @@ - * @copyright 1997-2010 Chuck Hagenbuch - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Mail.php 307489 2011-01-14 19:06:57Z alec $ + * @copyright 1997-2017 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ * @link http://pear.php.net/package/Mail/ */ @@ -62,8 +64,7 @@ * mailers under the PEAR hierarchy, and provides supporting functions * useful in multiple mailer backends. * - * @access public - * @version $Revision: 307489 $ + * @version $Revision$ * @package Mail */ class Mail @@ -72,7 +73,7 @@ class Mail * Line terminator used for separating header lines. * @var string */ - var $sep = "\r\n"; + public $sep = "\r\n"; /** * Provides an interface for generating Mail:: objects of various @@ -80,12 +81,13 @@ class Mail * * @param string $driver The kind of Mail:: object to instantiate. * @param array $params The parameters to pass to the Mail:: object. + * * @return object Mail a instance of the driver class or if fails a PEAR Error - * @access public */ - static function &factory($driver, $params = array()) + public static function factory($driver, $params = array()) { $driver = strtolower($driver); + @include_once 'Mail/' . $driver . '.php'; $class = 'Mail_' . $driver; if (class_exists($class)) { $mailer = new $class($params); @@ -119,10 +121,9 @@ static function &factory($driver, $params = array()) * containing a descriptive error message on * failure. * - * @access public * @deprecated use Mail_mail::send instead */ - function send($recipients, $headers, $body) + public function send($recipients, $headers, $body) { if (!is_array($headers)) { return Mail::raiseError('$headers must be an array'); @@ -159,18 +160,14 @@ function send($recipients, $headers, $body) * filter is to prevent mail injection attacks. * * @param array $headers The associative array of headers to sanitize. - * - * @access private */ - function _sanitizeHeaders(&$headers) + protected function _sanitizeHeaders(&$headers) { foreach ($headers as $key => $value) { $headers[$key] = preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', - null, $value); + '', $value); } - - return true; } /** @@ -187,15 +184,15 @@ function _sanitizeHeaders(&$headers) * otherwise returns an array containing two * elements: Any From: address found in the headers, * and the plain text version of the headers. - * @access private */ - function prepareHeaders($headers) + protected function prepareHeaders($headers) { $lines = array(); $from = null; foreach ($headers as $key => $value) { if (strcasecmp($key, 'From') === 0) { + //include_once 'Mail/RFC822.php'; $parser = new Mail_RFC822(); $addresses = $parser->parseAddressList($value, 'localhost', false); //if (is_a($addresses, 'PEAR_Error')) { @@ -249,10 +246,11 @@ function prepareHeaders($headers) * * @return mixed An array of forward paths (bare addresses) or a PEAR_Error * object if the address list could not be parsed. - * @access private */ - function parseRecipients($recipients) + protected function parseRecipients($recipients) { + //include_once 'Mail/RFC822.php'; + // if we're passed an array, assume addresses are valid and // implode them before parsing. if (is_array($recipients)) { @@ -262,8 +260,8 @@ function parseRecipients($recipients) // Parse recipients, leaving out all personal info. This is // for smtp recipients, etc. All relevant personal information // should already be in the headers. - $parser = new Mail_RFC822(); - $addresses = $parser->parseAddressList($recipients, 'localhost', false); + $Mail_RFC822 = new Mail_RFC822(); + $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false); // If parseAddressList() returned a PEAR_Error object, just return it. //if (is_a($addresses, 'PEAR_Error')) { From 8798de3d779221f8728440c005306364d61d8aae Mon Sep 17 00:00:00 2001 From: matidau <65836048+matidau@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:38:24 +1000 Subject: [PATCH 4/4] Update Mail.php comments on Z-push changes --- src/backend/imap/Mail.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/backend/imap/Mail.php b/src/backend/imap/Mail.php index e56cd38a..ff599387 100644 --- a/src/backend/imap/Mail.php +++ b/src/backend/imap/Mail.php @@ -50,10 +50,11 @@ * Z-Push changes * * removed PEAR dependency by implementing own raiseError() + * Remove duplicated addresses + * remove include dependancy * * Reference implementation used: - * http://download.pear.php.net/package/Mail-1.2.0.tgz - * SVN trunk version r333509 + * https://github.com/pear/Mail/tree/v2.0.0 * * */ @@ -93,6 +94,7 @@ public static function factory($driver, $params = array()) $mailer = new $class($params); return $mailer; } else { + // Z-Push change: rasiseError dependancy return Mail::raiseError('Unable to find class for driver ' . $driver); } } @@ -126,10 +128,12 @@ public static function factory($driver, $params = array()) public function send($recipients, $headers, $body) { if (!is_array($headers)) { + // Z-Push change: rasiseError dependancy return Mail::raiseError('$headers must be an array'); } $result = $this->_sanitizeHeaders($headers); + // Z-Push change: rasiseError dependancy //if (is_a($result, 'PEAR_Error')) { if ($result === false) { return $result; @@ -192,9 +196,11 @@ protected function prepareHeaders($headers) foreach ($headers as $key => $value) { if (strcasecmp($key, 'From') === 0) { + // Z-Push change: remove include dependancy //include_once 'Mail/RFC822.php'; $parser = new Mail_RFC822(); $addresses = $parser->parseAddressList($value, 'localhost', false); + // Z-Push change: rasiseError dependancy //if (is_a($addresses, 'PEAR_Error')) { if ($addresses === false) { return $addresses; @@ -249,6 +255,7 @@ protected function prepareHeaders($headers) */ protected function parseRecipients($recipients) { + // Z-Push change: remove include dependancy //include_once 'Mail/RFC822.php'; // if we're passed an array, assume addresses are valid and @@ -264,6 +271,7 @@ protected function parseRecipients($recipients) $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false); // If parseAddressList() returned a PEAR_Error object, just return it. + // Z-Push change: rasiseError dependancy //if (is_a($addresses, 'PEAR_Error')) { if ($addresses === false) { return $addresses; @@ -276,7 +284,7 @@ protected function parseRecipients($recipients) } } - // Remove duplicated + // Z-Push addition: Remove duplicated $recipients = array_unique($recipients); return $recipients;