Ticket #25014: 25014.patch
File 25014.patch, 54.7 KB (added by , 11 years ago) |
---|
-
wp-includes/class-phpmailer.php
2 2 /*~ class.phpmailer.php 3 3 .---------------------------------------------------------------------------. 4 4 | Software: PHPMailer - PHP email class | 5 | Version: 5.2. 4|6 | Site: https:// code.google.com/a/apache-extras.org/p/phpmailer/|5 | Version: 5.2.6 | 6 | Site: https://github.com/PHPMailer/PHPMailer/ | 7 7 | ------------------------------------------------------------------------- | 8 | Admin: Jim Jagielski (project admininistrator) | 8 | Admins: Marcus Bointon | 9 | Admins: Jim Jagielski | 9 10 | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 10 | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net|11 | : Marcus Bointon (coolbru) phpmailer@synchromedia.co.uk | 11 12 | : Jim Jagielski (jimjag) jimjag@gmail.com | 12 13 | Founder: Brent R. Matzelle (original founder) | 13 14 | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. | … … 34 35 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 35 36 */ 36 37 37 if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n"); 38 if (version_compare(PHP_VERSION, '5.0.0', '<') ) { 39 exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n"); 40 } 38 41 39 42 /** 40 43 * PHP email creation and transport class … … 90 93 public $FromName = 'Root User'; 91 94 92 95 /** 93 * Sets the Sender email (Return-Path) of the message. If not empty,94 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.96 * Sets the Sender email (Return-Path) of the message. 97 * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. 95 98 * @var string 96 99 */ 97 100 public $Sender = ''; … … 110 113 public $Subject = ''; 111 114 112 115 /** 113 * Sets the Body of the message. This can be either an HTML or textbody.114 * If HTML then runIsHTML(true).116 * An HTML or plain text message body. 117 * If HTML then call IsHTML(true). 115 118 * @var string 116 119 */ 117 120 public $Body = ''; 118 121 119 122 /** 120 * Sets the text-only body of the message. This automatically sets the121 * email to multipart/alternative. This body can be read bymail122 * c lients that do not have HTML email capability such as mutt. Clients123 * that can read HTML will view the normal Body.123 * The plain-text message body. 124 * This body can be read by mail clients that do not have HTML email 125 * capability such as mutt & Eudora. 126 * Clients that can read HTML will view the normal Body. 124 127 * @var string 125 128 */ 126 129 public $AltBody = ''; 127 130 128 131 /** 132 * An iCal message part body 133 * Only supported in simple alt or alt_inline message types 134 * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator 135 * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ 136 * @link http://kigkonsult.se/iCalcreator/ 137 * @var string 138 */ 139 public $Ical = ''; 140 141 /** 129 142 * Stores the complete compiled MIME message body. 130 143 * @var string 131 144 * @access protected … … 143 156 * Stores the extra header list which CreateHeader() doesn't fold in 144 157 * @var string 145 158 * @access protected 146 */159 */ 147 160 protected $mailHeader = ''; 148 161 149 162 /** … … 171 184 * @var boolean 172 185 */ 173 186 public $UseSendmailOptions = true; 174 187 175 188 /** 176 189 * Path to PHPMailer plugins. Useful if the SMTP class 177 190 * is in a different directory than the PHP include path. … … 260 273 public $Password = ''; 261 274 262 275 /** 263 * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM (default LOGIN)276 * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM | CRAM-MD5 (default LOGIN) 264 277 * @var string 265 278 */ 266 279 public $AuthType = ''; 267 280 268 281 /** 269 282 * Sets SMTP realm. 270 283 * @var string … … 312 325 */ 313 326 public $SingleTo = false; 314 327 315 /** 328 /** 329 * Should we generate VERP addresses when sending via SMTP? 330 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 331 * @var bool 332 */ 333 public $do_verp = false; 334 335 /** 316 336 * If SingleTo is true, this provides the array to hold the email addresses 317 337 * @var bool 318 338 */ 319 339 public $SingleToArray = array(); 320 340 321 /** 341 /** 342 * Should we allow sending messages with empty body? 343 * @var bool 344 */ 345 public $AllowEmpty = false; 346 347 /** 322 348 * Provides the ability to change the generic line ending 323 349 * NOTE: The default remains '\n'. We force CRLF where we KNOW 324 350 * it must be used via self::CRLF … … 390 416 * Sets the PHPMailer Version number 391 417 * @var string 392 418 */ 393 public $Version = '5.2. 4';419 public $Version = '5.2.6'; 394 420 395 421 /** 396 422 * What to use in the X-Mailer header … … 491 517 const STOP_CONTINUE = 1; // message?, likely ok to continue processing 492 518 const STOP_CRITICAL = 2; // message, plus full stop, critical error reached 493 519 const CRLF = "\r\n"; // SMTP RFC specified EOL 494 520 495 521 ///////////////////////////////////////////////// 496 522 // METHODS, VARIABLES 497 523 ///////////////////////////////////////////////// … … 522 548 * Outputs debugging info via user-defined method 523 549 * @param string $str 524 550 */ 525 private function edebug($str) { 526 if ($this->Debugoutput == "error_log") { 551 protected function edebug($str) { 552 switch ($this->Debugoutput) { 553 case 'error_log': 527 554 error_log($str); 528 } else { 555 break; 556 case 'html': 557 //Cleans up output a bit for a better looking display that's HTML-safe 558 echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, $this->CharSet)."<br>\n"; 559 break; 560 case 'echo': 561 default: 562 //Just echoes exactly what was received 529 563 echo $str; 530 564 } 531 565 } … … 539 573 } 540 574 541 575 /** 576 * Destructor 577 */ 578 public function __destruct() { 579 if ($this->Mailer == 'smtp') { //Close any open SMTP connection nicely 580 $this->SmtpClose(); 581 } 582 } 583 584 /** 542 585 * Sets message type to HTML. 543 586 * @param bool $ishtml 544 587 * @return void … … 683 726 return false; 684 727 } 685 728 686 /**687 * Set the From and FromName properties688 * @param string $address689 * @param string $name690 * @param int $auto Also set Reply-To and Sender729 /** 730 * Set the From and FromName properties 731 * @param string $address 732 * @param string $name 733 * @param boolean $auto Whether to also set the Sender address, defaults to true 691 734 * @throws phpmailerException 692 * @return boolean693 */694 public function SetFrom($address, $name = '', $auto = 1) {735 * @return boolean 736 */ 737 public function SetFrom($address, $name = '', $auto = true) { 695 738 $address = trim($address); 696 739 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 697 740 if (!$this->ValidateAddress($address)) { … … 707 750 $this->From = $address; 708 751 $this->FromName = $name; 709 752 if ($auto) { 710 if (empty($this->ReplyTo)) {711 $this->AddAnAddress('Reply-To', $address, $name);712 }713 753 if (empty($this->Sender)) { 714 754 $this->Sender = $address; 715 755 } … … 723 763 * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is 724 764 * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to 725 765 * not allow a@b type valid addresses :( 726 * Some Versions of PHP break on the regex though, likely due to PCRE, so use727 * the older validation method for those users. (http://php.net/manual/en/pcre.installation.php)728 766 * @link http://squiloople.com/2009/12/20/email-address-validation/ 729 767 * @copyright regex Copyright Michael Rushton 2009-10 | http://squiloople.com/ | Feel free to use and redistribute this code. But please keep this copyright notice. 730 768 * @param string $address The email address to check … … 733 771 * @access public 734 772 */ 735 773 public static function ValidateAddress($address) { 736 if ((defined('PCRE_VERSION')) && (version_compare(PCRE_VERSION, '8.0') >= 0)) { 737 return preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[ ])+|(?>[ ]*\x0D\x0A)?[ ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){7,})((?6)(?>:(?6)){0,5})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){5,})(?8)?::(?>((?6)(?>:(?6)){0,3}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address); 738 } elseif (function_exists('filter_var')) { //Introduced in PHP 5.2 739 if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { 740 return false; 741 } else { 742 return true; 743 } 744 } else { 745 return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[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_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); 746 } 774 if (defined('PCRE_VERSION')) { //Check this instead of extension_loaded so it works when that function is disabled 775 if (version_compare(PCRE_VERSION, '8.0') >= 0) { 776 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))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address); 777 } else { 778 //Fall back to an older regex that doesn't need a recent PCRE 779 return (boolean)preg_match('/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', $address); 780 } 781 } else { 782 //No PCRE! Do something _very_ approximate! 783 //Check the address is 3 chars or longer and contains an @ that's not the first or last char 784 return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1); 785 } 747 786 } 748 787 749 788 ///////////////////////////////////////////////// … … 790 829 791 830 $this->error_count = 0; // reset errors 792 831 $this->SetMessageType(); 793 //Refuse to send an empty message 794 if ( empty($this->Body)) {832 //Refuse to send an empty message unless we are specifically allowing it 833 if (!$this->AllowEmpty and empty($this->Body)) { 795 834 throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); 796 835 } 797 836 … … 807 846 $this->mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;"); 808 847 } 809 848 $this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject)))); 810 // if(count($this->cc) > 0) {811 // $this->mailHeader .= $this->AddrAppend("Cc", $this->cc);812 // }813 849 } 814 850 815 851 // digitally sign with DKIM if enabled 816 852 if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) { 817 $header_dkim = $this->DKIM_Add($this->MIMEHeader , $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);853 $header_dkim = $this->DKIM_Add($this->MIMEHeader . $this->mailHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody); 818 854 $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader; 819 855 } 820 856 … … 911 947 * Sends mail using the PHP mail() function. 912 948 * @param string $header The message headers 913 949 * @param string $body The message body 914 950 * @throws phpmailerException 915 951 * @access protected 916 952 * @return bool 917 953 */ … … 923 959 $to = implode(', ', $toArr); 924 960 925 961 if (empty($this->Sender)) { 926 $params = " -oi";962 $params = " "; 927 963 } else { 928 $params = sprintf("- oi -f%s", $this->Sender);964 $params = sprintf("-f%s", $this->Sender); 929 965 } 930 966 if ($this->Sender != '' and !ini_get('safe_mode')) { 931 967 $old_from = ini_get('sendmail_from'); … … 965 1001 * @return bool 966 1002 */ 967 1003 protected function SmtpSend($header, $body) { 968 require_once $this->PluginDir . 'class -smtp.php';1004 require_once $this->PluginDir . 'class.smtp.php'; 969 1005 $bad_rcpt = array(); 970 1006 971 1007 if(!$this->SmtpConnect()) { … … 973 1009 } 974 1010 $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; 975 1011 if(!$this->smtp->Mail($smtp_from)) { 976 $this->SetError($this->Lang('from_failed') . $smtp_from . " : " . implode(",",$this->smtp->getError()));1012 $this->SetError($this->Lang('from_failed') . $smtp_from . ' : ' .implode(',', $this->smtp->getError())); 977 1013 throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); 978 1014 } 979 1015 … … 1035 1071 /** 1036 1072 * Initiates a connection to an SMTP server. 1037 1073 * Returns false if the operation failed. 1074 * @param array $options An array of options compatible with stream_context_create() 1038 1075 * @uses SMTP 1039 1076 * @access public 1040 1077 * @throws phpmailerException 1041 1078 * @return bool 1042 1079 */ 1043 public function SmtpConnect( ) {1080 public function SmtpConnect($options = array()) { 1044 1081 if(is_null($this->smtp)) { 1045 1082 $this->smtp = new SMTP; 1046 1083 } 1047 1084 1085 //Already connected? 1086 if ($this->smtp->Connected()) { 1087 return true; 1088 } 1089 1048 1090 $this->smtp->Timeout = $this->Timeout; 1049 1091 $this->smtp->do_debug = $this->SMTPDebug; 1092 $this->smtp->Debugoutput = $this->Debugoutput; 1093 $this->smtp->do_verp = $this->do_verp; 1094 $index = 0; 1095 $tls = ($this->SMTPSecure == 'tls'); 1096 $ssl = ($this->SMTPSecure == 'ssl'); 1050 1097 $hosts = explode(';', $this->Host); 1051 $index = 0; 1052 $connection = $this->smtp->Connected(); 1098 $lastexception = null; 1053 1099 1054 // Retry while there is no connection 1055 try { 1056 while($index < count($hosts) && !$connection) { 1057 $hostinfo = array(); 1058 if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { 1059 $host = $hostinfo[1]; 1060 $port = $hostinfo[2]; 1061 } else { 1062 $host = $hosts[$index]; 1063 $port = $this->Port; 1064 } 1065 1066 $tls = ($this->SMTPSecure == 'tls'); 1067 $ssl = ($this->SMTPSecure == 'ssl'); 1068 1069 if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { 1070 1071 $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); 1100 foreach ($hosts as $hostentry) { 1101 $hostinfo = array(); 1102 $host = $hostentry; 1103 $port = $this->Port; 1104 if (preg_match('/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) { //If $hostentry contains 'address:port', override default 1105 $host = $hostinfo[1]; 1106 $port = $hostinfo[2]; 1107 } 1108 if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $options)) { 1109 try { 1110 if ($this->Helo) { 1111 $hello = $this->Helo; 1112 } else { 1113 $hello = $this->ServerHostname(); 1114 } 1072 1115 $this->smtp->Hello($hello); 1073 1116 1074 1117 if ($tls) { 1075 1118 if (!$this->smtp->StartTLS()) { 1076 1119 throw new phpmailerException($this->Lang('connect_host')); 1077 1120 } 1078 1079 1121 //We must resend HELO after tls negotiation 1080 1122 $this->smtp->Hello($hello); 1081 1123 } 1082 1083 $connection = true;1084 1124 if ($this->SMTPAuth) { 1085 if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, 1086 $this->Realm, $this->Workstation)) { 1125 if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) { 1087 1126 throw new phpmailerException($this->Lang('authenticate')); 1088 1127 } 1089 1128 } 1129 return true; 1130 } catch (phpmailerException $e) { 1131 $lastexception = $e; 1132 //We must have connected, but then failed TLS or Auth, so close connection nicely 1133 $this->smtp->Quit(); 1090 1134 } 1091 $index++;1092 if (!$connection) {1093 throw new phpmailerException($this->Lang('connect_host'));1094 1135 } 1095 }1096 } catch (phpmailerException $e) {1097 $this->smtp->Reset();1098 if ($this->exceptions) {1099 throw $e;1100 }1101 1136 } 1102 return true; 1137 //If we get here, all connection attempts have failed, so close connection hard 1138 $this->smtp->Close(); 1139 //As we've caught all exceptions, just report whatever the last one was 1140 if ($this->exceptions and !is_null($lastexception)) { 1141 throw $lastexception; 1142 } 1143 return false; 1103 1144 } 1104 1145 1105 1146 /** … … 1116 1157 } 1117 1158 1118 1159 /** 1119 * Sets the language for all class error messages.1120 * Returns false if it cannot load the language file. The default language is English.1121 * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")1122 * @param string $lang_path Path to the language file directory1160 * Sets the language for all class error messages. 1161 * Returns false if it cannot load the language file. The default language is English. 1162 * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") 1163 * @param string $lang_path Path to the language file directory 1123 1164 * @return bool 1124 * @access public1125 */1165 * @access public 1166 */ 1126 1167 function SetLanguage($langcode = 'en', $lang_path = 'language/') { 1127 1168 //Define full set of translatable strings 1128 1169 $PHPMAILER_LANG = array( … … 1251 1292 $buf = ''; 1252 1293 } 1253 1294 while (strlen($word) > 0) { 1295 if ($length <= 0) { 1296 break; 1297 } 1254 1298 $len = $length; 1255 1299 if ($is_utf8) { 1256 1300 $len = $this->UTF8CharBoundary($word, $len); … … 1370 1414 } 1371 1415 1372 1416 if ($this->ReturnPath) { 1373 $result .= $this->HeaderLine('Return-Path', trim($this->ReturnPath));1417 $result .= $this->HeaderLine('Return-Path', '<'.trim($this->ReturnPath).'>'); 1374 1418 } elseif ($this->Sender == '') { 1375 $result .= $this->HeaderLine('Return-Path', trim($this->From));1419 $result .= $this->HeaderLine('Return-Path', '<'.trim($this->From).'>'); 1376 1420 } else { 1377 $result .= $this->HeaderLine('Return-Path', trim($this->Sender));1421 $result .= $this->HeaderLine('Return-Path', '<'.trim($this->Sender).'>'); 1378 1422 } 1379 1423 1380 1424 // To be created automatically by mail() … … 1423 1467 } 1424 1468 $result .= $this->HeaderLine('X-Priority', $this->Priority); 1425 1469 if ($this->XMailer == '') { 1426 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http ://code.google.com/a/apache-extras.org/p/phpmailer/)');1470 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (https://github.com/PHPMailer/PHPMailer/)'); 1427 1471 } else { 1428 1472 $myXmailer = trim($this->XMailer); 1429 1473 if ($myXmailer) { … … 1457 1501 switch($this->message_type) { 1458 1502 case 'inline': 1459 1503 $result .= $this->HeaderLine('Content-Type', 'multipart/related;'); 1460 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] .'"');1504 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); 1461 1505 break; 1462 1506 case 'attach': 1463 1507 case 'inline_attach': 1464 1508 case 'alt_attach': 1465 1509 case 'alt_inline_attach': 1466 1510 $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); 1467 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] .'"');1511 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); 1468 1512 break; 1469 1513 case 'alt': 1470 1514 case 'alt_inline': 1471 1515 $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); 1472 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] .'"');1516 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"'); 1473 1517 break; 1474 1518 default: 1475 1519 // Catches case 'plain': and case '': 1476 $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);1477 1520 $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet); 1478 1521 break; 1479 1522 } 1523 //RFC1341 part 5 says 7bit is assumed if not specified 1524 if ($this->Encoding != '7bit') { 1525 $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); 1526 } 1480 1527 1481 1528 if($this->Mailer != 'mail') { 1482 1529 $result .= $this->LE; … … 1515 1562 $body .= $this->GetBoundary($this->boundary[1], '', '', ''); 1516 1563 $body .= $this->EncodeString($this->Body, $this->Encoding); 1517 1564 $body .= $this->LE.$this->LE; 1518 $body .= $this->AttachAll( "inline", $this->boundary[1]);1565 $body .= $this->AttachAll('inline', $this->boundary[1]); 1519 1566 break; 1520 1567 case 'attach': 1521 1568 $body .= $this->GetBoundary($this->boundary[1], '', '', ''); 1522 1569 $body .= $this->EncodeString($this->Body, $this->Encoding); 1523 1570 $body .= $this->LE.$this->LE; 1524 $body .= $this->AttachAll( "attachment", $this->boundary[1]);1571 $body .= $this->AttachAll('attachment', $this->boundary[1]); 1525 1572 break; 1526 1573 case 'inline_attach': 1527 $body .= $this->TextLine( "--". $this->boundary[1]);1574 $body .= $this->TextLine('--' . $this->boundary[1]); 1528 1575 $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); 1529 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] .'"');1576 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); 1530 1577 $body .= $this->LE; 1531 1578 $body .= $this->GetBoundary($this->boundary[2], '', '', ''); 1532 1579 $body .= $this->EncodeString($this->Body, $this->Encoding); 1533 1580 $body .= $this->LE.$this->LE; 1534 $body .= $this->AttachAll( "inline", $this->boundary[2]);1581 $body .= $this->AttachAll('inline', $this->boundary[2]); 1535 1582 $body .= $this->LE; 1536 $body .= $this->AttachAll( "attachment", $this->boundary[1]);1583 $body .= $this->AttachAll('attachment', $this->boundary[1]); 1537 1584 break; 1538 1585 case 'alt': 1539 1586 $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); … … 1542 1589 $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); 1543 1590 $body .= $this->EncodeString($this->Body, $this->Encoding); 1544 1591 $body .= $this->LE.$this->LE; 1592 if(!empty($this->Ical)) { 1593 $body .= $this->GetBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); 1594 $body .= $this->EncodeString($this->Ical, $this->Encoding); 1595 $body .= $this->LE.$this->LE; 1596 } 1545 1597 $body .= $this->EndBoundary($this->boundary[1]); 1546 1598 break; 1547 1599 case 'alt_inline': 1548 1600 $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); 1549 1601 $body .= $this->EncodeString($this->AltBody, $this->Encoding); 1550 1602 $body .= $this->LE.$this->LE; 1551 $body .= $this->TextLine( "--". $this->boundary[1]);1603 $body .= $this->TextLine('--' . $this->boundary[1]); 1552 1604 $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); 1553 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] .'"');1605 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); 1554 1606 $body .= $this->LE; 1555 1607 $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', ''); 1556 1608 $body .= $this->EncodeString($this->Body, $this->Encoding); 1557 1609 $body .= $this->LE.$this->LE; 1558 $body .= $this->AttachAll( "inline", $this->boundary[2]);1610 $body .= $this->AttachAll('inline', $this->boundary[2]); 1559 1611 $body .= $this->LE; 1560 1612 $body .= $this->EndBoundary($this->boundary[1]); 1561 1613 break; 1562 1614 case 'alt_attach': 1563 $body .= $this->TextLine( "--". $this->boundary[1]);1615 $body .= $this->TextLine('--' . $this->boundary[1]); 1564 1616 $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); 1565 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] .'"');1617 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); 1566 1618 $body .= $this->LE; 1567 1619 $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); 1568 1620 $body .= $this->EncodeString($this->AltBody, $this->Encoding); … … 1572 1624 $body .= $this->LE.$this->LE; 1573 1625 $body .= $this->EndBoundary($this->boundary[2]); 1574 1626 $body .= $this->LE; 1575 $body .= $this->AttachAll( "attachment", $this->boundary[1]);1627 $body .= $this->AttachAll('attachment', $this->boundary[1]); 1576 1628 break; 1577 1629 case 'alt_inline_attach': 1578 $body .= $this->TextLine( "--". $this->boundary[1]);1630 $body .= $this->TextLine('--' . $this->boundary[1]); 1579 1631 $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); 1580 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] .'"');1632 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"'); 1581 1633 $body .= $this->LE; 1582 1634 $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); 1583 1635 $body .= $this->EncodeString($this->AltBody, $this->Encoding); 1584 1636 $body .= $this->LE.$this->LE; 1585 $body .= $this->TextLine( "--". $this->boundary[2]);1637 $body .= $this->TextLine('--' . $this->boundary[2]); 1586 1638 $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); 1587 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] .'"');1639 $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3].'"'); 1588 1640 $body .= $this->LE; 1589 1641 $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', ''); 1590 1642 $body .= $this->EncodeString($this->Body, $this->Encoding); 1591 1643 $body .= $this->LE.$this->LE; 1592 $body .= $this->AttachAll( "inline", $this->boundary[3]);1644 $body .= $this->AttachAll('inline', $this->boundary[3]); 1593 1645 $body .= $this->LE; 1594 1646 $body .= $this->EndBoundary($this->boundary[2]); 1595 1647 $body .= $this->LE; 1596 $body .= $this->AttachAll( "attachment", $this->boundary[1]);1648 $body .= $this->AttachAll('attachment', $this->boundary[1]); 1597 1649 break; 1598 1650 default: 1599 1651 // catch case 'plain' and case '' … … 1605 1657 $body = ''; 1606 1658 } elseif ($this->sign_key_file) { 1607 1659 try { 1608 $file = tempnam('', 'mail'); 1660 if (!defined('PKCS7_TEXT')) { 1661 throw new phpmailerException($this->Lang('signing').' OpenSSL extension missing.'); 1662 } 1663 $file = tempnam(sys_get_temp_dir(), 'mail'); 1609 1664 file_put_contents($file, $body); //TODO check this worked 1610 $signed = tempnam( "", "signed");1611 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {1665 $signed = tempnam(sys_get_temp_dir(), 'signed'); 1666 if (@openssl_pkcs7_sign($file, $signed, 'file://'.realpath($this->sign_cert_file), array('file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) { 1612 1667 @unlink($file); 1613 1668 $body = file_get_contents($signed); 1614 1669 @unlink($signed); 1615 1670 } else { 1616 1671 @unlink($file); 1617 1672 @unlink($signed); 1618 throw new phpmailerException($this->Lang( "signing").openssl_error_string());1673 throw new phpmailerException($this->Lang('signing').openssl_error_string()); 1619 1674 } 1620 1675 } catch (phpmailerException $e) { 1621 1676 $body = ''; … … 1624 1679 } 1625 1680 } 1626 1681 } 1627 1628 1682 return $body; 1629 1683 } 1630 1684 … … 1682 1736 } 1683 1737 1684 1738 /** 1685 * 1739 * Returns a formatted header line. 1686 1740 * @access public 1687 1741 * @param string $name 1688 1742 * @param string $value … … 1714 1768 * @param string $name Overrides the attachment name. 1715 1769 * @param string $encoding File encoding (see $Encoding). 1716 1770 * @param string $type File extension (MIME) type. 1771 * @param string $disposition Disposition to use 1717 1772 * @throws phpmailerException 1718 1773 * @return bool 1719 1774 */ 1720 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = ' application/octet-stream') {1775 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') { 1721 1776 try { 1722 1777 if ( !@is_file($path) ) { 1723 1778 throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); 1724 1779 } 1780 1781 //If a MIME type is not specified, try to work it out from the file name 1782 if ($type == '') { 1783 $type = self::filenameToType($path); 1784 } 1785 1725 1786 $filename = basename($path); 1726 1787 if ( $name == '' ) { 1727 1788 $name = $filename; … … 1734 1795 3 => $encoding, 1735 1796 4 => $type, 1736 1797 5 => false, // isStringAttachment 1737 6 => 'attachment',1798 6 => $disposition, 1738 1799 7 => 0 1739 1800 ); 1740 1801 … … 1746 1807 if ($this->SMTPDebug) { 1747 1808 $this->edebug($e->getMessage()."\n"); 1748 1809 } 1749 if ( $e->getCode() == self::STOP_CRITICAL ) { 1750 return false; 1751 } 1810 return false; 1752 1811 } 1753 1812 return true; 1754 1813 } … … 1809 1868 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); 1810 1869 } 1811 1870 1812 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); 1871 //If a filename contains any of these chars, it should be quoted, but not otherwise: RFC2183 & RFC2045 5.1 1872 //Fixes a warning in IETF's msglint MIME checker 1873 // 1874 // Allow for bypassing the Content-Disposition header totally 1875 if (!(empty($disposition))) { 1876 if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) { 1877 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); 1878 } else { 1879 $mime[] = sprintf("Content-Disposition: %s; filename=%s%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); 1880 } 1881 } else { 1882 $mime[] = $this->LE; 1883 } 1813 1884 1814 1885 // Encode as string attachment 1815 1886 if($bString) { … … 1848 1919 if (!is_readable($path)) { 1849 1920 throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); 1850 1921 } 1851 // if (!function_exists('get_magic_quotes')) {1852 // function get_magic_quotes() {1853 // return false;1854 // }1855 // }1856 1922 $magic_quotes = get_magic_quotes_runtime(); 1857 1923 if ($magic_quotes) { 1858 1924 if (version_compare(PHP_VERSION, '5.3.0', '<')) { 1859 1925 set_magic_quotes_runtime(0); 1860 1926 } else { 1861 ini_set('magic_quotes_runtime', 0); 1927 ini_set('magic_quotes_runtime', 0); 1862 1928 } 1863 1929 } 1864 1930 $file_buffer = file_get_contents($path); … … 1867 1933 if (version_compare(PHP_VERSION, '5.3.0', '<')) { 1868 1934 set_magic_quotes_runtime($magic_quotes); 1869 1935 } else { 1870 ini_set('magic_quotes_runtime', $magic_quotes); 1936 ini_set('magic_quotes_runtime', $magic_quotes); 1871 1937 } 1872 1938 } 1873 1939 return $file_buffer; … … 1943 2009 break; 1944 2010 } 1945 2011 1946 if ($x == 0) { 2012 if ($x == 0) { //There are no chars that need encoding 1947 2013 return ($str); 1948 2014 } 1949 2015 1950 2016 $maxlen = 75 - 7 - strlen($this->CharSet); 1951 2017 // Try to select the encoding which should produce the shortest output 1952 if ( strlen($str)/3 < $x) {2018 if ($x > strlen($str)/3) { //More than a third of the content will need encoding, so B encoding will be most efficient 1953 2019 $encoding = 'B'; 1954 2020 if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { 1955 2021 // Use a custom function which correctly encodes and wraps long … … 2032 2098 } 2033 2099 2034 2100 /** 2035 * Encode string to quoted-printable. 2036 * Only uses standard PHP, slow, but will always work 2037 * @access public 2038 * @param string $input 2039 * @param integer $line_max Number of chars allowed on a line before wrapping 2040 * @param bool $space_conv 2041 * @internal param string $string the text to encode 2042 * @return string 2043 */ 2044 public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { 2045 $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); 2046 $lines = preg_split('/(?:\r\n|\r|\n)/', $input); 2047 $eol = "\r\n"; 2048 $escape = '='; 2049 $output = ''; 2050 while( list(, $line) = each($lines) ) { 2051 $linlen = strlen($line); 2052 $newline = ''; 2053 for($i = 0; $i < $linlen; $i++) { 2054 $c = substr( $line, $i, 1 ); 2055 $dec = ord( $c ); 2056 if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E 2057 $c = '=2E'; 2058 } 2059 if ( $dec == 32 ) { 2060 if ( $i == ( $linlen - 1 ) ) { // convert space at eol only 2061 $c = '=20'; 2062 } else if ( $space_conv ) { 2063 $c = '=20'; 2064 } 2065 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required 2066 $h2 = (integer)floor($dec/16); 2067 $h1 = (integer)floor($dec%16); 2068 $c = $escape.$hex[$h2].$hex[$h1]; 2069 } 2070 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted 2071 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 2072 $newline = ''; 2073 // check if newline first character will be point or not 2074 if ( $dec == 46 ) { 2075 $c = '=2E'; 2076 } 2077 } 2078 $newline .= $c; 2079 } // end of for 2080 $output .= $newline.$eol; 2081 } // end of while 2082 return $output; 2083 } 2084 2085 /** 2086 * Encode string to RFC2045 (6.7) quoted-printable format 2087 * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version 2088 * Also results in same content as you started with after decoding 2089 * @see EncodeQPphp() 2090 * @access public 2091 * @param string $string the text to encode 2092 * @param integer $line_max Number of chars allowed on a line before wrapping 2093 * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function 2094 * @return string 2095 * @author Marcus Bointon 2096 */ 2097 public function EncodeQP($string, $line_max = 76, $space_conv = false) { 2101 * Encode string to RFC2045 (6.7) quoted-printable format 2102 * @access public 2103 * @param string $string The text to encode 2104 * @param integer $line_max Number of chars allowed on a line before wrapping 2105 * @return string 2106 * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 2107 */ 2108 public function EncodeQP($string, $line_max = 76) { 2098 2109 if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) 2099 2110 return quoted_printable_encode($string); 2100 2111 } 2101 $filters = stream_get_filters(); 2102 if (!in_array('convert.*', $filters)) { //Got convert stream filter? 2103 return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation 2104 } 2105 $fp = fopen('php://temp/', 'r+'); 2106 $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks 2107 $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); 2108 $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); 2109 fputs($fp, $string); 2110 rewind($fp); 2111 $out = stream_get_contents($fp); 2112 stream_filter_remove($s); 2113 $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange 2114 fclose($fp); 2115 return $out; 2112 //Fall back to a pure PHP implementation 2113 $string = str_replace(array('%20', '%0D%0A.', '%0D%0A', '%'), array(' ', "\r\n=2E", "\r\n", '='), rawurlencode($string)); 2114 $string = preg_replace('/[^\r\n]{'.($line_max - 3).'}[^=\r\n]{2}/', "$0=\r\n", $string); 2115 return $string; 2116 2116 } 2117 2117 2118 2118 /** 2119 * Wrapper to preserve BC for old QP encoding function that was removed 2120 * @see EncodeQP() 2121 * @access public 2122 * @param string $string 2123 * @param integer $line_max 2124 * @param bool $space_conv 2125 * @return string 2126 */ 2127 public function EncodeQPphp($string, $line_max = 76, $space_conv = false) { 2128 return $this->EncodeQP($string, $line_max); 2129 } 2130 2131 /** 2119 2132 * Encode string to q encoding. 2120 2133 * @link http://tools.ietf.org/html/rfc2047 2121 2134 * @param string $str the text to encode … … 2125 2138 */ 2126 2139 public function EncodeQ($str, $position = 'text') { 2127 2140 //There should not be any EOL in the string 2128 $pattern="";2141 $pattern = ''; 2129 2142 $encoded = str_replace(array("\r", "\n"), '', $str); 2130 2143 switch (strtolower($position)) { 2131 2144 case 'phrase': … … 2134 2147 2135 2148 case 'comment': 2136 2149 $pattern = '\(\)"'; 2137 //note that we don t break here!2138 //for this reason we build the $pattern withou dincluding delimiters and []2150 //note that we don't break here! 2151 //for this reason we build the $pattern without including delimiters and [] 2139 2152 2140 2153 case 'text': 2141 2154 default: … … 2144 2157 $pattern = '\075\000-\011\013\014\016-\037\077\137\177-\377' . $pattern; 2145 2158 break; 2146 2159 } 2147 2160 2148 2161 if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { 2149 2162 foreach (array_unique($matches[0]) as $char) { 2150 2163 $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); 2151 2164 } 2152 2165 } 2153 2166 2154 2167 //Replace every spaces to _ (more readable than =20) 2155 2168 return str_replace(' ', '_', $encoded); 2156 2169 } … … 2164 2177 * @param string $filename Name of the attachment. 2165 2178 * @param string $encoding File encoding (see $Encoding). 2166 2179 * @param string $type File extension (MIME) type. 2180 * @param string $disposition Disposition to use 2167 2181 * @return void 2168 2182 */ 2169 public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { 2183 public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = '', $disposition = 'attachment') { 2184 //If a MIME type is not specified, try to work it out from the file name 2185 if ($type == '') { 2186 $type = self::filenameToType($filename); 2187 } 2170 2188 // Append to $attachment array 2171 2189 $this->attachment[] = array( 2172 2190 0 => $string, … … 2175 2193 3 => $encoding, 2176 2194 4 => $type, 2177 2195 5 => true, // isStringAttachment 2178 6 => 'attachment',2196 6 => $disposition, 2179 2197 7 => 0 2180 2198 ); 2181 2199 } 2182 2200 2183 2201 /** 2184 * Adds an embedded attachment. This can include images, sounds, and 2185 * just about any other document. Make sure to set the $type to an 2186 * image type. For JPEG images use "image/jpeg" and for GIF images 2187 * use "image/gif". 2202 * Add an embedded attachment from a file. 2203 * This can include images, sounds, and just about any other document type. 2188 2204 * @param string $path Path to the attachment. 2189 * @param string $cid Content ID of the attachment . Use this to identify2190 * the Id for accessing the image in an HTML form.2205 * @param string $cid Content ID of the attachment; Use this to reference 2206 * the content when using an embedded image in HTML. 2191 2207 * @param string $name Overrides the attachment name. 2192 2208 * @param string $encoding File encoding (see $Encoding). 2193 * @param string $type File extension (MIME) type. 2194 * @return bool 2209 * @param string $type File MIME type. 2210 * @param string $disposition Disposition to use 2211 * @return bool True on successfully adding an attachment 2195 2212 */ 2196 public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 2197 2213 public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') { 2198 2214 if ( !@is_file($path) ) { 2199 2215 $this->SetError($this->Lang('file_access') . $path); 2200 2216 return false; 2201 2217 } 2202 2218 2219 //If a MIME type is not specified, try to work it out from the file name 2220 if ($type == '') { 2221 $type = self::filenameToType($path); 2222 } 2223 2203 2224 $filename = basename($path); 2204 2225 if ( $name == '' ) { 2205 2226 $name = $filename; … … 2213 2234 3 => $encoding, 2214 2235 4 => $type, 2215 2236 5 => false, // isStringAttachment 2216 6 => 'inline',2237 6 => $disposition, 2217 2238 7 => $cid 2218 2239 ); 2219 2220 2240 return true; 2221 2241 } 2222 2242 2243 2223 2244 /** 2224 * Add s an embedded stringified attachment. This can include images, sounds, and2225 * just about any other document. Make sure to set the $type to an2226 * image type. For JPEG images use "image/jpeg" and for GIF images2227 * use "image/gif".2228 * @param string $string The attachment .2229 * @param string $cid Content ID of the attachment . Use this to identify2230 * the Id for accessing the image in an HTML form.2231 * @param string $name Overrides the attachment name.2245 * Add an embedded stringified attachment. 2246 * This can include images, sounds, and just about any other document type. 2247 * Be sure to set the $type to an image type for images: 2248 * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. 2249 * @param string $string The attachment binary data. 2250 * @param string $cid Content ID of the attachment; Use this to reference 2251 * the content when using an embedded image in HTML. 2252 * @param string $name 2232 2253 * @param string $encoding File encoding (see $Encoding). 2233 * @param string $type File extension (MIME) type. 2234 * @return bool 2254 * @param string $type MIME type. 2255 * @param string $disposition Disposition to use 2256 * @return bool True on successfully adding an attachment 2235 2257 */ 2236 public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 2258 public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') { 2259 //If a MIME type is not specified, try to work it out from the name 2260 if ($type == '') { 2261 $type = self::filenameToType($name); 2262 } 2263 2237 2264 // Append to $attachment array 2238 2265 $this->attachment[] = array( 2239 2266 0 => $string, … … 2242 2269 3 => $encoding, 2243 2270 4 => $type, 2244 2271 5 => true, // isStringAttachment 2245 6 => 'inline',2272 6 => $disposition, 2246 2273 7 => $cid 2247 2274 ); 2275 return true; 2248 2276 } 2249 2277 2250 2278 /** … … 2384 2412 * @static 2385 2413 */ 2386 2414 public static function RFCDate() { 2387 $tz = date('Z'); 2388 $tzs = ($tz < 0) ? '-' : '+'; 2389 $tz = abs($tz); 2390 $tz = (int)($tz/3600)*100 + ($tz%3600)/60; 2391 $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); 2392 2393 return $result; 2415 //Set the time zone to whatever the default is to avoid 500 errors 2416 //Will default to UTC if it's not set properly in php.ini 2417 date_default_timezone_set(@date_default_timezone_get()); 2418 return date('D, j M Y H:i:s O'); 2394 2419 } 2395 2420 2396 2421 /** … … 2471 2496 } 2472 2497 2473 2498 /** 2474 * Evaluates the message and returns modifications for inline images and backgrounds 2499 * Creates a message from an HTML string, making modifications for inline images and backgrounds 2500 * and creates a plain-text version by converting the HTML 2501 * Overwrites any existing values in $this->Body and $this->AltBody 2475 2502 * @access public 2476 * @param string $message Text to be HTML modified2503 * @param string $message HTML message string 2477 2504 * @param string $basedir baseline directory for path 2505 * @param bool $advanced Whether to use the advanced HTML to text converter 2478 2506 * @return string $message 2479 2507 */ 2480 public function MsgHTML($message, $basedir = '' ) {2508 public function MsgHTML($message, $basedir = '', $advanced = false) { 2481 2509 preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images); 2482 if (isset($images[2])) {2483 foreach ($images[2] as $i => $url) {2510 if (isset($images[2])) { 2511 foreach ($images[2] as $i => $url) { 2484 2512 // do not change urls for absolute images (thanks to corvuscorax) 2485 2513 if (!preg_match('#^[A-z]+://#', $url)) { 2486 2514 $filename = basename($url); … … 2488 2516 if ($directory == '.') { 2489 2517 $directory = ''; 2490 2518 } 2491 $cid = 'cid:' . md5($url); 2492 $ext = pathinfo($filename, PATHINFO_EXTENSION); 2493 $mimeType = self::_mime_types($ext); 2494 if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; } 2495 if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; } 2496 if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($url), $filename, 'base64', $mimeType) ) { 2497 $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"".$cid."\"", $message); 2519 $cid = md5($url).'@phpmailer.0'; //RFC2392 S 2 2520 if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { 2521 $basedir .= '/'; 2498 2522 } 2523 if (strlen($directory) > 1 && substr($directory, -1) != '/') { 2524 $directory .= '/'; 2525 } 2526 if ($this->AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename, 'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) { 2527 $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"cid:".$cid."\"", $message); 2528 } 2499 2529 } 2500 2530 } 2501 2531 } 2502 2532 $this->IsHTML(true); 2503 $this->Body = $message;2504 2533 if (empty($this->AltBody)) { 2505 $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message)));2506 if (!empty($textMsg)) {2507 $this->AltBody = html_entity_decode($textMsg, ENT_QUOTES, $this->CharSet);2508 }2509 }2510 if (empty($this->AltBody)) {2511 2534 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; 2512 2535 } 2513 return $message; 2536 //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better 2537 $this->Body = $this->NormalizeBreaks($message); 2538 $this->AltBody = $this->NormalizeBreaks($this->html2text($message, $advanced)); 2539 return $this->Body; 2514 2540 } 2515 2541 2542 /** 2543 * Convert an HTML string into a plain text version 2544 * @param string $html The HTML text to convert 2545 * @param bool $advanced Should this use the more complex html2text converter or just a simple one? 2546 * @return string 2547 */ 2548 public function html2text($html, $advanced = false) { 2549 if ($advanced) { 2550 require_once 'extras/class.html2text.php'; 2551 $h = new html2text($html); 2552 return $h->get_text(); 2553 } 2554 return html_entity_decode(trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet); 2555 } 2556 2516 2557 /** 2517 2558 * Gets the MIME type of the embedded or inline image 2518 2559 * @param string $ext File extension … … 2613 2654 } 2614 2655 2615 2656 /** 2616 * Set (or reset) Class Objects (variables) 2617 * 2618 * Usage Example: 2619 * $page->set('X-Priority', '3'); 2620 * 2621 * @access public 2622 * @param string $name Parameter Name 2623 * @param mixed $value Parameter Value 2624 * NOTE: will not work with arrays, there are no arrays to set/reset 2657 * Try to map a file name to a MIME type, default to application/octet-stream 2658 * @param string $filename A file name or full path, does not need to exist as a file 2659 * @return string 2660 * @static 2661 */ 2662 public static function filenameToType($filename) { 2663 //In case the path is a URL, strip any query string before getting extension 2664 $qpos = strpos($filename, '?'); 2665 if ($qpos !== false) { 2666 $filename = substr($filename, 0, $qpos); 2667 } 2668 $pathinfo = self::mb_pathinfo($filename); 2669 return self::_mime_types($pathinfo['extension']); 2670 } 2671 2672 /** 2673 * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. 2674 * Works similarly to the one in PHP >= 5.2.0 2675 * @link http://www.php.net/manual/en/function.pathinfo.php#107461 2676 * @param string $path A filename or path, does not need to exist as a file 2677 * @param integer|string $options Either a PATHINFO_* constant, or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 2678 * @return string|array 2679 * @static 2680 */ 2681 public static function mb_pathinfo($path, $options = null) { 2682 $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); 2683 $m = array(); 2684 preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m); 2685 if(array_key_exists(1, $m)) { 2686 $ret['dirname'] = $m[1]; 2687 } 2688 if(array_key_exists(2, $m)) { 2689 $ret['basename'] = $m[2]; 2690 } 2691 if(array_key_exists(5, $m)) { 2692 $ret['extension'] = $m[5]; 2693 } 2694 if(array_key_exists(3, $m)) { 2695 $ret['filename'] = $m[3]; 2696 } 2697 switch($options) { 2698 case PATHINFO_DIRNAME: 2699 case 'dirname': 2700 return $ret['dirname']; 2701 break; 2702 case PATHINFO_BASENAME: 2703 case 'basename': 2704 return $ret['basename']; 2705 break; 2706 case PATHINFO_EXTENSION: 2707 case 'extension': 2708 return $ret['extension']; 2709 break; 2710 case PATHINFO_FILENAME: 2711 case 'filename': 2712 return $ret['filename']; 2713 break; 2714 default: 2715 return $ret; 2716 } 2717 } 2718 2719 /** 2720 * Set (or reset) Class Objects (variables) 2721 * 2722 * Usage Example: 2723 * $page->set('X-Priority', '3'); 2724 * 2725 * @access public 2726 * @param string $name 2727 * @param mixed $value 2728 * NOTE: will not work with arrays, there are no arrays to set/reset 2625 2729 * @throws phpmailerException 2626 2730 * @return bool 2627 * @todo Should this not be using __set() magic function?2628 */2731 * @todo Should this not be using __set() magic function? 2732 */ 2629 2733 public function set($name, $value = '') { 2630 2734 try { 2631 2735 if (isset($this->$name) ) { … … 2645 2749 /** 2646 2750 * Strips newlines to prevent header injection. 2647 2751 * @access public 2648 * @param string $str String2752 * @param string $str 2649 2753 * @return string 2650 2754 */ 2651 2755 public function SecureHeader($str) { … … 2653 2757 } 2654 2758 2655 2759 /** 2760 * Normalize UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format 2761 * Defaults to CRLF (for message bodies) and preserves consecutive breaks 2762 * @param string $text 2763 * @param string $breaktype What kind of line break to use, defaults to CRLF 2764 * @return string 2765 * @access public 2766 * @static 2767 */ 2768 public static function NormalizeBreaks($text, $breaktype = "\r\n") { 2769 return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); 2770 } 2771 2772 2773 /** 2656 2774 * Set the private key file and password to sign the message. 2657 2775 * 2658 2776 * @access public 2659 * @param $cert_filename2660 * @param string $key_filename Parameter File Name2777 * @param string $cert_filename 2778 * @param string $key_filename 2661 2779 * @param string $key_pass Password for private key 2662 2780 */ 2663 2781 public function Sign($cert_filename, $key_filename, $key_pass) { … … 2691 2809 * 2692 2810 * @access public 2693 2811 * @param string $s Header 2812 * @throws phpmailerException 2694 2813 * @return string 2695 2814 */ 2696 2815 public function DKIM_Sign($s) { 2816 if (!defined('PKCS7_TEXT')) { 2817 if ($this->exceptions) { 2818 throw new phpmailerException($this->Lang("signing").' OpenSSL extension missing.'); 2819 } 2820 return ''; 2821 } 2697 2822 $privKeyStr = file_get_contents($this->DKIM_private); 2698 2823 if ($this->DKIM_passphrase != '') { 2699 2824 $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); … … 2761 2886 $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) 2762 2887 $subject_header = "Subject: $subject"; 2763 2888 $headers = explode($this->LE, $headers_line); 2764 $from_header = ""; 2765 $to_header = ""; 2889 $from_header = ''; 2890 $to_header = ''; 2891 $current = ''; 2766 2892 foreach($headers as $header) { 2767 2893 if (strpos($header, 'From:') === 0) { 2768 2894 $from_header = $header; 2895 $current = 'from_header'; 2769 2896 } elseif (strpos($header, 'To:') === 0) { 2770 2897 $to_header = $header; 2898 $current = 'to_header'; 2899 } else { 2900 if($current && strpos($header, ' =?') === 0){ 2901 $current .= $header; 2902 } else { 2903 $current = ''; 2904 } 2771 2905 } 2772 2906 } 2773 2907 $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); … … 2788 2922 "\tb="; 2789 2923 $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); 2790 2924 $signed = $this->DKIM_Sign($toSign); 2791 return "X-PHPMAILER-DKIM: code.google.com/a/apache-extras.org/p/phpmailer/\r\n".$dkimhdrs.$signed."\r\n";2925 return $dkimhdrs.$signed."\r\n"; 2792 2926 } 2793 2927 2794 2928 /** … … 2801 2935 * @param string $body 2802 2936 * @param string $from 2803 2937 */ 2804 protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from =null) {2938 protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null) { 2805 2939 if (!empty($this->action_function) && is_callable($this->action_function)) { 2806 2940 $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); 2807 2941 call_user_func_array($this->action_function, $params); … … 2822 2956 $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n"; 2823 2957 return $errorMsg; 2824 2958 } 2825 } 2826 ?> 2959 } 2960 No newline at end of file