|
|
@@ -30,6 +30,22 @@ namespace PHPMailer\PHPMailer;
|
|
|
*/
|
|
|
class PHPMailer
|
|
|
{
|
|
|
+ const CHARSET_ISO88591 = 'iso-8859-1';
|
|
|
+ const CHARSET_UTF8 = 'utf-8';
|
|
|
+
|
|
|
+ const CONTENT_TYPE_PLAINTEXT = 'text/plain';
|
|
|
+ const CONTENT_TYPE_TEXT_CALENDAR = 'text/calendar';
|
|
|
+ const CONTENT_TYPE_TEXT_HTML = 'text/html';
|
|
|
+ const CONTENT_TYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative';
|
|
|
+ const CONTENT_TYPE_MULTIPART_MIXED = 'multipart/mixed';
|
|
|
+ const CONTENT_TYPE_MULTIPART_RELATED = 'multipart/related';
|
|
|
+
|
|
|
+ const ENCODING_7BIT = '7bit';
|
|
|
+ const ENCODING_8BIT = '8bit';
|
|
|
+ const ENCODING_BASE64 = 'base64';
|
|
|
+ const ENCODING_BINARY = 'binary';
|
|
|
+ const ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
|
|
|
+
|
|
|
/**
|
|
|
* Email priority.
|
|
|
* Options: null (default), 1 = High, 3 = Normal, 5 = low.
|
|
|
@@ -44,14 +60,14 @@ class PHPMailer
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- public $CharSet = 'iso-8859-1';
|
|
|
+ public $CharSet = self::CHARSET_ISO88591;
|
|
|
|
|
|
/**
|
|
|
* The MIME Content-type of the message.
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- public $ContentType = 'text/plain';
|
|
|
+ public $ContentType = self::CONTENT_TYPE_PLAINTEXT;
|
|
|
|
|
|
/**
|
|
|
* The message encoding.
|
|
|
@@ -59,7 +75,7 @@ class PHPMailer
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- public $Encoding = '8bit';
|
|
|
+ public $Encoding = self::ENCODING_8BIT;
|
|
|
|
|
|
/**
|
|
|
* Holds the most recent mailer error message.
|
|
|
@@ -441,6 +457,22 @@ class PHPMailer
|
|
|
*/
|
|
|
public $DKIM_domain = '';
|
|
|
|
|
|
+ /**
|
|
|
+ * DKIM Copy header field values for diagnostic use.
|
|
|
+ *
|
|
|
+ * @var bool
|
|
|
+ */
|
|
|
+ public $DKIM_copyHeaderFields = true;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * DKIM Extra signing headers.
|
|
|
+ *
|
|
|
+ * @example ['List-Unsubscribe', 'List-Help']
|
|
|
+ *
|
|
|
+ * @var array
|
|
|
+ */
|
|
|
+ public $DKIM_extraHeaders = [];
|
|
|
+
|
|
|
/**
|
|
|
* DKIM private key file path.
|
|
|
*
|
|
|
@@ -669,7 +701,7 @@ class PHPMailer
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- const VERSION = '6.0.5';
|
|
|
+ const VERSION = '6.0.7';
|
|
|
|
|
|
/**
|
|
|
* Error severity: message only, continue processing.
|
|
|
@@ -837,9 +869,9 @@ class PHPMailer
|
|
|
public function isHTML($isHtml = true)
|
|
|
{
|
|
|
if ($isHtml) {
|
|
|
- $this->ContentType = 'text/html';
|
|
|
+ $this->ContentType = static::CONTENT_TYPE_TEXT_HTML;
|
|
|
} else {
|
|
|
- $this->ContentType = 'text/plain';
|
|
|
+ $this->ContentType = static::CONTENT_TYPE_PLAINTEXT;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1402,7 +1434,7 @@ class PHPMailer
|
|
|
|
|
|
// Set whether the message is multipart/alternative
|
|
|
if ($this->alternativeExists()) {
|
|
|
- $this->ContentType = 'multipart/alternative';
|
|
|
+ $this->ContentType = static::CONTENT_TYPE_MULTIPART_ALTERNATIVE;
|
|
|
}
|
|
|
|
|
|
$this->setMessageType();
|
|
|
@@ -1439,7 +1471,10 @@ class PHPMailer
|
|
|
if (!empty($this->DKIM_domain)
|
|
|
and !empty($this->DKIM_selector)
|
|
|
and (!empty($this->DKIM_private_string)
|
|
|
- or (!empty($this->DKIM_private) and file_exists($this->DKIM_private))
|
|
|
+ or (!empty($this->DKIM_private)
|
|
|
+ and static::isPermittedPath($this->DKIM_private)
|
|
|
+ and file_exists($this->DKIM_private)
|
|
|
+ )
|
|
|
)
|
|
|
) {
|
|
|
$header_dkim = $this->DKIM_Add(
|
|
|
@@ -1616,6 +1651,20 @@ class PHPMailer
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Check whether a file path is of a permitted type.
|
|
|
+ * Used to reject URLs and phar files from functions that access local file paths,
|
|
|
+ * such as addAttachment.
|
|
|
+ *
|
|
|
+ * @param string $path A relative or absolute path to a file
|
|
|
+ *
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ protected static function isPermittedPath($path)
|
|
|
+ {
|
|
|
+ return !preg_match('#^[a-z]+://#i', $path);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Send mail using the PHP mail() function.
|
|
|
*
|
|
|
@@ -1963,7 +2012,8 @@ class PHPMailer
|
|
|
'dk' => 'da',
|
|
|
'no' => 'nb',
|
|
|
'se' => 'sv',
|
|
|
- 'sr' => 'rs',
|
|
|
+ 'rs' => 'sr',
|
|
|
+ 'tg' => 'tl',
|
|
|
];
|
|
|
|
|
|
if (isset($renamed_langcodes[$langcode])) {
|
|
|
@@ -2005,7 +2055,7 @@ class PHPMailer
|
|
|
// There is no English translation file
|
|
|
if ('en' != $langcode) {
|
|
|
// Make sure language file path is readable
|
|
|
- if (!file_exists($lang_file)) {
|
|
|
+ if (!static::isPermittedPath($lang_file) || !file_exists($lang_file)) {
|
|
|
$foundlang = false;
|
|
|
} else {
|
|
|
// Overwrite language-specific strings.
|
|
|
@@ -2089,7 +2139,7 @@ class PHPMailer
|
|
|
}
|
|
|
// If utf-8 encoding is used, we will need to make sure we don't
|
|
|
// split multibyte characters when we wrap
|
|
|
- $is_utf8 = 'utf-8' == strtolower($this->CharSet);
|
|
|
+ $is_utf8 = static::CHARSET_UTF8 === strtolower($this->CharSet);
|
|
|
$lelen = strlen(static::$LE);
|
|
|
$crlflen = strlen(static::$LE);
|
|
|
|
|
|
@@ -2349,19 +2399,19 @@ class PHPMailer
|
|
|
$ismultipart = true;
|
|
|
switch ($this->message_type) {
|
|
|
case 'inline':
|
|
|
- $result .= $this->headerLine('Content-Type', 'multipart/related;');
|
|
|
+ $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
|
|
|
$result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
|
|
|
break;
|
|
|
case 'attach':
|
|
|
case 'inline_attach':
|
|
|
case 'alt_attach':
|
|
|
case 'alt_inline_attach':
|
|
|
- $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
|
|
|
+ $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_MIXED . ';');
|
|
|
$result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
|
|
|
break;
|
|
|
case 'alt':
|
|
|
case 'alt_inline':
|
|
|
- $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
|
|
|
+ $result .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
|
|
|
$result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
|
|
|
break;
|
|
|
default:
|
|
|
@@ -2371,11 +2421,11 @@ class PHPMailer
|
|
|
break;
|
|
|
}
|
|
|
// RFC1341 part 5 says 7bit is assumed if not specified
|
|
|
- if ('7bit' != $this->Encoding) {
|
|
|
+ if (static::ENCODING_7BIT != $this->Encoding) {
|
|
|
// RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
|
|
|
if ($ismultipart) {
|
|
|
- if ('8bit' == $this->Encoding) {
|
|
|
- $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
|
|
|
+ if (static::ENCODING_8BIT == $this->Encoding) {
|
|
|
+ $result .= $this->headerLine('Content-Transfer-Encoding', static::ENCODING_8BIT);
|
|
|
}
|
|
|
// The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
|
|
|
} else {
|
|
|
@@ -2451,29 +2501,29 @@ class PHPMailer
|
|
|
$bodyEncoding = $this->Encoding;
|
|
|
$bodyCharSet = $this->CharSet;
|
|
|
//Can we do a 7-bit downgrade?
|
|
|
- if ('8bit' == $bodyEncoding and !$this->has8bitChars($this->Body)) {
|
|
|
- $bodyEncoding = '7bit';
|
|
|
+ if (static::ENCODING_8BIT == $bodyEncoding and !$this->has8bitChars($this->Body)) {
|
|
|
+ $bodyEncoding = static::ENCODING_7BIT;
|
|
|
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
|
|
|
$bodyCharSet = 'us-ascii';
|
|
|
}
|
|
|
//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 static::hasLineLongerThanMax($this->Body)) {
|
|
|
- $bodyEncoding = 'quoted-printable';
|
|
|
+ if (static::ENCODING_BASE64 != $this->Encoding and static::hasLineLongerThanMax($this->Body)) {
|
|
|
+ $bodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
|
|
|
}
|
|
|
|
|
|
$altBodyEncoding = $this->Encoding;
|
|
|
$altBodyCharSet = $this->CharSet;
|
|
|
//Can we do a 7-bit downgrade?
|
|
|
- if ('8bit' == $altBodyEncoding and !$this->has8bitChars($this->AltBody)) {
|
|
|
- $altBodyEncoding = '7bit';
|
|
|
+ if (static::ENCODING_8BIT == $altBodyEncoding and !$this->has8bitChars($this->AltBody)) {
|
|
|
+ $altBodyEncoding = static::ENCODING_7BIT;
|
|
|
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
|
|
|
$altBodyCharSet = 'us-ascii';
|
|
|
}
|
|
|
//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 static::hasLineLongerThanMax($this->AltBody)) {
|
|
|
- $altBodyEncoding = 'quoted-printable';
|
|
|
+ if (static::ENCODING_BASE64 != $altBodyEncoding and static::hasLineLongerThanMax($this->AltBody)) {
|
|
|
+ $altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
|
|
|
}
|
|
|
//Use this as a preamble in all multipart message types
|
|
|
$mimepre = 'This is a multi-part message in MIME format.' . static::$LE;
|
|
|
@@ -2495,7 +2545,7 @@ class PHPMailer
|
|
|
case 'inline_attach':
|
|
|
$body .= $mimepre;
|
|
|
$body .= $this->textLine('--' . $this->boundary[1]);
|
|
|
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
|
|
|
+ $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
|
|
|
$body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
|
|
|
$body .= static::$LE;
|
|
|
$body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
|
|
|
@@ -2507,14 +2557,14 @@ class PHPMailer
|
|
|
break;
|
|
|
case 'alt':
|
|
|
$body .= $mimepre;
|
|
|
- $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
|
|
|
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
|
|
|
$body .= $this->encodeString($this->Body, $bodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
if (!empty($this->Ical)) {
|
|
|
- $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
|
|
|
+ $body .= $this->getBoundary($this->boundary[1], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
|
|
|
$body .= $this->encodeString($this->Ical, $this->Encoding);
|
|
|
$body .= static::$LE;
|
|
|
}
|
|
|
@@ -2522,14 +2572,14 @@ class PHPMailer
|
|
|
break;
|
|
|
case 'alt_inline':
|
|
|
$body .= $mimepre;
|
|
|
- $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
|
|
|
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
$body .= $this->textLine('--' . $this->boundary[1]);
|
|
|
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
|
|
|
+ $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
|
|
|
$body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
|
|
|
$body .= $this->encodeString($this->Body, $bodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
$body .= $this->attachAll('inline', $this->boundary[2]);
|
|
|
@@ -2539,17 +2589,17 @@ class PHPMailer
|
|
|
case 'alt_attach':
|
|
|
$body .= $mimepre;
|
|
|
$body .= $this->textLine('--' . $this->boundary[1]);
|
|
|
- $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
|
|
|
+ $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
|
|
|
$body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
|
|
|
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
|
|
|
$body .= $this->encodeString($this->Body, $bodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
if (!empty($this->Ical)) {
|
|
|
- $body .= $this->getBoundary($this->boundary[2], '', 'text/calendar; method=REQUEST', '');
|
|
|
+ $body .= $this->getBoundary($this->boundary[2], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
|
|
|
$body .= $this->encodeString($this->Ical, $this->Encoding);
|
|
|
}
|
|
|
$body .= $this->endBoundary($this->boundary[2]);
|
|
|
@@ -2559,17 +2609,17 @@ class PHPMailer
|
|
|
case 'alt_inline_attach':
|
|
|
$body .= $mimepre;
|
|
|
$body .= $this->textLine('--' . $this->boundary[1]);
|
|
|
- $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
|
|
|
+ $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_ALTERNATIVE . ';');
|
|
|
$body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, static::CONTENT_TYPE_PLAINTEXT, $altBodyEncoding);
|
|
|
$body .= $this->encodeString($this->AltBody, $altBodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
$body .= $this->textLine('--' . $this->boundary[2]);
|
|
|
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
|
|
|
+ $body .= $this->headerLine('Content-Type', static::CONTENT_TYPE_MULTIPART_RELATED . ';');
|
|
|
$body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
|
|
|
$body .= static::$LE;
|
|
|
- $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
|
|
|
+ $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, static::CONTENT_TYPE_TEXT_HTML, $bodyEncoding);
|
|
|
$body .= $this->encodeString($this->Body, $bodyEncoding);
|
|
|
$body .= static::$LE;
|
|
|
$body .= $this->attachAll('inline', $this->boundary[3]);
|
|
|
@@ -2671,7 +2721,7 @@ class PHPMailer
|
|
|
$result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
|
|
|
$result .= static::$LE;
|
|
|
// RFC1341 part 5 says 7bit is assumed if not specified
|
|
|
- if ('7bit' != $encoding) {
|
|
|
+ if (static::ENCODING_7BIT != $encoding) {
|
|
|
$result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
|
|
|
}
|
|
|
$result .= static::$LE;
|
|
|
@@ -2743,6 +2793,8 @@ class PHPMailer
|
|
|
* Add an attachment from a path on the filesystem.
|
|
|
* Never use a user-supplied path to a file!
|
|
|
* Returns false if the file could not be found or read.
|
|
|
+ * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client.
|
|
|
+ * If you need to do that, fetch the resource yourself and pass it in via a local file or string.
|
|
|
*
|
|
|
* @param string $path Path to the attachment
|
|
|
* @param string $name Overrides the attachment name
|
|
|
@@ -2754,10 +2806,10 @@ class PHPMailer
|
|
|
*
|
|
|
* @return bool
|
|
|
*/
|
|
|
- public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
|
|
|
+ public function addAttachment($path, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'attachment')
|
|
|
{
|
|
|
try {
|
|
|
- if (!@is_file($path)) {
|
|
|
+ if (!static::isPermittedPath($path) || !@is_file($path)) {
|
|
|
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
|
|
|
}
|
|
|
|
|
|
@@ -2866,7 +2918,7 @@ class PHPMailer
|
|
|
);
|
|
|
}
|
|
|
// RFC1341 part 5 says 7bit is assumed if not specified
|
|
|
- if ('7bit' != $encoding) {
|
|
|
+ if (static::ENCODING_7BIT != $encoding) {
|
|
|
$mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, static::$LE);
|
|
|
}
|
|
|
|
|
|
@@ -2936,10 +2988,10 @@ class PHPMailer
|
|
|
*
|
|
|
* @return string
|
|
|
*/
|
|
|
- protected function encodeFile($path, $encoding = 'base64')
|
|
|
+ protected function encodeFile($path, $encoding = self::ENCODING_BASE64)
|
|
|
{
|
|
|
try {
|
|
|
- if (!file_exists($path)) {
|
|
|
+ if (!static::isPermittedPath($path) || !file_exists($path)) {
|
|
|
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
|
|
|
}
|
|
|
$file_buffer = file_get_contents($path);
|
|
|
@@ -2961,33 +3013,33 @@ class PHPMailer
|
|
|
* Returns an empty string on failure.
|
|
|
*
|
|
|
* @param string $str The text to encode
|
|
|
- * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable
|
|
|
+ * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
|
|
|
*
|
|
|
* @return string
|
|
|
*/
|
|
|
- public function encodeString($str, $encoding = 'base64')
|
|
|
+ public function encodeString($str, $encoding = self::ENCODING_BASE64)
|
|
|
{
|
|
|
$encoded = '';
|
|
|
switch (strtolower($encoding)) {
|
|
|
- case 'base64':
|
|
|
+ case static::ENCODING_BASE64:
|
|
|
$encoded = chunk_split(
|
|
|
base64_encode($str),
|
|
|
static::STD_LINE_LENGTH,
|
|
|
static::$LE
|
|
|
);
|
|
|
break;
|
|
|
- case '7bit':
|
|
|
- case '8bit':
|
|
|
+ case static::ENCODING_7BIT:
|
|
|
+ case static::ENCODING_8BIT:
|
|
|
$encoded = static::normalizeBreaks($str);
|
|
|
// Make sure it ends with a line break
|
|
|
if (substr($encoded, -(strlen(static::$LE))) != static::$LE) {
|
|
|
$encoded .= static::$LE;
|
|
|
}
|
|
|
break;
|
|
|
- case 'binary':
|
|
|
+ case static::ENCODING_BINARY:
|
|
|
$encoded = $str;
|
|
|
break;
|
|
|
- case 'quoted-printable':
|
|
|
+ case static::ENCODING_QUOTED_PRINTABLE:
|
|
|
$encoded = $this->encodeQP($str);
|
|
|
break;
|
|
|
default:
|
|
|
@@ -3238,7 +3290,7 @@ class PHPMailer
|
|
|
public function addStringAttachment(
|
|
|
$string,
|
|
|
$filename,
|
|
|
- $encoding = 'base64',
|
|
|
+ $encoding = self::ENCODING_BASE64,
|
|
|
$type = '',
|
|
|
$disposition = 'attachment'
|
|
|
) {
|
|
|
@@ -3278,9 +3330,9 @@ class PHPMailer
|
|
|
*
|
|
|
* @return bool True on successfully adding an attachment
|
|
|
*/
|
|
|
- public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
|
|
|
+ public function addEmbeddedImage($path, $cid, $name = '', $encoding = self::ENCODING_BASE64, $type = '', $disposition = 'inline')
|
|
|
{
|
|
|
- if (!@is_file($path)) {
|
|
|
+ if (!static::isPermittedPath($path) || !@is_file($path)) {
|
|
|
$this->setError($this->lang('file_access') . $path);
|
|
|
|
|
|
return false;
|
|
|
@@ -3332,7 +3384,7 @@ class PHPMailer
|
|
|
$string,
|
|
|
$cid,
|
|
|
$name = '',
|
|
|
- $encoding = 'base64',
|
|
|
+ $encoding = self::ENCODING_BASE64,
|
|
|
$type = '',
|
|
|
$disposition = 'inline'
|
|
|
) {
|
|
|
@@ -3596,7 +3648,7 @@ class PHPMailer
|
|
|
//Is it a valid IPv4 address?
|
|
|
return (bool) filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
|
|
|
}
|
|
|
- if (filter_var('http://' . $host, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) {
|
|
|
+ if (filter_var('http://' . $host, FILTER_VALIDATE_URL)) {
|
|
|
//Is it a syntactically valid hostname?
|
|
|
return true;
|
|
|
}
|
|
|
@@ -3700,7 +3752,7 @@ class PHPMailer
|
|
|
// Convert data URIs into embedded images
|
|
|
//e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
|
|
|
if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
|
|
|
- if (count($match) == 4 and 'base64' == $match[2]) {
|
|
|
+ if (count($match) == 4 and static::ENCODING_BASE64 == $match[2]) {
|
|
|
$data = base64_decode($match[3]);
|
|
|
} elseif ('' == $match[2]) {
|
|
|
$data = rawurldecode($match[3]);
|
|
|
@@ -3713,7 +3765,7 @@ class PHPMailer
|
|
|
$cid = hash('sha256', $data) . '@phpmailer.0'; // RFC2392 S 2
|
|
|
|
|
|
if (!$this->cidExists($cid)) {
|
|
|
- $this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1]);
|
|
|
+ $this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, static::ENCODING_BASE64, $match[1]);
|
|
|
}
|
|
|
$message = str_replace(
|
|
|
$images[0][$imgindex],
|
|
|
@@ -3747,7 +3799,7 @@ class PHPMailer
|
|
|
$basedir . $directory . $filename,
|
|
|
$cid,
|
|
|
$filename,
|
|
|
- 'base64',
|
|
|
+ static::ENCODING_BASE64,
|
|
|
static::_mime_types((string) static::mb_pathinfo($filename, PATHINFO_EXTENSION))
|
|
|
)
|
|
|
) {
|
|
|
@@ -4250,6 +4302,11 @@ class PHPMailer
|
|
|
$to_header = '';
|
|
|
$date_header = '';
|
|
|
$current = '';
|
|
|
+ $copiedHeaderFields = '';
|
|
|
+ $foundExtraHeaders = [];
|
|
|
+ $extraHeaderKeys = '';
|
|
|
+ $extraHeaderValues = '';
|
|
|
+ $extraCopyHeaderFields = '';
|
|
|
foreach ($headers as $header) {
|
|
|
if (strpos($header, 'From:') === 0) {
|
|
|
$from_header = $header;
|
|
|
@@ -4260,6 +4317,23 @@ class PHPMailer
|
|
|
} elseif (strpos($header, 'Date:') === 0) {
|
|
|
$date_header = $header;
|
|
|
$current = 'date_header';
|
|
|
+ } elseif (!empty($this->DKIM_extraHeaders)) {
|
|
|
+ foreach ($this->DKIM_extraHeaders as $extraHeader) {
|
|
|
+ if (strpos($header, $extraHeader . ':') === 0) {
|
|
|
+ $headerValue = $header;
|
|
|
+ foreach ($this->CustomHeader as $customHeader) {
|
|
|
+ if ($customHeader[0] === $extraHeader) {
|
|
|
+ $headerValue = trim($customHeader[0]) .
|
|
|
+ ': ' .
|
|
|
+ $this->encodeHeader(trim($customHeader[1]));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $foundExtraHeaders[$extraHeader] = $headerValue;
|
|
|
+ $current = '';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
} else {
|
|
|
if (!empty($$current) and strpos($header, ' =?') === 0) {
|
|
|
$$current .= $header;
|
|
|
@@ -4268,14 +4342,24 @@ class PHPMailer
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- $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)
|
|
|
+ foreach ($foundExtraHeaders as $key => $value) {
|
|
|
+ $extraHeaderKeys .= ':' . $key;
|
|
|
+ $extraHeaderValues .= $value . "\r\n";
|
|
|
+ if ($this->DKIM_copyHeaderFields) {
|
|
|
+ $extraCopyHeaderFields .= "\t|" . str_replace('|', '=7C', $this->DKIM_QP($value)) . ";\r\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($this->DKIM_copyHeaderFields) {
|
|
|
+ $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));
|
|
|
+ $copiedHeaderFields = "\tz=$from\r\n" .
|
|
|
+ "\t|$to\r\n" .
|
|
|
+ "\t|$date\r\n" .
|
|
|
+ "\t|$subject;\r\n" .
|
|
|
+ $extraCopyHeaderFields;
|
|
|
+ }
|
|
|
$body = $this->DKIM_BodyC($body);
|
|
|
$DKIMlen = strlen($body); // Length of body
|
|
|
$DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
|
|
|
@@ -4291,12 +4375,9 @@ class PHPMailer
|
|
|
$this->DKIM_selector .
|
|
|
";\r\n" .
|
|
|
"\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
|
|
|
- "\th=From:To:Date:Subject;\r\n" .
|
|
|
+ "\th=From:To:Date:Subject" . $extraHeaderKeys . ";\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" .
|
|
|
+ $copiedHeaderFields .
|
|
|
"\tbh=" . $DKIMb64 . ";\r\n" .
|
|
|
"\tb=";
|
|
|
$toSign = $this->DKIM_HeaderC(
|
|
|
@@ -4304,6 +4385,7 @@ class PHPMailer
|
|
|
$to_header . "\r\n" .
|
|
|
$date_header . "\r\n" .
|
|
|
$subject_header . "\r\n" .
|
|
|
+ $extraHeaderValues .
|
|
|
$dkimhdrs
|
|
|
);
|
|
|
$signed = $this->DKIM_Sign($toSign);
|