<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[39724] branches/4.4: Mail: Upgrade PHPMailer to 5.2.21.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/39724">39724</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/39724","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-01-06 05:37:55 +0000 (Fri, 06 Jan 2017)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Mail: Upgrade PHPMailer to 5.2.21.
Merges <a href="https://core.trac.wordpress.org/changeset/39645">[39645]</a> to the 4.4 branch.
See <a href="https://core.trac.wordpress.org/ticket/37210">#37210</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branches44srcwpincludesclassphpmailerphp">branches/4.4/src/wp-includes/class-phpmailer.php</a></li>
<li><a href="#branches44srcwpincludesclasssmtpphp">branches/4.4/src/wp-includes/class-smtp.php</a></li>
</ul>
<h3>Property Changed</h3>
<ul>
<li><a href="#branches44">branches/4.4/</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<span class="cx" style="display: block; padding: 0 10px">Index: branches/4.4
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- branches/4.4 2017-01-06 05:35:54 UTC (rev 39723)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ branches/4.4 2017-01-06 05:37:55 UTC (rev 39724)
</ins><a id="branches44"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: branches/4.4</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:mergeinfo</h4></div>
<span class="cx" style="display: block; padding: 0 10px"> /branches/3.3:20543
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/3.4:21757
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/4.6:38615
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/trunk:18512,35802,35823,35825-35826,35829,35832-35834,35837,35839,35850,35876,35880,35897,35922,35931,35933,35943-35944,35978,35994,36003,36005,36007,36038,36040,36042,36045,36048,36056,36068,36081,36089,36094,36096-36097,36100,36108,36110,36117,36119-36121,36123,36130,36132,36134,36137,36141,36154,36157,36163,36168,36226,36249,36251,36258,36260-36261,36275-36277,36323-36324,36326,36359,36368,36411,36429,36435,36989,37124,37145,37150,37651,37730,38524,39659
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/trunk:18512,35802,35823,35825-35826,35829,35832-35834,35837,35839,35850,35876,35880,35897,35922,35931,35933,35943-35944,35978,35994,36003,36005,36007,36038,36040,36042,36045,36048,36056,36068,36081,36089,36094,36096-36097,36100,36108,36110,36117,36119-36121,36123,36130,36132,36134,36137,36141,36154,36157,36163,36168,36226,36249,36251,36258,36260-36261,36275-36277,36323-36324,36326,36359,36368,36411,36429,36435,36989,37124,37145,37150,37651,37730,38524,39645,39659
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="branches44srcwpincludesclassphpmailerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.4/src/wp-includes/class-phpmailer.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.4/src/wp-includes/class-phpmailer.php 2017-01-06 05:35:54 UTC (rev 39723)
+++ branches/4.4/src/wp-includes/class-phpmailer.php 2017-01-06 05:37:55 UTC (rev 39724)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,7 +31,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * The PHPMailer Version number.
</span><span class="cx" style="display: block; padding: 0 10px"> * @var string
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public $Version = '5.2.14';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public $Version = '5.2.21';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Email priority.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -201,6 +201,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * An ID to be used in the Message-ID header.
</span><span class="cx" style="display: block; padding: 0 10px"> * If empty, a unique id will be generated.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * You can set your own, but it must be in the format "<id@domain>",
+ * as defined in RFC5322 section 3.6.4 or it will be ignored.
+ * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var string
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public $MessageID = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -285,7 +288,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SMTP auth type.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Options are CRAM-MD5, LOGIN, PLAIN, attempted in that order if not specified
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var string
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public $AuthType = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -352,6 +355,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Whether to split multiple to addresses into multiple messages
</span><span class="cx" style="display: block; padding: 0 10px"> * or send them all in one message.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Only supported in `mail` and `sendmail` transports, not in SMTP.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var boolean
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public $SingleTo = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -394,7 +398,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * DKIM Identity.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Usually the email address used as the source of the email
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Usually the email address used as the source of the email.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var string
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public $DKIM_identity = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -420,6 +424,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public $DKIM_private = '';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * DKIM private key string.
+ * If set, takes precedence over `$DKIM_private`.
+ * @var string
+ */
+ public $DKIM_private_string = '';
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Callback Action function name.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * The function that handles the result of the send email action.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -447,6 +458,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public $XMailer = '';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Which validator to use by default when validating email addresses.
+ * May be a callable to inject your own validator, but there are several built-in validators.
+ * @see PHPMailer::validateAddress()
+ * @var string|callable
+ * @static
+ */
+ public static $validator = 'auto';
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * An instance of the SMTP sender class.
</span><span class="cx" style="display: block; padding: 0 10px"> * @var SMTP
</span><span class="cx" style="display: block; padding: 0 10px"> * @access protected
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -634,9 +654,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Constructor.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param boolean $exceptions Should we throw external exceptions?
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function __construct($exceptions = false)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function __construct($exceptions = null)
</ins><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->exceptions = (boolean)$exceptions;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ($exceptions !== null) {
+ $this->exceptions = (boolean)$exceptions;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -645,9 +667,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public function __destruct()
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> //Close any open SMTP connection nicely
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->Mailer == 'smtp') {
- $this->smtpClose();
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->smtpClose();
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -671,14 +691,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $subject = $this->encodeHeader($this->secureHeader($subject));
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ //Can't use additional_parameters in safe_mode, calling mail() with null params breaks
+ //@link http://php.net/manual/en/function.mail.php
+ if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $result = @mail($to, $subject, $body, $header);
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $result = @mail($to, $subject, $body, $header, $params);
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> return $result;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Output debugging info via user-defined method.
</span><span class="cx" style="display: block; padding: 0 10px"> * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -713,7 +735,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> case 'echo':
</span><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> //Normalize line breaks
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $str = preg_replace('/\r\n?/ms', "\n", $str);
</ins><span class="cx" style="display: block; padding: 0 10px"> echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
</span><span class="cx" style="display: block; padding: 0 10px"> "\n",
</span><span class="cx" style="display: block; padding: 0 10px"> "\n \t ",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -850,7 +872,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
</span><span class="cx" style="display: block; padding: 0 10px"> if (($pos = strrpos($address, '@')) === false) {
</span><span class="cx" style="display: block; padding: 0 10px"> // At-sign is misssing.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $error_message = $this->lang('invalid_address') . $address;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setError($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->edebug($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->exceptions) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -900,7 +922,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->validateAddress($address)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $error_message = $this->lang('invalid_address') . $address;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setError($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->edebug($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->exceptions) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -924,6 +946,61 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
+ * of the form "display name <address>" into an array of name/address pairs.
+ * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
+ * Note that quotes in the name part are removed.
+ * @param string $addrstr The address list string
+ * @param bool $useimap Whether to use the IMAP extension to parse the list
+ * @return array
+ * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
+ */
+ public function parseAddresses($addrstr, $useimap = true)
+ {
+ $addresses = array();
+ if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
+ //Use this built-in parser if it's available
+ $list = imap_rfc822_parse_adrlist($addrstr, '');
+ foreach ($list as $address) {
+ if ($address->host != '.SYNTAX-ERROR.') {
+ if ($this->validateAddress($address->mailbox . '@' . $address->host)) {
+ $addresses[] = array(
+ 'name' => (property_exists($address, 'personal') ? $address->personal : ''),
+ 'address' => $address->mailbox . '@' . $address->host
+ );
+ }
+ }
+ }
+ } else {
+ //Use this simpler parser
+ $list = explode(',', $addrstr);
+ foreach ($list as $address) {
+ $address = trim($address);
+ //Is there a separate name part?
+ if (strpos($address, '<') === false) {
+ //No separate name, just use the whole thing
+ if ($this->validateAddress($address)) {
+ $addresses[] = array(
+ 'name' => '',
+ 'address' => $address
+ );
+ }
+ } else {
+ list($name, $email) = explode('<', $address);
+ $email = trim(str_replace('>', '', $email));
+ if ($this->validateAddress($email)) {
+ $addresses[] = array(
+ 'name' => trim(str_replace(array('"', "'"), '', $name)),
+ 'address' => $email
+ );
+ }
+ }
+ }
+ }
+ return $addresses;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Set the From and FromName properties.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $address
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $name
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -939,7 +1016,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if (($pos = strrpos($address, '@')) === false or
</span><span class="cx" style="display: block; padding: 0 10px"> (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
</span><span class="cx" style="display: block; padding: 0 10px"> !$this->validateAddress($address)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $error_message = $this->lang('invalid_address') . $address;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $error_message = $this->lang('invalid_address') . " (setFrom) $address";
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setError($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->edebug($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->exceptions) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -972,19 +1049,30 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Check that a string looks like an email address.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $address The email address to check
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $patternselect A selector for the validation pattern to use :
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string|callable $patternselect A selector for the validation pattern to use :
</ins><span class="cx" style="display: block; padding: 0 10px"> * * `auto` Pick best pattern automatically;
</span><span class="cx" style="display: block; padding: 0 10px"> * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
</span><span class="cx" style="display: block; padding: 0 10px"> * * `pcre` Use old PCRE implementation;
</span><span class="cx" style="display: block; padding: 0 10px"> * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
</span><span class="cx" style="display: block; padding: 0 10px"> * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
</span><span class="cx" style="display: block; padding: 0 10px"> * * `noregex` Don't use a regex: super fast, really dumb.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Alternatively you may pass in a callable to inject your own validator, for example:
+ * PHPMailer::validateAddress('user@example.com', function($address) {
+ * return (strpos($address, '@') !== false);
+ * });
+ * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return boolean
</span><span class="cx" style="display: block; padding: 0 10px"> * @static
</span><span class="cx" style="display: block; padding: 0 10px"> * @access public
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public static function validateAddress($address, $patternselect = 'auto')
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public static function validateAddress($address, $patternselect = null)
</ins><span class="cx" style="display: block; padding: 0 10px"> {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (is_null($patternselect)) {
+ $patternselect = self::$validator;
+ }
+ if (is_callable($patternselect)) {
+ return call_user_func($patternselect, $address);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
</span><span class="cx" style="display: block; padding: 0 10px"> if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1161,7 +1249,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->validateAddress($this->$address_kind)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $error_message = $this->lang('invalid_address') . $this->$address_kind;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind;
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setError($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->edebug($error_message);
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->exceptions) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1172,7 +1260,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Set whether the message is multipart/alternative
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (!empty($this->AltBody)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ($this->alternativeExists()) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->ContentType = 'multipart/alternative';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1206,9 +1294,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Sign with DKIM if enabled
</span><span class="cx" style="display: block; padding: 0 10px"> if (!empty($this->DKIM_domain)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- && !empty($this->DKIM_private)
</del><span class="cx" style="display: block; padding: 0 10px"> && !empty($this->DKIM_selector)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- && file_exists($this->DKIM_private)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ && (!empty($this->DKIM_private_string)
+ || (!empty($this->DKIM_private) && file_exists($this->DKIM_private))
+ )
+ ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $header_dkim = $this->DKIM_Add(
</span><span class="cx" style="display: block; padding: 0 10px"> $this->MIMEHeader . $this->mailHeader,
</span><span class="cx" style="display: block; padding: 0 10px"> $this->encodeHeader($this->secureHeader($this->Subject)),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1274,19 +1364,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> protected function sendmailSend($header, $body)
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->Sender != '') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+ if (!empty($this->Sender) and self::isShellSafe($this->Sender)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> if ($this->Mailer == 'qmail') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $sendmailFmt = '%s -f%s';
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $sendmailFmt = '%s -oi -f%s -t';
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->Mailer == 'qmail') {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $sendmailFmt = '%s';
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $sendmailFmt = '%s -oi -t';
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing.
+ $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ($this->SingleTo) {
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ($this->SingleToArray as $toAddr) {
</span><span class="cx" style="display: block; padding: 0 10px"> if (!@$mail = popen($sendmail, 'w')) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1333,6 +1428,40 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
+ *
+ * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
+ * @param string $string The string to be validated
+ * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
+ * @access protected
+ * @return boolean
+ */
+ protected static function isShellSafe($string)
+ {
+ // Future-proof
+ if (escapeshellcmd($string) !== $string
+ or !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))
+ ) {
+ return false;
+ }
+
+ $length = strlen($string);
+
+ for ($i = 0; $i < $length; $i++) {
+ $c = $string[$i];
+
+ // All other characters have a special meaning in at least one common shell, including = and +.
+ // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
+ // Note that this does permit non-Latin alphanumeric characters based on the current locale.
+ if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Send mail using the PHP mail() function.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $header The message headers
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $body The message body
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1349,17 +1478,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $to = implode(', ', $toArr);
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (empty($this->Sender)) {
- $params = ' ';
- } else {
- $params = sprintf('-f%s', $this->Sender);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $params = null;
+ //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
+ if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
+ // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
+ if (self::isShellSafe($this->Sender)) {
+ $params = sprintf('-f%s', $this->Sender);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->Sender != '' and !ini_get('safe_mode')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $old_from = ini_get('sendmail_from');
</span><span class="cx" style="display: block; padding: 0 10px"> ini_set('sendmail_from', $this->Sender);
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $result = false;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->SingleTo && count($toArr) > 1) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ($this->SingleTo and count($toArr) > 1) {
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ($toArr as $toAddr) {
</span><span class="cx" style="display: block; padding: 0 10px"> $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1409,10 +1541,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->smtpConnect($this->SMTPOptions)) {
</span><span class="cx" style="display: block; padding: 0 10px"> throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ('' == $this->Sender) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
+ $smtp_from = $this->Sender;
+ } else {
</ins><span class="cx" style="display: block; padding: 0 10px"> $smtp_from = $this->From;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- } else {
- $smtp_from = $this->Sender;
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->smtp->mail($smtp_from)) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1466,12 +1598,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @throws phpmailerException
</span><span class="cx" style="display: block; padding: 0 10px"> * @return boolean
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function smtpConnect($options = array())
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function smtpConnect($options = null)
</ins><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> if (is_null($this->smtp)) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->smtp = $this->getSMTPInstance();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //If no options are provided, use whatever is set in the instance
+ if (is_null($options)) {
+ $options = $this->SMTPOptions;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Already connected?
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->smtp->connected()) {
</span><span class="cx" style="display: block; padding: 0 10px"> return true;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1541,7 +1678,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->smtp->startTLS()) {
</span><span class="cx" style="display: block; padding: 0 10px"> throw new phpmailerException($this->lang('connect_host'));
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // We must resend HELO after tls negotiation
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // We must resend EHLO after TLS negotiation
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->smtp->hello($hello);
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->SMTPAuth) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1580,7 +1717,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function smtpClose()
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->smtp !== null) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (is_a($this->smtp, 'SMTP')) {
</ins><span class="cx" style="display: block; padding: 0 10px"> if ($this->smtp->connected()) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->smtp->quit();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->smtp->close();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1599,6 +1736,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function setLanguage($langcode = 'en', $lang_path = '')
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Backwards compatibility for renamed language codes
+ $renamed_langcodes = array(
+ 'br' => 'pt_br',
+ 'cz' => 'cs',
+ 'dk' => 'da',
+ 'no' => 'nb',
+ 'se' => 'sv',
+ );
+
+ if (isset($renamed_langcodes[$langcode])) {
+ $langcode = $renamed_langcodes[$langcode];
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Define full set of translatable strings in English
</span><span class="cx" style="display: block; padding: 0 10px"> $PHPMAILER_LANG = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'authenticate' => 'SMTP Error: Could not authenticate.',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1625,6 +1775,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Calculate an absolute path so it can work if CWD is not here
</span><span class="cx" style="display: block; padding: 0 10px"> $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //Validate $langcode
+ if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
+ $langcode = 'en';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $foundlang = true;
</span><span class="cx" style="display: block; padding: 0 10px"> $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
</span><span class="cx" style="display: block; padding: 0 10px"> // There is no English translation file
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1918,7 +2072,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ($this->MessageID != '') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
+ // https://tools.ietf.org/html/rfc5322#section-3.6.4
+ if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->lastMessageID = $this->MessageID;
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2020,10 +2176,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function getSentMIMEMessage()
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Create unique ID
+ * @return string
+ */
+ protected function generateId() {
+ return md5(uniqid(time()));
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Assemble the message body.
</span><span class="cx" style="display: block; padding: 0 10px"> * Returns an empty string on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> * @access public
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2034,7 +2198,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> $body = '';
</span><span class="cx" style="display: block; padding: 0 10px"> //Create unique IDs and preset boundaries
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->uniqueid = md5(uniqid(time()));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->uniqueid = $this->generateId();
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->boundary[1] = 'b1_' . $this->uniqueid;
</span><span class="cx" style="display: block; padding: 0 10px"> $this->boundary[2] = 'b2_' . $this->uniqueid;
</span><span class="cx" style="display: block; padding: 0 10px"> $this->boundary[3] = 'b3_' . $this->uniqueid;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2050,11 +2214,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> //Can we do a 7-bit downgrade?
</span><span class="cx" style="display: block; padding: 0 10px"> if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
</span><span class="cx" style="display: block; padding: 0 10px"> $bodyEncoding = '7bit';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
</ins><span class="cx" style="display: block; padding: 0 10px"> $bodyCharSet = 'us-ascii';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //If lines are too long, change to quoted-printable transfer encoding
- if (self::hasLineLongerThanMax($this->Body)) {
- $this->Encoding = 'quoted-printable';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //If lines are too long, and we're not already using an encoding that will shorten them,
+ //change to quoted-printable transfer encoding for the body part only
+ if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $bodyEncoding = 'quoted-printable';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2063,10 +2228,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> //Can we do a 7-bit downgrade?
</span><span class="cx" style="display: block; padding: 0 10px"> if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
</span><span class="cx" style="display: block; padding: 0 10px"> $altBodyEncoding = '7bit';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
</ins><span class="cx" style="display: block; padding: 0 10px"> $altBodyCharSet = 'us-ascii';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //If lines are too long, change to quoted-printable transfer encoding
- if (self::hasLineLongerThanMax($this->AltBody)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //If lines are too long, and we're not already using an encoding that will shorten them,
+ //change to quoted-printable transfer encoding for the alt body part only
+ if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $altBodyEncoding = 'quoted-printable';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> //Use this as a preamble in all multipart message types
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2169,8 +2336,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $body .= $this->attachAll('attachment', $this->boundary[1]);
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><span class="cx" style="display: block; padding: 0 10px"> default:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // catch case 'plain' and case ''
- $body .= $this->encodeString($this->Body, $bodyEncoding);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
+ //Reset the `Encoding` property in case we changed it for line length reasons
+ $this->Encoding = $bodyEncoding;
+ $body .= $this->encodeString($this->Body, $this->Encoding);
</ins><span class="cx" style="display: block; padding: 0 10px"> break;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2276,8 +2445,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Set the message type.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * PHPMailer only supports some preset message types,
- * not arbitrary MIME structures.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * PHPMailer only supports some preset message types, not arbitrary MIME structures.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access protected
</span><span class="cx" style="display: block; padding: 0 10px"> * @return void
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2295,6 +2463,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $this->message_type = implode('_', $type);
</span><span class="cx" style="display: block; padding: 0 10px"> if ($this->message_type == '') {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //The 'plain' message_type refers to the message having a single body element, not that it is plain-text
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->message_type = 'plain';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3209,16 +3378,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Create a message from an HTML string.
- * Automatically makes modifications for inline images and backgrounds
- * and creates a plain-text version by converting the HTML.
- * Overwrites any existing values in $this->Body and $this->AltBody
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Create a message body from an HTML string.
+ * Automatically inlines images and creates a plain-text version by converting the HTML,
+ * overwriting any existing values in Body and AltBody.
+ * $basedir is used when handling relative image paths, e.g. <img src="images/a.png">
+ * will look for an image file in $basedir/images/a.png and convert it to inline.
+ * If you don't want to apply these transformations to your HTML, just set Body and AltBody yourself.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access public
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $message HTML message string
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $basedir baseline directory for path
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $basedir base directory for relative paths to images
</ins><span class="cx" style="display: block; padding: 0 10px"> * @param boolean|callable $advanced Whether to use the internal HTML to text converter
</span><span class="cx" style="display: block; padding: 0 10px"> * or your own custom converter @see PHPMailer::html2text()
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return string $message
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return string $message The transformed message Body
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function msgHTML($message, $basedir = '', $advanced = false)
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3241,7 +3412,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $message
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) {
</ins><span class="cx" style="display: block; padding: 0 10px"> // Do not change urls for absolute images (thanks to corvuscorax)
</span><span class="cx" style="display: block; padding: 0 10px"> // Do not change urls that are already inline images
</span><span class="cx" style="display: block; padding: 0 10px"> $filename = basename($url);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3277,7 +3448,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
</span><span class="cx" style="display: block; padding: 0 10px"> $this->Body = $this->normalizeBreaks($message);
</span><span class="cx" style="display: block; padding: 0 10px"> $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (empty($this->AltBody)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (!$this->alternativeExists()) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
</span><span class="cx" style="display: block; padding: 0 10px"> self::CRLF . self::CRLF;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3288,7 +3459,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Convert an HTML string into plain text.
</span><span class="cx" style="display: block; padding: 0 10px"> * This is used by msgHTML().
</span><span class="cx" style="display: block; padding: 0 10px"> * Note - older versions of this function used a bundled advanced converter
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * which was been removed for license reasons in #232
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * which was been removed for license reasons in #232.
</ins><span class="cx" style="display: block; padding: 0 10px"> * Example usage:
</span><span class="cx" style="display: block; padding: 0 10px"> * <code>
</span><span class="cx" style="display: block; padding: 0 10px"> * // Use default conversion
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3588,7 +3759,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @access public
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $signHeader
</span><span class="cx" style="display: block; padding: 0 10px"> * @throws phpmailerException
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @return string
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return string The DKIM signature value
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function DKIM_Sign($signHeader)
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3598,15 +3769,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> return '';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $privKeyStr = file_get_contents($this->DKIM_private);
- if ($this->DKIM_passphrase != '') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private);
+ if ('' != $this->DKIM_passphrase) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $privKey = $privKeyStr;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $privKey = openssl_pkey_get_private($privKeyStr);
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if (openssl_sign($signHeader, $signature, $privKey)) {
- return base64_encode($signature);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ //Workaround for missing digest algorithms in old PHP & OpenSSL versions
+ //@link http://stackoverflow.com/a/11117338/333340
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0 and
+ in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
+ if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
+ openssl_pkey_free($privKey);
+ return base64_encode($signature);
+ }
+ } else {
+ $pinfo = openssl_pkey_get_details($privKey);
+ $hash = hash('sha256', $signHeader);
+ //'Magic' constant for SHA256 from RFC3447
+ //@link https://tools.ietf.org/html/rfc3447#page-43
+ $t = '3031300d060960864801650304020105000420' . $hash;
+ $pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3);
+ $eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t);
+
+ if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) {
+ openssl_pkey_free($privKey);
+ return base64_encode($signature);
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ openssl_pkey_free($privKey);
</ins><span class="cx" style="display: block; padding: 0 10px"> return '';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3623,7 +3814,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ($lines as $key => $line) {
</span><span class="cx" style="display: block; padding: 0 10px"> list($heading, $value) = explode(':', $line, 2);
</span><span class="cx" style="display: block; padding: 0 10px"> $heading = strtolower($heading);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces
</ins><span class="cx" style="display: block; padding: 0 10px"> $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $signHeader = implode("\r\n", $lines);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3661,7 +3852,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function DKIM_Add($headers_line, $subject, $body)
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
</ins><span class="cx" style="display: block; padding: 0 10px"> $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
</span><span class="cx" style="display: block; padding: 0 10px"> $DKIMquery = 'dns/txt'; // Query method
</span><span class="cx" style="display: block; padding: 0 10px"> $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3669,6 +3860,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = explode($this->LE, $headers_line);
</span><span class="cx" style="display: block; padding: 0 10px"> $from_header = '';
</span><span class="cx" style="display: block; padding: 0 10px"> $to_header = '';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $date_header = '';
</ins><span class="cx" style="display: block; padding: 0 10px"> $current = '';
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ($headers as $header) {
</span><span class="cx" style="display: block; padding: 0 10px"> if (strpos($header, 'From:') === 0) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3677,6 +3869,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } elseif (strpos($header, 'To:') === 0) {
</span><span class="cx" style="display: block; padding: 0 10px"> $to_header = $header;
</span><span class="cx" style="display: block; padding: 0 10px"> $current = 'to_header';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } elseif (strpos($header, 'Date:') === 0) {
+ $date_header = $header;
+ $current = 'date_header';
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> if (!empty($$current) && strpos($header, ' =?') === 0) {
</span><span class="cx" style="display: block; padding: 0 10px"> $$current .= $header;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3687,6 +3882,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
</span><span class="cx" style="display: block; padding: 0 10px"> $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
</ins><span class="cx" style="display: block; padding: 0 10px"> $subject = str_replace(
</span><span class="cx" style="display: block; padding: 0 10px"> '|',
</span><span class="cx" style="display: block; padding: 0 10px"> '=7C',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3694,7 +3890,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ); // Copied header fields (dkim-quoted-printable)
</span><span class="cx" style="display: block; padding: 0 10px"> $body = $this->DKIM_BodyC($body);
</span><span class="cx" style="display: block; padding: 0 10px"> $DKIMlen = strlen($body); // Length of body
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
</ins><span class="cx" style="display: block; padding: 0 10px"> if ('' == $this->DKIM_identity) {
</span><span class="cx" style="display: block; padding: 0 10px"> $ident = '';
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3707,16 +3903,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->DKIM_selector .
</span><span class="cx" style="display: block; padding: 0 10px"> ";\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "\th=From:To:Subject;\r\n" .
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "\th=From:To:Date:Subject;\r\n" .
</ins><span class="cx" style="display: block; padding: 0 10px"> "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> "\tz=$from\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> "\t|$to\r\n" .
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "\t|$date\r\n" .
</ins><span class="cx" style="display: block; padding: 0 10px"> "\t|$subject;\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> "\tbh=" . $DKIMb64 . ";\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> "\tb=";
</span><span class="cx" style="display: block; padding: 0 10px"> $toSign = $this->DKIM_HeaderC(
</span><span class="cx" style="display: block; padding: 0 10px"> $from_header . "\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> $to_header . "\r\n" .
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $date_header . "\r\n" .
</ins><span class="cx" style="display: block; padding: 0 10px"> $subject_header . "\r\n" .
</span><span class="cx" style="display: block; padding: 0 10px"> $dkimhdrs
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span></span></pre></div>
<a id="branches44srcwpincludesclasssmtpphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.4/src/wp-includes/class-smtp.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.4/src/wp-includes/class-smtp.php 2017-01-06 05:35:54 UTC (rev 39723)
+++ branches/4.4/src/wp-includes/class-smtp.php 2017-01-06 05:37:55 UTC (rev 39724)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,7 +30,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * The PHPMailer SMTP version number.
</span><span class="cx" style="display: block; padding: 0 10px"> * @var string
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const VERSION = '5.2.14';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VERSION = '5.2.21';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SMTP line break constant.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,7 +81,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @deprecated Use the `VERSION` constant instead
</span><span class="cx" style="display: block; padding: 0 10px"> * @see SMTP::VERSION
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public $Version = '5.2.14';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public $Version = '5.2.21';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * SMTP server port number.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -150,6 +150,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public $Timelimit = 300;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @var array patterns to extract smtp transaction id from smtp reply
+ * Only first capture group will be use, use non-capturing group to deal with it
+ * Extend this class to override this property to fulfil your needs.
+ */
+ protected $smtp_transaction_id_patterns = array(
+ 'exim' => '/[0-9]{3} OK id=(.*)/',
+ 'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/',
+ 'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/'
+ );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * The socket for the server connection.
</span><span class="cx" style="display: block; padding: 0 10px"> * @var resource
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -206,7 +217,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> //Avoid clash with built-in function names
</span><span class="cx" style="display: block; padding: 0 10px"> if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- call_user_func($this->Debugoutput, $str, $this->do_debug);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ call_user_func($this->Debugoutput, $str, $level);
</ins><span class="cx" style="display: block; padding: 0 10px"> return;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> switch ($this->Debugoutput) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -272,8 +283,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $errstr = '';
</span><span class="cx" style="display: block; padding: 0 10px"> if ($streamok) {
</span><span class="cx" style="display: block; padding: 0 10px"> $socket_context = stream_context_create($options);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- //Suppress errors; connection failures are handled at a higher level
- $this->smtp_conn = @stream_socket_client(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ set_error_handler(array($this, 'errorHandler'));
+ $this->smtp_conn = stream_socket_client(
</ins><span class="cx" style="display: block; padding: 0 10px"> $host . ":" . $port,
</span><span class="cx" style="display: block; padding: 0 10px"> $errno,
</span><span class="cx" style="display: block; padding: 0 10px"> $errstr,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -281,12 +292,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> STREAM_CLIENT_CONNECT,
</span><span class="cx" style="display: block; padding: 0 10px"> $socket_context
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ restore_error_handler();
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> //Fall back to fsockopen which should work in more places, but is missing some features
</span><span class="cx" style="display: block; padding: 0 10px"> $this->edebug(
</span><span class="cx" style="display: block; padding: 0 10px"> "Connection: stream_socket_client not available, falling back to fsockopen",
</span><span class="cx" style="display: block; padding: 0 10px"> self::DEBUG_CONNECTION
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ set_error_handler(array($this, 'errorHandler'));
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->smtp_conn = fsockopen(
</span><span class="cx" style="display: block; padding: 0 10px"> $host,
</span><span class="cx" style="display: block; padding: 0 10px"> $port,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -294,6 +307,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $errstr,
</span><span class="cx" style="display: block; padding: 0 10px"> $timeout
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ restore_error_handler();
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> // Verify we connected properly
</span><span class="cx" style="display: block; padding: 0 10px"> if (!is_resource($this->smtp_conn)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -336,11 +350,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ //Allow the best TLS version(s) we can
+ $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
+
+ //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
+ //so add them back in manually if we can
+ if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
+ $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+ $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Begin encrypted connection
</span><span class="cx" style="display: block; padding: 0 10px"> if (!stream_socket_enable_crypto(
</span><span class="cx" style="display: block; padding: 0 10px"> $this->smtp_conn,
</span><span class="cx" style="display: block; padding: 0 10px"> true,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- STREAM_CRYPTO_METHOD_TLS_CLIENT
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $crypto_method
</ins><span class="cx" style="display: block; padding: 0 10px"> )) {
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -353,7 +378,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @see hello()
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $username The user name
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $password The password
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5, XOAUTH2)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $authtype The auth type (PLAIN, LOGIN, CRAM-MD5)
</ins><span class="cx" style="display: block; padding: 0 10px"> * @param string $realm The auth realm for NTLM
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $workstation The auth workstation for NTLM
</span><span class="cx" style="display: block; padding: 0 10px"> * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -389,7 +414,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if (empty($authtype)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach (array('LOGIN', 'CRAM-MD5', 'PLAIN') as $method) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN') as $method) {
</ins><span class="cx" style="display: block; padding: 0 10px"> if (in_array($method, $this->server_caps['AUTH'])) {
</span><span class="cx" style="display: block; padding: 0 10px"> $authtype = $method;
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -673,7 +698,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> protected function parseHelloFields($type)
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->server_caps = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $lines = explode("\n", $this->last_reply);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $lines = explode("\n", $this->helo_rply);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ($lines as $n => $s) {
</span><span class="cx" style="display: block; padding: 0 10px"> //First 4 chars contain response code followed by - or space
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1115,4 +1140,47 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> return $this->Timeout;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * Reports an error number and string.
+ * @param integer $errno The error number returned by PHP.
+ * @param string $errmsg The error message returned by PHP.
+ */
+ protected function errorHandler($errno, $errmsg)
+ {
+ $notice = 'Connection: Failed to connect to server.';
+ $this->setError(
+ $notice,
+ $errno,
+ $errmsg
+ );
+ $this->edebug(
+ $notice . ' Error number ' . $errno . '. "Error notice: ' . $errmsg,
+ self::DEBUG_CONNECTION
+ );
+ }
+
+ /**
+ * Will return the ID of the last smtp transaction based on a list of patterns provided
+ * in SMTP::$smtp_transaction_id_patterns.
+ * If no reply has been received yet, it will return null.
+ * If no pattern has been matched, it will return false.
+ * @return bool|null|string
+ */
+ public function getLastTransactionID()
+ {
+ $reply = $this->getLastReply();
+
+ if (empty($reply)) {
+ return null;
+ }
+
+ foreach($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
+ if(preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
+ return $matches[1];
+ }
+ }
+
+ return false;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>