|
|
|
|
@ -15,6 +15,7 @@
|
|
|
|
|
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
* @suppress PHP0417
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -657,7 +658,7 @@ class PHPMailer
|
|
|
|
|
public function __construct($exceptions = null)
|
|
|
|
|
{
|
|
|
|
|
if ($exceptions !== null) {
|
|
|
|
|
$this->exceptions = (boolean)$exceptions;
|
|
|
|
|
$this->exceptions = (boolean) $exceptions;
|
|
|
|
|
}
|
|
|
|
|
//Pick an appropriate debug output format automatically
|
|
|
|
|
$this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
|
|
|
|
|
@ -1015,9 +1016,11 @@ class PHPMailer
|
|
|
|
|
$address = trim($address);
|
|
|
|
|
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
|
|
|
|
|
// Don't validate now addresses with IDN. Will be done in send().
|
|
|
|
|
if (($pos = strrpos($address, '@')) === false or
|
|
|
|
|
if (
|
|
|
|
|
($pos = strrpos($address, '@')) === false or
|
|
|
|
|
(!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
|
|
|
|
|
!$this->validateAddress($address)) {
|
|
|
|
|
!$this->validateAddress($address)
|
|
|
|
|
) {
|
|
|
|
|
$error_message = $this->lang('invalid_address') . " (setFrom) $address";
|
|
|
|
|
$this->setError($error_message);
|
|
|
|
|
$this->edebug($error_message);
|
|
|
|
|
@ -1109,7 +1112,7 @@ class PHPMailer
|
|
|
|
|
* @copyright 2009-2010 Michael Rushton
|
|
|
|
|
* Feel free to use and redistribute this code. But please keep this copyright notice.
|
|
|
|
|
*/
|
|
|
|
|
return (boolean)preg_match(
|
|
|
|
|
return (boolean) preg_match(
|
|
|
|
|
'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
|
|
|
|
|
'((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
|
|
|
|
|
'(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
|
|
|
|
|
@ -1123,7 +1126,7 @@ class PHPMailer
|
|
|
|
|
);
|
|
|
|
|
case 'pcre':
|
|
|
|
|
//An older regex that doesn't need a recent PCRE
|
|
|
|
|
return (boolean)preg_match(
|
|
|
|
|
return (boolean) preg_match(
|
|
|
|
|
'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
|
|
|
|
|
'[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
|
|
|
|
|
'(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
|
|
|
|
|
@ -1141,7 +1144,7 @@ class PHPMailer
|
|
|
|
|
* This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
|
|
|
|
|
* @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
|
|
|
|
|
*/
|
|
|
|
|
return (boolean)preg_match(
|
|
|
|
|
return (boolean) preg_match(
|
|
|
|
|
'/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
|
|
|
|
|
'[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
|
|
|
|
|
$address
|
|
|
|
|
@ -1154,7 +1157,7 @@ class PHPMailer
|
|
|
|
|
and strpos($address, '@') != strlen($address) - 1);
|
|
|
|
|
case 'php':
|
|
|
|
|
default:
|
|
|
|
|
return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
|
|
|
|
|
return (boolean) filter_var($address, FILTER_VALIDATE_EMAIL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1183,16 +1186,20 @@ class PHPMailer
|
|
|
|
|
public function punyencodeAddress($address)
|
|
|
|
|
{
|
|
|
|
|
// Verify we have required functions, CharSet, and at-sign.
|
|
|
|
|
if ($this->idnSupported() and
|
|
|
|
|
if (
|
|
|
|
|
$this->idnSupported() and
|
|
|
|
|
!empty($this->CharSet) and
|
|
|
|
|
($pos = strrpos($address, '@')) !== false) {
|
|
|
|
|
($pos = strrpos($address, '@')) !== false
|
|
|
|
|
) {
|
|
|
|
|
$domain = substr($address, ++$pos);
|
|
|
|
|
// Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
|
|
|
|
|
if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
|
|
|
|
|
$domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
|
|
|
|
|
if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
|
|
|
|
|
if (
|
|
|
|
|
($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
|
|
|
|
|
idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) :
|
|
|
|
|
idn_to_ascii($domain)) !== false) {
|
|
|
|
|
idn_to_ascii($domain)) !== false
|
|
|
|
|
) {
|
|
|
|
|
return substr($address, 0, $pos) . $punycode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1295,7 +1302,8 @@ class PHPMailer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sign with DKIM if enabled
|
|
|
|
|
if (!empty($this->DKIM_domain)
|
|
|
|
|
if (
|
|
|
|
|
!empty($this->DKIM_domain)
|
|
|
|
|
and !empty($this->DKIM_selector)
|
|
|
|
|
and (!empty($this->DKIM_private_string)
|
|
|
|
|
or (!empty($this->DKIM_private)
|
|
|
|
|
@ -1341,7 +1349,7 @@ class PHPMailer
|
|
|
|
|
case 'mail':
|
|
|
|
|
return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
|
|
|
|
|
default:
|
|
|
|
|
$sendMethod = $this->Mailer.'Send';
|
|
|
|
|
$sendMethod = $this->Mailer . 'Send';
|
|
|
|
|
if (method_exists($this, $sendMethod)) {
|
|
|
|
|
return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
|
|
|
|
|
}
|
|
|
|
|
@ -1444,7 +1452,8 @@ class PHPMailer
|
|
|
|
|
protected static function isShellSafe($string)
|
|
|
|
|
{
|
|
|
|
|
// Future-proof
|
|
|
|
|
if (escapeshellcmd($string) !== $string
|
|
|
|
|
if (
|
|
|
|
|
escapeshellcmd($string) !== $string
|
|
|
|
|
or !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
@ -1639,11 +1648,13 @@ class PHPMailer
|
|
|
|
|
|
|
|
|
|
foreach ($hosts as $hostentry) {
|
|
|
|
|
$hostinfo = array();
|
|
|
|
|
if (!preg_match(
|
|
|
|
|
if (
|
|
|
|
|
!preg_match(
|
|
|
|
|
'/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*|\[[a-fA-F0-9:]+\]):?([0-9]*)$/',
|
|
|
|
|
trim($hostentry),
|
|
|
|
|
$hostinfo
|
|
|
|
|
)) {
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
// Not a valid host entry
|
|
|
|
|
$this->edebug('Ignoring invalid host: ' . $hostentry);
|
|
|
|
|
continue;
|
|
|
|
|
@ -1670,12 +1681,12 @@ class PHPMailer
|
|
|
|
|
if ('tls' === $secure or 'ssl' === $secure) {
|
|
|
|
|
//Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
|
|
|
|
|
if (!$sslext) {
|
|
|
|
|
throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
|
|
|
|
|
throw new phpmailerException($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$host = $hostinfo[3];
|
|
|
|
|
$port = $this->Port;
|
|
|
|
|
$tport = (integer)$hostinfo[4];
|
|
|
|
|
$tport = (integer) $hostinfo[4];
|
|
|
|
|
if ($tport > 0 and $tport < 65536) {
|
|
|
|
|
$port = $tport;
|
|
|
|
|
}
|
|
|
|
|
@ -1703,7 +1714,8 @@ class PHPMailer
|
|
|
|
|
$this->smtp->hello($hello);
|
|
|
|
|
}
|
|
|
|
|
if ($this->SMTPAuth) {
|
|
|
|
|
if (!$this->smtp->authenticate(
|
|
|
|
|
if (
|
|
|
|
|
!$this->smtp->authenticate(
|
|
|
|
|
$this->Username,
|
|
|
|
|
$this->Password,
|
|
|
|
|
$this->AuthType,
|
|
|
|
|
@ -1795,7 +1807,7 @@ class PHPMailer
|
|
|
|
|
);
|
|
|
|
|
if (empty($lang_path)) {
|
|
|
|
|
// Calculate an absolute path so it can work if CWD is not here
|
|
|
|
|
$lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
|
|
|
|
|
$lang_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
|
|
|
|
|
}
|
|
|
|
|
//Validate $langcode
|
|
|
|
|
if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
|
|
|
|
|
@ -1815,7 +1827,7 @@ class PHPMailer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->language = $PHPMAILER_LANG;
|
|
|
|
|
return (boolean)$foundlang; // Returns false if language not found
|
|
|
|
|
return (boolean) $foundlang; // Returns false if language not found
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -2074,7 +2086,8 @@ class PHPMailer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sendmail and mail() extract Bcc from the header before sending
|
|
|
|
|
if ((
|
|
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
$this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
|
|
|
|
|
)
|
|
|
|
|
and count($this->bcc) > 0
|
|
|
|
|
@ -2202,7 +2215,8 @@ class PHPMailer
|
|
|
|
|
* Create unique ID
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
protected function generateId() {
|
|
|
|
|
protected function generateId()
|
|
|
|
|
{
|
|
|
|
|
return md5(uniqid(time()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -2712,7 +2726,7 @@ class PHPMailer
|
|
|
|
|
throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
|
|
|
|
|
}
|
|
|
|
|
$magic_quotes = false;
|
|
|
|
|
if( version_compare(PHP_VERSION, '7.4.0', '<') ) {
|
|
|
|
|
if (version_compare(PHP_VERSION, '7.4.0', '<')) {
|
|
|
|
|
$magic_quotes = get_magic_quotes_runtime();
|
|
|
|
|
}
|
|
|
|
|
if ($magic_quotes) {
|
|
|
|
|
@ -2865,7 +2879,7 @@ class PHPMailer
|
|
|
|
|
*/
|
|
|
|
|
public function has8bitChars($text)
|
|
|
|
|
{
|
|
|
|
|
return (boolean)preg_match('/[\x80-\xFF]/', $text);
|
|
|
|
|
return (boolean) preg_match('/[\x80-\xFF]/', $text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -3273,7 +3287,7 @@ class PHPMailer
|
|
|
|
|
if (!empty($lasterror['error'])) {
|
|
|
|
|
$msg .= $this->lang('smtp_error') . $lasterror['error'];
|
|
|
|
|
if (!empty($lasterror['detail'])) {
|
|
|
|
|
$msg .= ' Detail: '. $lasterror['detail'];
|
|
|
|
|
$msg .= ' Detail: ' . $lasterror['detail'];
|
|
|
|
|
}
|
|
|
|
|
if (!empty($lasterror['smtp_code'])) {
|
|
|
|
|
$msg .= ' SMTP code: ' . $lasterror['smtp_code'];
|
|
|
|
|
@ -3465,12 +3479,13 @@ class PHPMailer
|
|
|
|
|
if (strlen($directory) > 1 && substr($directory, -1) != '/') {
|
|
|
|
|
$directory .= '/';
|
|
|
|
|
}
|
|
|
|
|
if ($this->addEmbeddedImage(
|
|
|
|
|
if (
|
|
|
|
|
$this->addEmbeddedImage(
|
|
|
|
|
$basedir . $directory . $filename,
|
|
|
|
|
$cid,
|
|
|
|
|
$filename,
|
|
|
|
|
'base64',
|
|
|
|
|
self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
|
|
|
|
|
self::_mime_types((string) self::mb_pathinfo($filename, PATHINFO_EXTENSION))
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
$message = preg_replace(
|
|
|
|
|
@ -3815,8 +3830,10 @@ class PHPMailer
|
|
|
|
|
}
|
|
|
|
|
//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 (
|
|
|
|
|
version_compare(PHP_VERSION, '5.3.0') >= 0 and
|
|
|
|
|
in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))
|
|
|
|
|
) {
|
|
|
|
|
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
|
|
|
|
|
if (PHP_MAJOR_VERSION < 8) {
|
|
|
|
|
openssl_pkey_free($privKey);
|
|
|
|
|
@ -3975,7 +3992,7 @@ class PHPMailer
|
|
|
|
|
public static function hasLineLongerThanMax($str)
|
|
|
|
|
{
|
|
|
|
|
//+2 to include CRLF line break for a 1000 total
|
|
|
|
|
return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str);
|
|
|
|
|
return (boolean) preg_match('/^(.{' . (self::MAX_LINE_LENGTH + 2) . ',})/m', $str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|