@@ -59,6 +59,7 @@ class PHPMailer
5959 const ICAL_METHOD_REFRESH = 'REFRESH ' ;
6060 const ICAL_METHOD_COUNTER = 'COUNTER ' ;
6161 const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER ' ;
62+ const RFC822_DATE_FORMAT = 'D, j M Y H:i:s O ' ;
6263
6364 /**
6465 * Email priority.
@@ -77,7 +78,7 @@ class PHPMailer
7778 public $ CharSet = self ::CHARSET_ISO88591 ;
7879
7980 /**
80- * The MIME Content-type of the message.
81+ * The MIME Content-Type of the message.
8182 *
8283 * @var string
8384 */
@@ -159,7 +160,7 @@ class PHPMailer
159160 public $ Ical = '' ;
160161
161162 /**
162- * Value-array of "method" in Contenttype header "text/calendar"
163+ * Value-array of "method" in Content-Type header "text/calendar"
163164 *
164165 * @var string[]
165166 */
@@ -768,7 +769,7 @@ class PHPMailer
768769 *
769770 * @var string
770771 */
771- const VERSION = '7.0.2 ' ;
772+ const VERSION = '7.1.1 ' ;
772773
773774 /**
774775 * Error severity: message only, continue processing.
@@ -1283,26 +1284,27 @@ protected function addAnAddress($kind, $address, $name = '')
12831284 /**
12841285 * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
12851286 * of the form "display name <address>" into an array of name/address pairs.
1286- * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
1287+ * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available and
1288+ * the deprecated $useimap argument is truthy.
12871289 * Note that quotes in the name part are removed.
12881290 *
12891291 * @see https://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
12901292 *
12911293 * @param string $addrstr The address list string
1292- * @param null $useimap Unused. Argument has been deprecated in PHPMailer 6.11.0.
1293- * Previously this argument determined whether to use
1294- * the IMAP extension to parse the list and accepted a boolean value .
1294+ * @param bool| null $useimap Deprecated in PHPMailer 6.11.0.
1295+ * Truthy values request the deprecated IMAP parser
1296+ * and trigger a deprecation warning .
12951297 * @param string $charset The charset to use when decoding the address list string.
12961298 *
12971299 * @return array
12981300 */
12991301 public static function parseAddresses ($ addrstr , $ useimap = null , $ charset = self ::CHARSET_ISO88591 )
13001302 {
1301- if ($ useimap ! == null ) {
1303+ if ($ useimap == true ) {
13021304 trigger_error (self ::lang ('deprecated_argument ' ) . '$useimap ' , E_USER_DEPRECATED );
13031305 }
13041306 $ addresses = [];
1305- if (function_exists ('imap_rfc822_parse_adrlist ' )) {
1307+ if ($ useimap == true && function_exists ('imap_rfc822_parse_adrlist ' )) {
13061308 //Use this built-in parser if it's available
13071309 // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.imap_rfc822_parse_adrlistRemoved -- wrapped in function_exists()
13081310 $ list = imap_rfc822_parse_adrlist ($ addrstr , '' );
@@ -1779,6 +1781,8 @@ public function preSend()
17791781
17801782 //Trim subject consistently
17811783 $ this ->Subject = trim ($ this ->Subject );
1784+
1785+
17821786 //Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
17831787 $ this ->MIMEHeader = '' ;
17841788 $ this ->MIMEBody = $ this ->createBody ();
@@ -1853,7 +1857,7 @@ public function postSend()
18531857 return $ this ->mailSend ($ this ->MIMEHeader , $ this ->MIMEBody );
18541858 default :
18551859 $ sendMethod = $ this ->Mailer . 'Send ' ;
1856- if (method_exists ($ this , $ sendMethod )) {
1860+ if (! empty ( $ this -> Mailer ) && method_exists ($ this , $ sendMethod )) {
18571861 return $ this ->{$ sendMethod }($ this ->MIMEHeader , $ this ->MIMEBody );
18581862 }
18591863
@@ -1911,7 +1915,7 @@ protected function sendmailSend($header, $body)
19111915
19121916 // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
19131917 // Also don't add the -f automatically unless it has been set either via Sender
1914- // or sendmail_path. Otherwise it can introduce new problems.
1918+ // or sendmail_path. Otherwise, it can introduce new problems.
19151919 // @see http://github.com/PHPMailer/PHPMailer/issues/2298
19161920 if (!empty ($ this ->Sender ) && static ::validateAddress ($ this ->Sender ) && self ::isShellSafe ($ this ->Sender )) {
19171921 $ sendmailArgs [] = '-f ' . $ this ->Sender ;
@@ -2510,7 +2514,7 @@ public static function setLanguage($langcode = 'en', $lang_path = '')
25102514 'authenticate ' => 'SMTP Error: Could not authenticate. ' ,
25112515 'buggy_php ' => 'Your version of PHP is affected by a bug that may result in corrupted messages. ' .
25122516 ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in ' .
2513- ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+. ' ,
2517+ ' your php.ini, switch to macOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+. ' ,
25142518 'connect_host ' => 'SMTP Error: Could not connect to SMTP host. ' ,
25152519 'data_not_accepted ' => 'SMTP Error: data not accepted. ' ,
25162520 'empty_message ' => 'Message body empty ' ,
@@ -2847,7 +2851,10 @@ public function createHeader()
28472851 {
28482852 $ result = '' ;
28492853
2850- $ result .= $ this ->headerLine ('Date ' , '' === $ this ->MessageDate ? self ::rfcDate () : $ this ->MessageDate );
2854+ $ result .= $ this ->headerLine (
2855+ 'Date ' ,
2856+ self ::sanitiseDate ($ this ->MessageDate )
2857+ );
28512858
28522859 //The To header is created automatically by mail(), so needs to be omitted here
28532860 if ('mail ' !== $ this ->Mailer ) {
@@ -2916,7 +2923,7 @@ public function createHeader()
29162923 );
29172924 } elseif (is_string ($ this ->XMailer ) && trim ($ this ->XMailer ) !== '' ) {
29182925 //Some string
2919- $ result .= $ this ->headerLine ('X-Mailer ' , trim ($ this ->XMailer ));
2926+ $ result .= $ this ->headerLine ('X-Mailer ' , $ this -> secureHeader ( trim ($ this ->XMailer ) ));
29202927 } //Other values result in no X-Mailer header
29212928
29222929 if ('' !== $ this ->ConfirmReadingTo ) {
@@ -2966,13 +2973,20 @@ public function getMailMIME()
29662973 break ;
29672974 default :
29682975 //Catches case 'plain': and case '':
2969- $ result .= $ this ->textLine ('Content-Type: ' . $ this ->ContentType . '; charset= ' . $ this ->CharSet );
2976+ $ result .= $ this ->textLine (
2977+ 'Content-Type: ' .
2978+ $ this ->secureHeader ($ this ->ContentType ) .
2979+ '; charset= ' . $ this ->secureHeader ($ this ->CharSet )
2980+ );
29702981 $ ismultipart = false ;
29712982 break ;
29722983 }
2984+ if (!$ this ->validateEncoding ($ this ->Encoding )) {
2985+ throw new Exception (self ::lang ('encoding ' ) . $ this ->Encoding );
2986+ }
29732987 //RFC1341 part 5 says 7bit is assumed if not specified
29742988 if (static ::ENCODING_7BIT !== $ this ->Encoding ) {
2975- //RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
2989+ //RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit, or binary CTE
29762990 if ($ ismultipart ) {
29772991 if (static ::ENCODING_8BIT === $ this ->Encoding ) {
29782992 $ result .= $ this ->headerLine ('Content-Transfer-Encoding ' , static ::ENCODING_8BIT );
@@ -3047,6 +3061,9 @@ public function createBody()
30473061
30483062 $ this ->setWordWrap ();
30493063
3064+ if (!$ this ->validateEncoding ($ this ->Encoding )) {
3065+ throw new Exception (self ::lang ('encoding ' ) . $ this ->Encoding );
3066+ }
30503067 $ bodyEncoding = $ this ->Encoding ;
30513068 $ bodyCharSet = $ this ->CharSet ;
30523069 //Can we do a 7-bit downgrade?
@@ -4166,7 +4183,7 @@ public function addStringEmbeddedImage(
41664183 protected function validateEncoding ($ encoding )
41674184 {
41684185 return in_array (
4169- $ encoding ,
4186+ strtolower ( $ encoding) ,
41704187 [
41714188 self ::ENCODING_7BIT ,
41724189 self ::ENCODING_QUOTED_PRINTABLE ,
@@ -4426,7 +4443,7 @@ protected function setError($msg)
44264443 }
44274444
44284445 /**
4429- * Return an RFC 822 formatted date.
4446+ * Return the current date and time as an RFC 822 formatted date.
44304447 *
44314448 * @return string
44324449 */
@@ -4436,7 +4453,51 @@ public static function rfcDate()
44364453 //Will default to UTC if it's not set properly in php.ini
44374454 date_default_timezone_set (@date_default_timezone_get ());
44384455
4439- return date ('D, j M Y H:i:s O ' );
4456+ return date (self ::RFC822_DATE_FORMAT );
4457+ }
4458+
4459+ /**
4460+ * Normalise a user-supplied date into a correctly-formatted RFC 5322 date value
4461+ * string suitable for use in the Date header.
4462+ *
4463+ * Accepts:
4464+ * - A {@see \DateTime} (or \DateTimeImmutable) object
4465+ * - Any date/time string understood by PHP's DateTime constructor (RFC 5322, ISO 8601,
4466+ * Unix timestamp with leading "@", natural-language strings, etc.)
4467+ *
4468+ * Dates in the future are not permitted for email headers; if the parsed date is later
4469+ * than "now" the method falls back to the current time via {@see self::rfcDate()}.
4470+ * An empty value, a non-string/non-DateTime argument, or any value that cannot be
4471+ * parsed will likewise fall back to {@see self::rfcDate()}.
4472+ *
4473+ * @param \DateTime|\DateTimeImmutable|string $date The date to normalise
4474+ *
4475+ * @return string An RFC 5322-formatted date string
4476+ */
4477+ private static function sanitiseDate ($ date )
4478+ {
4479+ try {
4480+ //Ensure the default timezone is set properly
4481+ date_default_timezone_set (@date_default_timezone_get ());
4482+
4483+ if ($ date instanceof \DateTimeInterface) {
4484+ $ dt = $ date ;
4485+ } elseif (is_string ($ date ) && $ date !== '' ) {
4486+ $ dt = new \DateTime ($ date );
4487+ } else {
4488+ //Empty string, null, or any unsupported type
4489+ return self ::rfcDate ();
4490+ }
4491+
4492+ //Reject future dates — they are invalid for outgoing message headers
4493+ if ($ dt ->getTimestamp () > time ()) {
4494+ return self ::rfcDate ();
4495+ }
4496+
4497+ return $ dt ->format (self ::RFC822_DATE_FORMAT );
4498+ } catch (\Exception $ e ) {
4499+ return self ::rfcDate ();
4500+ }
44404501 }
44414502
44424503 /**
0 commit comments