-
-
Notifications
You must be signed in to change notification settings - Fork 458
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Michael Kaufmann (d00p) <[email protected]>
- Loading branch information
Showing
2 changed files
with
73 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ class PHPMailer | |
* The PHPMailer Version number. | ||
* @var string | ||
*/ | ||
public $Version = '5.2.14'; | ||
public $Version = '5.2.15'; | ||
|
||
/** | ||
* Email priority. | ||
|
@@ -352,6 +352,7 @@ class PHPMailer | |
/** | ||
* Whether to split multiple to addresses into multiple messages | ||
* or send them all in one message. | ||
* Only supported in `mail` and `sendmail` transports, not in SMTP. | ||
* @var boolean | ||
*/ | ||
public $SingleTo = false; | ||
|
@@ -446,6 +447,15 @@ class PHPMailer | |
*/ | ||
public $XMailer = ''; | ||
|
||
/** | ||
* 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'; | ||
|
||
/** | ||
* An instance of the SMTP sender class. | ||
* @var SMTP | ||
|
@@ -634,9 +644,11 @@ class PHPMailer | |
* Constructor. | ||
* @param boolean $exceptions Should we throw external exceptions? | ||
*/ | ||
public function __construct($exceptions = false) | ||
public function __construct($exceptions = null) | ||
{ | ||
$this->exceptions = (boolean)$exceptions; | ||
if ($exceptions !== null) { | ||
$this->exceptions = (boolean)$exceptions; | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -645,9 +657,7 @@ public function __construct($exceptions = false) | |
public function __destruct() | ||
{ | ||
//Close any open SMTP connection nicely | ||
if ($this->Mailer == 'smtp') { | ||
$this->smtpClose(); | ||
} | ||
$this->smtpClose(); | ||
} | ||
|
||
/** | ||
|
@@ -713,7 +723,7 @@ protected function edebug($str) | |
case 'echo': | ||
default: | ||
//Normalize line breaks | ||
$str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); | ||
$str = preg_replace('/\r\n?/ms', "\n", $str); | ||
echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( | ||
"\n", | ||
"\n \t ", | ||
|
@@ -850,7 +860,7 @@ protected function addOrEnqueueAnAddress($kind, $address, $name) | |
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim | ||
if (($pos = strrpos($address, '@')) === false) { | ||
// At-sign is misssing. | ||
$error_message = $this->lang('invalid_address') . $address; | ||
$error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; | ||
$this->setError($error_message); | ||
$this->edebug($error_message); | ||
if ($this->exceptions) { | ||
|
@@ -900,7 +910,7 @@ protected function addAnAddress($kind, $address, $name = '') | |
return false; | ||
} | ||
if (!$this->validateAddress($address)) { | ||
$error_message = $this->lang('invalid_address') . $address; | ||
$error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; | ||
$this->setError($error_message); | ||
$this->edebug($error_message); | ||
if ($this->exceptions) { | ||
|
@@ -994,7 +1004,7 @@ public function setFrom($address, $name = '', $auto = true) | |
if (($pos = strrpos($address, '@')) === false or | ||
(!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and | ||
!$this->validateAddress($address)) { | ||
$error_message = $this->lang('invalid_address') . $address; | ||
$error_message = $this->lang('invalid_address') . " (setFrom) $address"; | ||
$this->setError($error_message); | ||
$this->edebug($error_message); | ||
if ($this->exceptions) { | ||
|
@@ -1027,19 +1037,30 @@ public function getLastMessageID() | |
/** | ||
* Check that a string looks like an email address. | ||
* @param string $address The email address to check | ||
* @param string $patternselect A selector for the validation pattern to use : | ||
* @param string|callable $patternselect A selector for the validation pattern to use : | ||
* * `auto` Pick best pattern automatically; | ||
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; | ||
* * `pcre` Use old PCRE implementation; | ||
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; | ||
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. | ||
* * `noregex` Don't use a regex: super fast, really dumb. | ||
* Alternatively you may pass in a callable to inject your own validator, for example: | ||
* PHPMailer::validateAddress('[email protected]', 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. | ||
* @return boolean | ||
* @static | ||
* @access public | ||
*/ | ||
public static function validateAddress($address, $patternselect = 'auto') | ||
public static function validateAddress($address, $patternselect = null) | ||
{ | ||
if (is_null($patternselect)) { | ||
$patternselect = self::$validator; | ||
} | ||
if (is_callable($patternselect)) { | ||
return call_user_func($patternselect, $address); | ||
} | ||
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 | ||
if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { | ||
return false; | ||
|
@@ -1216,7 +1237,7 @@ public function preSend() | |
} | ||
$this->$address_kind = $this->punyencodeAddress($this->$address_kind); | ||
if (!$this->validateAddress($this->$address_kind)) { | ||
$error_message = $this->lang('invalid_address') . $this->$address_kind; | ||
$error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind; | ||
$this->setError($error_message); | ||
$this->edebug($error_message); | ||
if ($this->exceptions) { | ||
|
@@ -1227,7 +1248,7 @@ public function preSend() | |
} | ||
|
||
// Set whether the message is multipart/alternative | ||
if (!empty($this->AltBody)) { | ||
if ($this->alternativeExists()) { | ||
$this->ContentType = 'multipart/alternative'; | ||
} | ||
|
||
|
@@ -1634,7 +1655,7 @@ public function smtpConnect($options = array()) | |
*/ | ||
public function smtpClose() | ||
{ | ||
if ($this->smtp !== null) { | ||
if (is_a($this->smtp, 'SMTP')) { | ||
if ($this->smtp->connected()) { | ||
$this->smtp->quit(); | ||
$this->smtp->close(); | ||
|
@@ -1972,7 +1993,7 @@ public function createHeader() | |
$result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject))); | ||
} | ||
|
||
if ($this->MessageID != '') { | ||
if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) { | ||
$this->lastMessageID = $this->MessageID; | ||
} else { | ||
$this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname()); | ||
|
@@ -2074,7 +2095,7 @@ public function getMailMIME() | |
*/ | ||
public function getSentMIMEMessage() | ||
{ | ||
return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; | ||
return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody; | ||
} | ||
|
||
/** | ||
|
@@ -2120,8 +2141,9 @@ public function createBody() | |
$altBodyEncoding = '7bit'; | ||
$altBodyCharSet = 'us-ascii'; | ||
} | ||
//If lines are too long, change to quoted-printable transfer encoding | ||
if (self::hasLineLongerThanMax($this->AltBody)) { | ||
//If lines are too long, and we're not already using an encoding that will shorten them, | ||
//change to quoted-printable transfer encoding | ||
if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) { | ||
$altBodyEncoding = 'quoted-printable'; | ||
} | ||
//Use this as a preamble in all multipart message types | ||
|
@@ -3296,7 +3318,7 @@ public function msgHTML($message, $basedir = '', $advanced = false) | |
$message | ||
); | ||
} | ||
} elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) { | ||
} elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) { | ||
// Do not change urls for absolute images (thanks to corvuscorax) | ||
// Do not change urls that are already inline images | ||
$filename = basename($url); | ||
|
@@ -3332,7 +3354,7 @@ public function msgHTML($message, $basedir = '', $advanced = false) | |
// Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better | ||
$this->Body = $this->normalizeBreaks($message); | ||
$this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); | ||
if (empty($this->AltBody)) { | ||
if (!$this->alternativeExists()) { | ||
$this->AltBody = 'To view this email message, open it in a program that understands HTML!' . | ||
self::CRLF . self::CRLF; | ||
} | ||
|
@@ -3657,11 +3679,13 @@ public function DKIM_Sign($signHeader) | |
if ($this->DKIM_passphrase != '') { | ||
$privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); | ||
} else { | ||
$privKey = $privKeyStr; | ||
$privKey = openssl_pkey_get_private($privKeyStr); | ||
} | ||
if (openssl_sign($signHeader, $signature, $privKey)) { | ||
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { //sha1WithRSAEncryption | ||
openssl_pkey_free($privKey); | ||
return base64_encode($signature); | ||
} | ||
openssl_pkey_free($privKey); | ||
return ''; | ||
} | ||
|
||
|
@@ -3678,7 +3702,7 @@ public function DKIM_HeaderC($signHeader) | |
foreach ($lines as $key => $line) { | ||
list($heading, $value) = explode(':', $line, 2); | ||
$heading = strtolower($heading); | ||
$value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces | ||
$value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces | ||
$lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value | ||
} | ||
$signHeader = implode("\r\n", $lines); | ||
|
@@ -3716,14 +3740,15 @@ public function DKIM_BodyC($body) | |
*/ | ||
public function DKIM_Add($headers_line, $subject, $body) | ||
{ | ||
$DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms | ||
$DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms | ||
$DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body | ||
$DKIMquery = 'dns/txt'; // Query method | ||
$DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) | ||
$subject_header = "Subject: $subject"; | ||
$headers = explode($this->LE, $headers_line); | ||
$from_header = ''; | ||
$to_header = ''; | ||
$date_header = ''; | ||
$current = ''; | ||
foreach ($headers as $header) { | ||
if (strpos($header, 'From:') === 0) { | ||
|
@@ -3732,6 +3757,9 @@ public function DKIM_Add($headers_line, $subject, $body) | |
} elseif (strpos($header, 'To:') === 0) { | ||
$to_header = $header; | ||
$current = 'to_header'; | ||
} elseif (strpos($header, 'Date:') === 0) { | ||
$date_header = $header; | ||
$current = 'date_header'; | ||
} else { | ||
if (!empty($$current) && strpos($header, ' =?') === 0) { | ||
$$current .= $header; | ||
|
@@ -3742,14 +3770,15 @@ public function DKIM_Add($headers_line, $subject, $body) | |
} | ||
$from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); | ||
$to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); | ||
$date = str_replace('|', '=7C', $this->DKIM_QP($date_header)); | ||
$subject = str_replace( | ||
'|', | ||
'=7C', | ||
$this->DKIM_QP($subject_header) | ||
); // Copied header fields (dkim-quoted-printable) | ||
$body = $this->DKIM_BodyC($body); | ||
$DKIMlen = strlen($body); // Length of body | ||
$DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body | ||
$DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body | ||
if ('' == $this->DKIM_identity) { | ||
$ident = ''; | ||
} else { | ||
|
@@ -3762,16 +3791,18 @@ public function DKIM_Add($headers_line, $subject, $body) | |
$this->DKIM_selector . | ||
";\r\n" . | ||
"\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . | ||
"\th=From:To:Subject;\r\n" . | ||
"\th=From:To:Date:Subject;\r\n" . | ||
"\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . | ||
"\tz=$from\r\n" . | ||
"\t|$to\r\n" . | ||
"\t|$date\r\n" . | ||
"\t|$subject;\r\n" . | ||
"\tbh=" . $DKIMb64 . ";\r\n" . | ||
"\tb="; | ||
$toSign = $this->DKIM_HeaderC( | ||
$from_header . "\r\n" . | ||
$to_header . "\r\n" . | ||
$date_header . "\r\n" . | ||
$subject_header . "\r\n" . | ||
$dkimhdrs | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters