summaryrefslogtreecommitdiffstats
path: root/system/libraries/Email.php
diff options
context:
space:
mode:
Diffstat (limited to 'system/libraries/Email.php')
-rw-r--r--system/libraries/Email.php270
1 files changed, 115 insertions, 155 deletions
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index d7178f321..55f81f4bd 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,8 +29,8 @@
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
- * @license http://opensource.org/licenses/MIT MIT License
+ * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (https://bcit.ca/)
+ * @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
@@ -174,7 +174,7 @@ class CI_Email {
* Newline character sequence.
* Use "\r\n" to comply with RFC 822.
*
- * @link http://www.ietf.org/rfc/rfc822.txt
+ * @link https://www.ietf.org/rfc/rfc822.txt
* @var string "\r\n" or "\n"
*/
public $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
@@ -188,7 +188,7 @@ class CI_Email {
* switching to "\n", while improper, is the only solution
* that seems to work for all environments.
*
- * @link http://www.ietf.org/rfc/rfc822.txt
+ * @link https://www.ietf.org/rfc/rfc822.txt
* @var string
*/
public $crlf = "\n";
@@ -893,18 +893,13 @@ class CI_Email {
/**
* Get Mail Protocol
*
- * @param bool
* @return mixed
*/
- protected function _get_protocol($return = TRUE)
+ protected function _get_protocol()
{
$this->protocol = strtolower($this->protocol);
in_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';
-
- if ($return === TRUE)
- {
- return $this->protocol;
- }
+ return $this->protocol;
}
// --------------------------------------------------------------------
@@ -912,25 +907,21 @@ class CI_Email {
/**
* Get Mail Encoding
*
- * @param bool
* @return string
*/
- protected function _get_encoding($return = TRUE)
+ protected function _get_encoding()
{
in_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit';
foreach ($this->_base_charsets as $charset)
{
- if (strpos($charset, $this->charset) === 0)
+ if (strpos($this->charset, $charset) === 0)
{
$this->_encoding = '7bit';
}
}
- if ($return === TRUE)
- {
- return $this->_encoding;
- }
+ return $this->_encoding;
}
// --------------------------------------------------------------------
@@ -950,10 +941,8 @@ class CI_Email {
{
return 'plain-attach';
}
- else
- {
- return 'plain';
- }
+
+ return 'plain';
}
// --------------------------------------------------------------------
@@ -1023,9 +1012,12 @@ class CI_Email {
*/
public function valid_email($email)
{
- if (function_exists('idn_to_ascii') && $atpos = strpos($email, '@'))
+ if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $email, $matches))
{
- $email = self::substr($email, 0, ++$atpos).idn_to_ascii(self::substr($email, $atpos));
+ $domain = defined('INTL_IDNA_VARIANT_UTS46')
+ ? idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46)
+ : idn_to_ascii($matches[2]);
+ $email = $matches[1].'@'.$domain;
}
return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
@@ -1244,7 +1236,7 @@ class CI_Email {
/**
* Build Final Body and attachments
*
- * @return bool
+ * @return void
*/
protected function _build_message()
{
@@ -1411,8 +1403,6 @@ class CI_Email {
$this->_finalbody = ($this->_get_protocol() === 'mail')
? $body
: $hdr.$this->newline.$this->newline.$body;
-
- return TRUE;
}
// --------------------------------------------------------------------
@@ -1473,7 +1463,7 @@ class CI_Email {
* Prep Quoted Printable
*
* Prepares string for Quoted-Printable Content-Transfer-Encoding
- * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
+ * Refer to RFC 2045 https://www.ietf.org/rfc/rfc2045.txt
*
* @param string
* @return string
@@ -1482,7 +1472,7 @@ class CI_Email {
{
// ASCII code numbers for "safe" characters that can always be
// used literally, without encoding, as described in RFC 2049.
- // http://www.ietf.org/rfc/rfc2049.txt
+ // https://www.ietf.org/rfc/rfc2049.txt
static $ascii_safe_chars = array(
// ' ( ) + , - . / : = ?
39, 40, 41, 43, 44, 45, 46, 47, 58, 61, 63,
@@ -1674,8 +1664,8 @@ class CI_Email {
$this->reply_to($this->_headers['From']);
}
- if ( ! isset($this->_recipients) && ! isset($this->_headers['To'])
- && ! isset($this->_bcc_array) && ! isset($this->_headers['Bcc'])
+ if (empty($this->_recipients) && ! isset($this->_headers['To'])
+ && empty($this->_bcc_array) && ! isset($this->_headers['Bcc'])
&& ! isset($this->_headers['Cc']))
{
$this->_set_error_message('lang:email_no_recipients');
@@ -1686,21 +1676,17 @@ class CI_Email {
if ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size)
{
- $result = $this->batch_bcc_send();
+ $this->batch_bcc_send();
- if ($result && $auto_clear)
+ if ($auto_clear)
{
$this->clear();
}
- return $result;
- }
-
- if ($this->_build_message() === FALSE)
- {
- return FALSE;
+ return TRUE;
}
+ $this->_build_message();
$result = $this->_spool_email();
if ($result && $auto_clear)
@@ -1759,11 +1745,7 @@ class CI_Email {
$this->_bcc_array = $bcc;
}
- if ($this->_build_message() === FALSE)
- {
- return FALSE;
- }
-
+ $this->_build_message();
$this->_spool_email();
}
}
@@ -1809,14 +1791,15 @@ class CI_Email {
{
$this->_unwrap_specials();
- $method = '_send_with_'.$this->_get_protocol();
+ $protocol = $this->_get_protocol();
+ $method = '_send_with_'.$protocol;
if ( ! $this->$method())
{
- $this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));
+ $this->_set_error_message('lang:email_send_failure_'.($protocol === 'mail' ? 'phpmail' : $protocol));
return FALSE;
}
- $this->_set_error_message('lang:email_sent', $this->_get_protocol());
+ $this->_set_error_message('lang:email_sent', $protocol);
return TRUE;
}
@@ -1841,7 +1824,11 @@ class CI_Email {
{
if (function_exists('idn_to_ascii') && $atpos = strpos($email, '@'))
{
- $email = self::substr($email, 0, ++$atpos).idn_to_ascii(self::substr($email, $atpos));
+ list($account, $domain) = explode('@', $email, 2);
+ $domain = defined('INTL_IDNA_VARIANT_UTS46')
+ ? idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)
+ : idn_to_ascii($domain);
+ $email = $account.'@'.$domain;
}
return (filter_var($email, FILTER_VALIDATE_EMAIL) === $email && preg_match('#\A[a-z0-9._+-]+@[a-z0-9.-]{1,253}\z#i', $email));
@@ -1953,27 +1940,21 @@ class CI_Email {
}
}
- if (count($this->_cc_array) > 0)
+ foreach ($this->_cc_array as $val)
{
- foreach ($this->_cc_array as $val)
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- if ($val !== '' && ! $this->_send_command('to', $val))
- {
- $this->_smtp_end();
- return FALSE;
- }
+ $this->_smtp_end();
+ return FALSE;
}
}
- if (count($this->_bcc_array) > 0)
+ foreach ($this->_bcc_array as $val)
{
- foreach ($this->_bcc_array as $val)
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- if ($val !== '' && ! $this->_send_command('to', $val))
- {
- $this->_smtp_end();
- return FALSE;
- }
+ $this->_smtp_end();
+ return FALSE;
}
}
@@ -1987,7 +1968,6 @@ class CI_Email {
$this->_send_data($this->_header_str.preg_replace('/^\./m', '..$1', $this->_finalbody));
$this->_send_data('.');
-
$reply = $this->_get_smtp_data();
$this->_set_error_message($reply);
@@ -2013,9 +1993,7 @@ class CI_Email {
*/
protected function _smtp_end()
{
- ($this->smtp_keepalive)
- ? $this->_send_command('reset')
- : $this->_send_command('quit');
+ $this->_send_command($this->smtp_keepalive ? 'reset' : 'quit');
}
// --------------------------------------------------------------------
@@ -2034,11 +2012,13 @@ class CI_Email {
$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : '';
- $this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
- $this->smtp_port,
- $errno,
- $errstr,
- $this->smtp_timeout);
+ $this->_smtp_connect = fsockopen(
+ $ssl.$this->smtp_host,
+ $this->smtp_port,
+ $errno,
+ $errstr,
+ $this->smtp_timeout
+ );
if ( ! is_resource($this->_smtp_connect))
{
@@ -2054,7 +2034,19 @@ class CI_Email {
$this->_send_command('hello');
$this->_send_command('starttls');
- $crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+ /**
+ * STREAM_CRYPTO_METHOD_TLS_CLIENT is quite the mess ...
+ *
+ * - On PHP <5.6 it doesn't even mean TLS, but SSL 2.0, and there's no option to use actual TLS
+ * - On PHP 5.6.0-5.6.6, >=7.2 it means negotiation with any of TLS 1.0, 1.1, 1.2
+ * - On PHP 5.6.7-7.1.* it means only TLS 1.0
+ *
+ * We want the negotiation, so we'll force it below ...
+ */
+ $method = is_php('5.6')
+ ? STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
+ : STREAM_CRYPTO_METHOD_TLS_CLIENT;
+ $crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, $method);
if ($crypto !== TRUE)
{
@@ -2079,57 +2071,49 @@ class CI_Email {
{
switch ($cmd)
{
- case 'hello' :
-
- if ($this->_smtp_auth OR $this->_get_encoding() === '8bit')
- {
- $this->_send_data('EHLO '.$this->_get_hostname());
- }
- else
- {
- $this->_send_data('HELO '.$this->_get_hostname());
- }
-
- $resp = 250;
- break;
- case 'starttls' :
-
- $this->_send_data('STARTTLS');
- $resp = 220;
- break;
- case 'from' :
-
- $this->_send_data('MAIL FROM:<'.$data.'>');
- $resp = 250;
- break;
- case 'to' :
-
- if ($this->dsn)
- {
- $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);
- }
- else
- {
- $this->_send_data('RCPT TO:<'.$data.'>');
- }
-
- $resp = 250;
- break;
- case 'data' :
-
- $this->_send_data('DATA');
- $resp = 354;
- break;
- case 'reset':
-
- $this->_send_data('RSET');
- $resp = 250;
- break;
- case 'quit' :
+ case 'hello':
+ if ($this->_smtp_auth OR $this->_get_encoding() === '8bit')
+ {
+ $this->_send_data('EHLO '.$this->_get_hostname());
+ }
+ else
+ {
+ $this->_send_data('HELO '.$this->_get_hostname());
+ }
- $this->_send_data('QUIT');
- $resp = 221;
- break;
+ $resp = 250;
+ break;
+ case 'starttls':
+ $this->_send_data('STARTTLS');
+ $resp = 220;
+ break;
+ case 'from':
+ $this->_send_data('MAIL FROM:<'.$data.'>');
+ $resp = 250;
+ break;
+ case 'to':
+ if ($this->dsn)
+ {
+ $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);
+ }
+ else
+ {
+ $this->_send_data('RCPT TO:<'.$data.'>');
+ }
+ $resp = 250;
+ break;
+ case 'data':
+ $this->_send_data('DATA');
+ $resp = 354;
+ break;
+ case 'reset':
+ $this->_send_data('RSET');
+ $resp = 250;
+ break;
+ case 'quit':
+ $this->_send_data('QUIT');
+ $resp = 221;
+ break;
}
$reply = $this->_get_smtp_data();
@@ -2171,7 +2155,6 @@ class CI_Email {
}
$this->_send_data('AUTH LOGIN');
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '503') === 0) // Already authenticated
@@ -2185,7 +2168,6 @@ class CI_Email {
}
$this->_send_data(base64_encode($this->smtp_user));
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '334') !== 0)
@@ -2195,7 +2177,6 @@ class CI_Email {
}
$this->_send_data(base64_encode($this->smtp_pass));
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '235') !== 0)
@@ -2229,7 +2210,7 @@ class CI_Email {
{
break;
}
- // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951
+ // See https://bugs.php.net/bug.php?id=39598 and https://secure.php.net/manual/en/function.fwrite.php#96951
elseif ($result === 0)
{
if ($timestamp === 0)
@@ -2245,10 +2226,8 @@ class CI_Email {
usleep(250000);
continue;
}
- else
- {
- $timestamp = 0;
- }
+
+ $timestamp = 0;
}
if ($result === FALSE)
@@ -2294,7 +2273,7 @@ class CI_Email {
* (eg: "[1.2.3.4]").
*
* @link https://tools.ietf.org/html/rfc5321#section-2.3.5
- * @link http://cbl.abuseat.org/namingproblems.html
+ * @link https://cbl.abuseat.org/namingproblems.html
* @return string
*/
protected function _get_hostname()
@@ -2318,34 +2297,15 @@ class CI_Email {
*/
public function print_debugger($include = array('headers', 'subject', 'body'))
{
- $msg = '';
-
- if (count($this->_debug_msg) > 0)
- {
- foreach ($this->_debug_msg as $val)
- {
- $msg .= $val;
- }
- }
+ $msg = implode('', $this->_debug_msg);
// Determine which parts of our raw data needs to be printed
$raw_data = '';
is_array($include) OR $include = array($include);
- if (in_array('headers', $include, TRUE))
- {
- $raw_data = htmlspecialchars($this->_header_str)."\n";
- }
-
- if (in_array('subject', $include, TRUE))
- {
- $raw_data .= htmlspecialchars($this->_subject)."\n";
- }
-
- if (in_array('body', $include, TRUE))
- {
- $raw_data .= htmlspecialchars($this->_finalbody);
- }
+ in_array('headers', $include, TRUE) && $raw_data = htmlspecialchars($this->_header_str)."\n";
+ in_array('subject', $include, TRUE) && $raw_data .= htmlspecialchars($this->_subject)."\n";
+ in_array('body', $include, TRUE) && $raw_data .= htmlspecialchars($this->_finalbody);
return $msg.($raw_data === '' ? '' : '<pre>'.$raw_data.'</pre>');
}