Ticket #28909: 28909.2.diff
File 28909.2.diff, 117.9 KB (added by , 10 years ago) |
---|
-
src/wp-includes/class-phpmailer.php
diff --git a/src/wp-includes/class-phpmailer.php b/src/wp-includes/class-phpmailer.php index c38632a..059ec28 100644
a b 1 1 <?php 2 2 /** 3 3 * PHPMailer - PHP email creation and transport class. 4 * PHP Version 5.0.0 5 * Version 5.2.7 4 * PHP Version 5 6 5 * @package PHPMailer 7 * @link https://github.com/PHPMailer/PHPMailer/ 8 * @author Marcus Bointon ( coolbru) <phpmailer@synchromedia.co.uk>6 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project 7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 9 8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 10 9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 11 10 * @author Brent R. Matzelle (original founder) 12 * @copyright 201 3Marcus Bointon11 * @copyright 2012 - 2014 Marcus Bointon 13 12 * @copyright 2010 - 2012 Jim Jagielski 14 13 * @copyright 2004 - 2009 Andy Prevost 15 14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License … … 18 17 * FITNESS FOR A PARTICULAR PURPOSE. 19 18 */ 20 19 21 if (version_compare(PHP_VERSION, '5.0.0', '<')) {22 exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n");23 }24 25 20 /** 26 21 * PHPMailer - PHP email creation and transport class. 27 * PHP Version 5.0.028 22 * @package PHPMailer 29 * @author Marcus Bointon ( coolbru) <phpmailer@synchromedia.co.uk>23 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 30 24 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 31 25 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 32 26 * @author Brent R. Matzelle (original founder) 33 * @copyright 2013 Marcus Bointon34 * @copyright 2010 - 2012 Jim Jagielski35 * @copyright 2004 - 2009 Andy Prevost36 27 */ 37 28 class PHPMailer 38 29 { … … class PHPMailer 40 31 * The PHPMailer Version number. 41 32 * @type string 42 33 */ 43 public $Version = '5.2. 7';34 public $Version = '5.2.8'; 44 35 45 36 /** 46 37 * Email priority. … … class PHPMailer 97 88 * The Return-Path of the message. 98 89 * If empty, it will be set to either From or Sender. 99 90 * @type string 91 * @deprecated Email senders should never set a return-path header; 92 * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. 93 * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference 100 94 */ 101 95 public $ReturnPath = ''; 102 96 … … class PHPMailer 299 293 300 294 /** 301 295 * SMTP class debug output mode. 302 * Options: 0 = off, 1 = commands, 2 = commands and data 296 * Options: 297 * 0: no output 298 * 1: commands 299 * 2: data and commands 300 * 3: as 2 plus connection status 301 * 4: low level data output 303 302 * @type int 304 303 * @see SMTP::$do_debug 305 304 */ 306 305 public $SMTPDebug = 0; 307 306 308 307 /** 309 * The function/method to use for debugging output. 310 * Options: "echo" or "error_log" 308 * How to handle debug output. 309 * Options: 310 * 'echo': Output plain-text as-is, appropriate for CLI 311 * 'html': Output escaped, line breaks converted to <br>, appropriate for browser output 312 * 'error_log': Output to error log as configured in php.ini 311 313 * @type string 312 314 * @see SMTP::$Debugoutput 313 315 */ 314 public $Debugoutput = "echo";316 public $Debugoutput = 'echo'; 315 317 316 318 /** 317 319 * Whether to keep SMTP connection open after each message. … … class PHPMailer 339 341 * Whether to generate VERP addresses on send. 340 342 * Only applicable when sending via SMTP. 341 343 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 344 * @link http://www.postfix.org/VERP_README.html Postfix VERP info 342 345 * @type bool 343 346 */ 344 347 public $do_verp = false; … … class PHPMailer 396 399 * The function that handles the result of the send email action. 397 400 * It is called out by send() for each email sent. 398 401 * 399 * Value can be: 400 * - 'function_name' for function names 401 * - 'Class::Method' for static method calls 402 * - array($object, 'Method') for calling methods on $object 403 * See http://php.net/is_callable manual page for more details. 402 * Value can be any php callable: http://www.php.net/is_callable 404 403 * 405 404 * Parameters: 406 405 * bool $result result of the send action … … class PHPMailer 410 409 * string $subject the subject 411 410 * string $body the email body 412 411 * string $from email address of sender 413 *414 412 * @type string 415 413 */ 416 414 public $action_function = ''; … … class PHPMailer 597 595 */ 598 596 private function mailPassthru($to, $subject, $body, $header, $params) 599 597 { 598 //Check overloading of mail function to avoid double-encoding 599 if (ini_get('mbstring.func_overload') & 1) { 600 $subject = $this->secureHeader($subject); 601 } else { 602 $subject = $this->encodeHeader($this->secureHeader($subject)); 603 } 600 604 if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { 601 $r t = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header);605 $result = @mail($to, $subject, $body, $header); 602 606 } else { 603 $r t = @mail($to, $this->encodeHeader($this->secureHeader($subject)), $body, $header, $params);607 $result = @mail($to, $subject, $body, $header, $params); 604 608 } 605 return $r t;609 return $result; 606 610 } 607 611 608 612 /** … … class PHPMailer 627 631 break; 628 632 case 'echo': 629 633 default: 630 //Just echoes exactly what was received 631 echo $str; 634 echo $str."\n"; 632 635 } 633 636 } 634 637 … … class PHPMailer 670 673 */ 671 674 public function isSendmail() 672 675 { 673 if (!stristr(ini_get('sendmail_path'), 'sendmail')) { 674 $this->Sendmail = '/var/qmail/bin/sendmail'; 676 $ini_sendmail_path = ini_get('sendmail_path'); 677 678 if (!stristr($ini_sendmail_path, 'sendmail')) { 679 $this->Sendmail = '/usr/sbin/sendmail'; 680 } else { 681 $this->Sendmail = $ini_sendmail_path; 675 682 } 676 683 $this->Mailer = 'sendmail'; 677 684 } … … class PHPMailer 682 689 */ 683 690 public function isQmail() 684 691 { 685 if (stristr(ini_get('sendmail_path'), 'qmail')) { 686 $this->Sendmail = '/var/qmail/bin/sendmail'; 692 $ini_sendmail_path = ini_get('sendmail_path'); 693 694 if (!stristr($ini_sendmail_path, 'qmail')) { 695 $this->Sendmail = '/var/qmail/bin/qmail-inject'; 696 } else { 697 $this->Sendmail = $ini_sendmail_path; 687 698 } 688 $this->Mailer = ' sendmail';699 $this->Mailer = 'qmail'; 689 700 } 690 701 691 702 /** … … class PHPMailer 748 759 { 749 760 if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { 750 761 $this->setError($this->lang('Invalid recipient array') . ': ' . $kind); 762 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind); 751 763 if ($this->exceptions) { 752 764 throw new phpmailerException('Invalid recipient array: ' . $kind); 753 765 } 754 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);755 766 return false; 756 767 } 757 768 $address = trim($address); 758 769 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 759 770 if (!$this->validateAddress($address)) { 760 771 $this->setError($this->lang('invalid_address') . ': ' . $address); 772 $this->edebug($this->lang('invalid_address') . ': ' . $address); 761 773 if ($this->exceptions) { 762 774 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); 763 775 } 764 $this->edebug($this->lang('invalid_address') . ': ' . $address);765 776 return false; 766 777 } 767 778 if ($kind != 'Reply-To') { … … class PHPMailer 793 804 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 794 805 if (!$this->validateAddress($address)) { 795 806 $this->setError($this->lang('invalid_address') . ': ' . $address); 807 $this->edebug($this->lang('invalid_address') . ': ' . $address); 796 808 if ($this->exceptions) { 797 809 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); 798 810 } 799 $this->edebug($this->lang('invalid_address') . ': ' . $address);800 811 return false; 801 812 } 802 813 $this->From = $address; … … class PHPMailer 825 836 * Check that a string looks like an email address. 826 837 * @param string $address The email address to check 827 838 * @param string $patternselect A selector for the validation pattern to use : 828 * 'auto' - pick best one automatically; 829 * 'pcre8' - use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; 830 * 'pcre' - use old PCRE implementation; 831 * 'php' - use PHP built-in FILTER_VALIDATE_EMAIL; faster, less thorough; 832 * 'noregex' - super fast, really dumb. 839 * * `auto` Pick strictest one automatically; 840 * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; 841 * * `pcre` Use old PCRE implementation; 842 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains; 843 * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. 844 * * `noregex` Don't use a regex: super fast, really dumb. 833 845 * @return bool 834 846 * @static 835 847 * @access public 836 848 */ 837 849 public static function validateAddress($address, $patternselect = 'auto') 838 850 { 839 if ($patternselect == 'auto') { 840 if (defined( 841 'PCRE_VERSION' 842 ) 843 ) { //Check this instead of extension_loaded so it works when that function is disabled 851 if (!$patternselect or $patternselect == 'auto') { 852 if (defined('PCRE_VERSION')) { //Check this constant so it works when extension_loaded() is disabled 844 853 if (version_compare(PCRE_VERSION, '8.0') >= 0) { 845 854 $patternselect = 'pcre8'; 846 855 } else { … … class PHPMailer 858 867 switch ($patternselect) { 859 868 case 'pcre8': 860 869 /** 861 * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is 862 * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to 863 * not allow a@b type valid addresses :( 870 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. 864 871 * @link http://squiloople.com/2009/12/20/email-address-validation/ 865 872 * @copyright 2009-2010 Michael Rushton 866 873 * Feel free to use and redistribute this code. But please keep this copyright notice. … … class PHPMailer 894 901 $address 895 902 ); 896 903 break; 904 case 'html5': 905 /** 906 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. 907 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) 908 */ 909 return (bool)preg_match('/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . 910 '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', $address); 911 break; 897 912 case 'php': 898 913 default: 899 914 return (bool)filter_var($address, FILTER_VALIDATE_EMAIL); … … class PHPMailer 911 926 /** 912 927 * Create a message and send it. 913 928 * Uses the sending method specified by $Mailer. 914 * Returns false on error - Use the ErrorInfo variable to view description of the error.915 929 * @throws phpmailerException 916 * @return bool 930 * @return bool false on error - See the ErrorInfo property for details of the error. 917 931 */ 918 932 public function send() 919 933 { … … class PHPMailer 922 936 return false; 923 937 } 924 938 return $this->postSend(); 925 } catch (phpmailerException $e ) {939 } catch (phpmailerException $exc) { 926 940 $this->mailHeader = ''; 927 $this->setError($e ->getMessage());941 $this->setError($exc->getMessage()); 928 942 if ($this->exceptions) { 929 throw $e ;943 throw $exc; 930 944 } 931 945 return false; 932 946 } … … class PHPMailer 940 954 public function preSend() 941 955 { 942 956 try { 943 $this->mailHeader = "";957 $this->mailHeader = ''; 944 958 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { 945 959 throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); 946 960 } … … class PHPMailer 964 978 // an extra header list which createHeader() doesn't fold in 965 979 if ($this->Mailer == 'mail') { 966 980 if (count($this->to) > 0) { 967 $this->mailHeader .= $this->addrAppend( "To", $this->to);981 $this->mailHeader .= $this->addrAppend('To', $this->to); 968 982 } else { 969 $this->mailHeader .= $this->headerLine( "To", "undisclosed-recipients:;");983 $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;'); 970 984 } 971 985 $this->mailHeader .= $this->headerLine( 972 986 'Subject', … … class PHPMailer 990 1004 } 991 1005 return true; 992 1006 993 } catch (phpmailerException $e ) {994 $this->setError($e ->getMessage());1007 } catch (phpmailerException $exc) { 1008 $this->setError($exc->getMessage()); 995 1009 if ($this->exceptions) { 996 throw $e ;1010 throw $exc; 997 1011 } 998 1012 return false; 999 1013 } … … class PHPMailer 1011 1025 // Choose the mailer and send through it 1012 1026 switch ($this->Mailer) { 1013 1027 case 'sendmail': 1028 case 'qmail': 1014 1029 return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody); 1015 1030 case 'smtp': 1016 1031 return $this->smtpSend($this->MIMEHeader, $this->MIMEBody); 1017 1032 case 'mail': 1018 1033 return $this->mailSend($this->MIMEHeader, $this->MIMEBody); 1019 1034 default: 1035 $sendMethod = $this->Mailer.'Send'; 1036 if (method_exists($this, $sendMethod)) { 1037 return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); 1038 } 1039 1020 1040 return $this->mailSend($this->MIMEHeader, $this->MIMEBody); 1021 1041 } 1022 } catch (phpmailerException $e) { 1023 $this->setError($e->getMessage()); 1042 } catch (phpmailerException $exc) { 1043 $this->setError($exc->getMessage()); 1044 $this->edebug($exc->getMessage()); 1024 1045 if ($this->exceptions) { 1025 throw $e ;1046 throw $exc; 1026 1047 } 1027 $this->edebug($e->getMessage() . "\n");1028 1048 } 1029 1049 return false; 1030 1050 } … … class PHPMailer 1041 1061 protected function sendmailSend($header, $body) 1042 1062 { 1043 1063 if ($this->Sender != '') { 1044 $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1064 if ($this->Mailer == 'qmail') { 1065 $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1066 } else { 1067 $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 1068 } 1045 1069 } else { 1046 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); 1070 if ($this->Mailer == 'qmail') { 1071 $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); 1072 } else { 1073 $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); 1074 } 1047 1075 } 1048 1076 if ($this->SingleTo === true) { 1049 1077 foreach ($this->SingleToArray as $val) { 1050 1078 if (!@$mail = popen($sendmail, 'w')) { 1051 1079 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 1052 1080 } 1053 fputs($mail, "To: ". $val . "\n");1081 fputs($mail, 'To: ' . $val . "\n"); 1054 1082 fputs($mail, $header); 1055 1083 fputs($mail, $body); 1056 1084 $result = pclose($mail); … … class PHPMailer 1090 1118 protected function mailSend($header, $body) 1091 1119 { 1092 1120 $toArr = array(); 1093 foreach ($this->to as $t ) {1094 $toArr[] = $this->addrFormat($t );1121 foreach ($this->to as $toaddr) { 1122 $toArr[] = $this->addrFormat($toaddr); 1095 1123 } 1096 1124 $to = implode(', ', $toArr); 1097 1125 1098 1126 if (empty($this->Sender)) { 1099 $params = " ";1127 $params = ' '; 1100 1128 } else { 1101 $params = sprintf( "-f%s", $this->Sender);1129 $params = sprintf('-f%s', $this->Sender); 1102 1130 } 1103 1131 if ($this->Sender != '' and !ini_get('safe_mode')) { 1104 1132 $old_from = ini_get('sendmail_from'); 1105 1133 ini_set('sendmail_from', $this->Sender); 1106 1134 } 1107 $r t = false;1135 $result = false; 1108 1136 if ($this->SingleTo === true && count($toArr) > 1) { 1109 1137 foreach ($toArr as $val) { 1110 $r t = $this->mailPassthru($val, $this->Subject, $body, $header, $params);1138 $result = $this->mailPassthru($val, $this->Subject, $body, $header, $params); 1111 1139 // implement call back function if it exists 1112 $isSent = ($r t == 1) ? 1 : 0;1140 $isSent = ($result == 1) ? 1 : 0; 1113 1141 $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1114 1142 } 1115 1143 } else { 1116 $r t = $this->mailPassthru($to, $this->Subject, $body, $header, $params);1144 $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); 1117 1145 // implement call back function if it exists 1118 $isSent = ($r t == 1) ? 1 : 0;1146 $isSent = ($result == 1) ? 1 : 0; 1119 1147 $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1120 1148 } 1121 1149 if (isset($old_from)) { 1122 1150 ini_set('sendmail_from', $old_from); 1123 1151 } 1124 if (!$r t) {1152 if (!$result) { 1125 1153 throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); 1126 1154 } 1127 1155 return true; … … class PHPMailer 1135 1163 public function getSMTPInstance() 1136 1164 { 1137 1165 if (!is_object($this->smtp)) { 1138 1166 require_once 'class-smtp.php'; 1139 1167 $this->smtp = new SMTP; 1140 1168 } 1141 1169 return $this->smtp; … … class PHPMailer 1166 1194 throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); 1167 1195 } 1168 1196 1169 // Attempt to send attachall recipients1197 // Attempt to send to all recipients 1170 1198 foreach ($this->to as $to) { 1171 1199 if (!$this->smtp->recipient($to[0])) { 1172 1200 $bad_rcpt[] = $to[0]; … … class PHPMailer 1195 1223 $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body, $this->From); 1196 1224 } 1197 1225 1198 if (count($bad_rcpt) > 0) { //Create error message for any bad addresses 1199 throw new phpmailerException($this->lang('recipients_failed') . implode(', ', $bad_rcpt)); 1200 } 1201 if (!$this->smtp->data($header . $body)) { 1226 //Only send the DATA command if we have viable recipients 1227 if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { 1202 1228 throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); 1203 1229 } 1204 1230 if ($this->SMTPKeepAlive == true) { … … class PHPMailer 1207 1233 $this->smtp->quit(); 1208 1234 $this->smtp->close(); 1209 1235 } 1236 if (count($bad_rcpt) > 0) { //Create error message for any bad addresses 1237 throw new phpmailerException( 1238 $this->lang('recipients_failed') . implode(', ', $bad_rcpt), 1239 self::STOP_CONTINUE 1240 ); 1241 } 1210 1242 return true; 1211 1243 } 1212 1244 … … class PHPMailer 1234 1266 $this->smtp->setDebugLevel($this->SMTPDebug); 1235 1267 $this->smtp->setDebugOutput($this->Debugoutput); 1236 1268 $this->smtp->setVerp($this->do_verp); 1237 $tls = ($this->SMTPSecure == 'tls');1238 $ssl = ($this->SMTPSecure == 'ssl');1239 1269 $hosts = explode(';', $this->Host); 1240 1270 $lastexception = null; 1241 1271 1242 1272 foreach ($hosts as $hostentry) { 1243 1273 $hostinfo = array(); 1244 $host = $hostentry; 1274 if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { 1275 //Not a valid host entry 1276 continue; 1277 } 1278 //$hostinfo[2]: optional ssl or tls prefix 1279 //$hostinfo[3]: the hostname 1280 //$hostinfo[4]: optional port number 1281 //The host string prefix can temporarily override the current setting for SMTPSecure 1282 //If it's not specified, the default value is used 1283 $prefix = ''; 1284 $tls = ($this->SMTPSecure == 'tls'); 1285 if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) { 1286 $prefix = 'ssl://'; 1287 $tls = false; //Can't have SSL and TLS at once 1288 } elseif ($hostinfo[2] == 'tls') { 1289 $tls = true; 1290 //tls doesn't use a prefix 1291 } 1292 $host = $hostinfo[3]; 1245 1293 $port = $this->Port; 1246 if (preg_match( 1247 '/^(.+):([0-9]+)$/', 1248 $hostentry, 1249 $hostinfo 1250 ) 1251 ) { //If $hostentry contains 'address:port', override default 1252 $host = $hostinfo[1]; 1253 $port = $hostinfo[2]; 1294 $tport = (integer)$hostinfo[4]; 1295 if ($tport > 0 and $tport < 65536) { 1296 $port = $tport; 1254 1297 } 1255 if ($this->smtp->connect( ($ssl ? 'ssl://' : ''). $host, $port, $this->Timeout, $options)) {1298 if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { 1256 1299 try { 1257 1300 if ($this->Helo) { 1258 1301 $hello = $this->Helo; … … class PHPMailer 1281 1324 } 1282 1325 } 1283 1326 return true; 1284 } catch (phpmailerException $e ) {1285 $lastexception = $e ;1327 } catch (phpmailerException $exc) { 1328 $lastexception = $exc; 1286 1329 //We must have connected, but then failed TLS or Auth, so close connection nicely 1287 1330 $this->smtp->quit(); 1288 1331 } … … class PHPMailer 1320 1363 * @return bool 1321 1364 * @access public 1322 1365 */ 1323 public function setLanguage($langcode = 'en', $lang_path = ' language/')1366 public function setLanguage($langcode = 'en', $lang_path = '') 1324 1367 { 1325 //Define full set of translatable strings 1368 //Define full set of translatable strings in English 1326 1369 $PHPMAILER_LANG = array( 1327 1370 'authenticate' => 'SMTP Error: Could not authenticate.', 1328 1371 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', … … class PHPMailer 1343 1386 'smtp_error' => 'SMTP server error: ', 1344 1387 'variable_set' => 'Cannot set or reset variable: ' 1345 1388 ); 1346 //Overwrite language-specific strings. 1347 //This way we'll never have missing translations - no more "language string failed to load"! 1348 $l = true; 1389 if (empty($lang_path)) { 1390 //Calculate an absolute path so it can work if CWD is not here 1391 $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; 1392 } 1393 $foundlang = true; 1394 $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php'; 1349 1395 if ($langcode != 'en') { //There is no English translation file 1350 $l = @include $lang_path . 'phpmailer.lang-' . $langcode . '.php'; 1396 //Make sure language file path is readable 1397 if (!is_readable($lang_file)) { 1398 $foundlang = false; 1399 } else { 1400 //Overwrite language-specific strings. 1401 //This way we'll never have missing translations. 1402 $foundlang = include $lang_file; 1403 } 1351 1404 } 1352 1405 $this->language = $PHPMAILER_LANG; 1353 return ($ l== true); //Returns false if language not found1406 return ($foundlang == true); //Returns false if language not found 1354 1407 } 1355 1408 1356 1409 /** … … class PHPMailer 1375 1428 public function addrAppend($type, $addr) 1376 1429 { 1377 1430 $addresses = array(); 1378 foreach ($addr as $a ) {1379 $addresses[] = $this->addrFormat($a );1431 foreach ($addr as $address) { 1432 $addresses[] = $this->addrFormat($address); 1380 1433 } 1381 1434 return $type . ': ' . implode(', ', $addresses) . $this->LE; 1382 1435 } … … class PHPMailer 1393 1446 if (empty($addr[1])) { // No name provided 1394 1447 return $this->secureHeader($addr[0]); 1395 1448 } else { 1396 return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . " <". $this->secureHeader(1449 return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( 1397 1450 $addr[0] 1398 ) . ">";1451 ) . '>'; 1399 1452 } 1400 1453 } 1401 1454 … … class PHPMailer 1412 1465 */ 1413 1466 public function wrapText($message, $length, $qp_mode = false) 1414 1467 { 1415 $soft_break = ($qp_mode) ? sprintf( " =%s", $this->LE) : $this->LE;1468 $soft_break = ($qp_mode) ? sprintf(' =%s', $this->LE) : $this->LE; 1416 1469 // If utf-8 encoding is used, we will need to make sure we don't 1417 1470 // split multibyte characters when we wrap 1418 $is_utf8 = (strtolower($this->CharSet) == "utf-8");1471 $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); 1419 1472 $lelen = strlen($this->LE); 1420 1473 $crlflen = strlen(self::CRLF); 1421 1474 … … class PHPMailer 1438 1491 $len = $space_left; 1439 1492 if ($is_utf8) { 1440 1493 $len = $this->utf8CharBoundary($word, $len); 1441 } elseif (substr($word, $len - 1, 1) == "=") {1494 } elseif (substr($word, $len - 1, 1) == '=') { 1442 1495 $len--; 1443 } elseif (substr($word, $len - 2, 1) == "=") {1496 } elseif (substr($word, $len - 2, 1) == '=') { 1444 1497 $len -= 2; 1445 1498 } 1446 1499 $part = substr($word, 0, $len); 1447 1500 $word = substr($word, $len); 1448 1501 $buf .= ' ' . $part; 1449 $message .= $buf . sprintf( "=%s", self::CRLF);1502 $message .= $buf . sprintf('=%s', self::CRLF); 1450 1503 } else { 1451 1504 $message .= $buf . $soft_break; 1452 1505 } … … class PHPMailer 1459 1512 $len = $length; 1460 1513 if ($is_utf8) { 1461 1514 $len = $this->utf8CharBoundary($word, $len); 1462 } elseif (substr($word, $len - 1, 1) == "=") {1515 } elseif (substr($word, $len - 1, 1) == '=') { 1463 1516 $len--; 1464 } elseif (substr($word, $len - 2, 1) == "=") {1517 } elseif (substr($word, $len - 2, 1) == '=') { 1465 1518 $len -= 2; 1466 1519 } 1467 1520 $part = substr($word, 0, $len); 1468 1521 $word = substr($word, $len); 1469 1522 1470 1523 if (strlen($word) > 0) { 1471 $message .= $part . sprintf( "=%s", self::CRLF);1524 $message .= $part . sprintf('=%s', self::CRLF); 1472 1525 } else { 1473 1526 $buf = $part; 1474 1527 } … … class PHPMailer 1504 1557 $lookBack = 3; 1505 1558 while (!$foundSplitPos) { 1506 1559 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); 1507 $encodedCharPos = strpos($lastChunk, "=");1560 $encodedCharPos = strpos($lastChunk, '='); 1508 1561 if ($encodedCharPos !== false) { 1509 1562 // Found start of encoded character byte within $lookBack block. 1510 1563 // Check the encoded byte value (the 2 chars after the '=') … … class PHPMailer 1531 1584 return $maxLength; 1532 1585 } 1533 1586 1534 1535 1587 /** 1536 1588 * Set the body wrapping. 1537 1589 * @access public … … class PHPMailer 1572 1624 $this->boundary[3] = 'b3_' . $uniq_id; 1573 1625 1574 1626 if ($this->MessageDate == '') { 1575 $result .= $this->headerLine('Date', self::rfcDate()); 1576 } else { 1577 $result .= $this->headerLine('Date', $this->MessageDate); 1627 $this->MessageDate = self::rfcDate(); 1578 1628 } 1629 $result .= $this->headerLine('Date', $this->MessageDate); 1579 1630 1580 if ($this->ReturnPath) {1581 $result .= $this->headerLine('Return-Path', '<' . trim($this->ReturnPath) . '>');1582 } elseif ($this->Sender == '') {1583 $result .= $this->headerLine('Return-Path', '<' . trim($this->From) . '>');1584 } else {1585 $result .= $this->headerLine('Return-Path', '<' . trim($this->Sender) . '>');1586 }1587 1631 1588 1632 // To be created automatically by mail() 1589 if ($this-> Mailer != 'mail') {1590 if ($this-> SingleTo === true) {1591 foreach ($this->to as $t ) {1592 $this->SingleToArray[] = $this->addrFormat($t );1633 if ($this->SingleTo === true) { 1634 if ($this->Mailer != 'mail') { 1635 foreach ($this->to as $toaddr) { 1636 $this->SingleToArray[] = $this->addrFormat($toaddr); 1593 1637 } 1594 } else { 1595 if (count($this->to) > 0) { 1638 } 1639 } else { 1640 if (count($this->to) > 0) { 1641 if ($this->Mailer != 'mail') { 1596 1642 $result .= $this->addrAppend('To', $this->to); 1597 } elseif (count($this->cc) == 0) {1598 $result .= $this->headerLine('To', 'undisclosed-recipients:;');1599 1643 } 1644 } elseif (count($this->cc) == 0) { 1645 $result .= $this->headerLine('To', 'undisclosed-recipients:;'); 1600 1646 } 1601 1647 } 1602 1648 … … class PHPMailer 1608 1654 } 1609 1655 1610 1656 // sendmail and mail() extract Bcc from the header before sending 1611 if ((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { 1657 if (( 1658 $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail' 1659 ) 1660 and count($this->bcc) > 0 1661 ) { 1612 1662 $result .= $this->addrAppend('Bcc', $this->bcc); 1613 1663 } 1614 1664 … … class PHPMailer 1624 1674 if ($this->MessageID != '') { 1625 1675 $this->lastMessageID = $this->MessageID; 1626 1676 } else { 1627 $this->lastMessageID = sprintf( "<%s@%s>", $uniq_id, $this->ServerHostname());1677 $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname()); 1628 1678 } 1629 1679 $result .= $this->HeaderLine('Message-ID', $this->lastMessageID); 1630 1680 $result .= $this->headerLine('X-Priority', $this->Priority); … … class PHPMailer 1667 1717 public function getMailMIME() 1668 1718 { 1669 1719 $result = ''; 1720 $ismultipart = true; 1670 1721 switch ($this->message_type) { 1671 1722 case 'inline': 1672 1723 $result .= $this->headerLine('Content-Type', 'multipart/related;'); … … class PHPMailer 1687 1738 default: 1688 1739 // Catches case 'plain': and case '': 1689 1740 $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet); 1741 $ismultipart = false; 1690 1742 break; 1691 1743 } 1692 1744 //RFC1341 part 5 says 7bit is assumed if not specified 1693 1745 if ($this->Encoding != '7bit') { 1694 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); 1746 //RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE 1747 if ($ismultipart) { 1748 if ($this->Encoding == '8bit') { 1749 $result .= $this->headerLine('Content-Transfer-Encoding', '8bit'); 1750 } 1751 //The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible 1752 } else { 1753 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); 1754 } 1695 1755 } 1696 1756 1697 1757 if ($this->Mailer != 'mail') { … … class PHPMailer 1704 1764 /** 1705 1765 * Returns the whole MIME message. 1706 1766 * Includes complete headers and body. 1707 * Only valid post PreSend().1708 * @see PHPMailer:: PreSend()1767 * Only valid post preSend(). 1768 * @see PHPMailer::preSend() 1709 1769 * @access public 1710 1770 * @return string 1711 1771 */ … … class PHPMailer 1732 1792 1733 1793 $this->setWordWrap(); 1734 1794 1795 $bodyEncoding = $this->Encoding; 1796 $bodyCharSet = $this->CharSet; 1797 if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { 1798 $bodyEncoding = '7bit'; 1799 $bodyCharSet = 'us-ascii'; 1800 } 1801 $altBodyEncoding = $this->Encoding; 1802 $altBodyCharSet = $this->CharSet; 1803 if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { 1804 $altBodyEncoding = '7bit'; 1805 $altBodyCharSet = 'us-ascii'; 1806 } 1735 1807 switch ($this->message_type) { 1736 1808 case 'inline': 1737 $body .= $this->getBoundary($this->boundary[1], '', '', '');1738 $body .= $this->encodeString($this->Body, $ this->Encoding);1809 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); 1810 $body .= $this->encodeString($this->Body, $bodyEncoding); 1739 1811 $body .= $this->LE . $this->LE; 1740 1812 $body .= $this->attachAll('inline', $this->boundary[1]); 1741 1813 break; 1742 1814 case 'attach': 1743 $body .= $this->getBoundary($this->boundary[1], '', '', '');1744 $body .= $this->encodeString($this->Body, $ this->Encoding);1815 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); 1816 $body .= $this->encodeString($this->Body, $bodyEncoding); 1745 1817 $body .= $this->LE . $this->LE; 1746 1818 $body .= $this->attachAll('attachment', $this->boundary[1]); 1747 1819 break; … … class PHPMailer 1750 1822 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1751 1823 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1752 1824 $body .= $this->LE; 1753 $body .= $this->getBoundary($this->boundary[2], '', '', '');1754 $body .= $this->encodeString($this->Body, $ this->Encoding);1825 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding); 1826 $body .= $this->encodeString($this->Body, $bodyEncoding); 1755 1827 $body .= $this->LE . $this->LE; 1756 1828 $body .= $this->attachAll('inline', $this->boundary[2]); 1757 1829 $body .= $this->LE; 1758 1830 $body .= $this->attachAll('attachment', $this->boundary[1]); 1759 1831 break; 1760 1832 case 'alt': 1761 $body .= $this->getBoundary($this->boundary[1], '', 'text/plain', '');1762 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1833 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1834 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1763 1835 $body .= $this->LE . $this->LE; 1764 $body .= $this->getBoundary($this->boundary[1], '', 'text/html', '');1765 $body .= $this->encodeString($this->Body, $ this->Encoding);1836 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding); 1837 $body .= $this->encodeString($this->Body, $bodyEncoding); 1766 1838 $body .= $this->LE . $this->LE; 1767 1839 if (!empty($this->Ical)) { 1768 1840 $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); … … class PHPMailer 1772 1844 $body .= $this->endBoundary($this->boundary[1]); 1773 1845 break; 1774 1846 case 'alt_inline': 1775 $body .= $this->getBoundary($this->boundary[1], '', 'text/plain', '');1776 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1847 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1848 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1777 1849 $body .= $this->LE . $this->LE; 1778 1850 $body .= $this->textLine('--' . $this->boundary[1]); 1779 1851 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1780 1852 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1781 1853 $body .= $this->LE; 1782 $body .= $this->getBoundary($this->boundary[2], '', 'text/html', '');1783 $body .= $this->encodeString($this->Body, $ this->Encoding);1854 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); 1855 $body .= $this->encodeString($this->Body, $bodyEncoding); 1784 1856 $body .= $this->LE . $this->LE; 1785 1857 $body .= $this->attachAll('inline', $this->boundary[2]); 1786 1858 $body .= $this->LE; … … class PHPMailer 1791 1863 $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); 1792 1864 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1793 1865 $body .= $this->LE; 1794 $body .= $this->getBoundary($this->boundary[2], '', 'text/plain', '');1795 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1866 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1867 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1796 1868 $body .= $this->LE . $this->LE; 1797 $body .= $this->getBoundary($this->boundary[2], '', 'text/html', '');1798 $body .= $this->encodeString($this->Body, $ this->Encoding);1869 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); 1870 $body .= $this->encodeString($this->Body, $bodyEncoding); 1799 1871 $body .= $this->LE . $this->LE; 1800 1872 $body .= $this->endBoundary($this->boundary[2]); 1801 1873 $body .= $this->LE; … … class PHPMailer 1806 1878 $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); 1807 1879 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); 1808 1880 $body .= $this->LE; 1809 $body .= $this->getBoundary($this->boundary[2], '', 'text/plain', '');1810 $body .= $this->encodeString($this->AltBody, $ this->Encoding);1881 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); 1882 $body .= $this->encodeString($this->AltBody, $altBodyEncoding); 1811 1883 $body .= $this->LE . $this->LE; 1812 1884 $body .= $this->textLine('--' . $this->boundary[2]); 1813 1885 $body .= $this->headerLine('Content-Type', 'multipart/related;'); 1814 1886 $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"'); 1815 1887 $body .= $this->LE; 1816 $body .= $this->getBoundary($this->boundary[3], '', 'text/html', '');1817 $body .= $this->encodeString($this->Body, $ this->Encoding);1888 $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding); 1889 $body .= $this->encodeString($this->Body, $bodyEncoding); 1818 1890 $body .= $this->LE . $this->LE; 1819 1891 $body .= $this->attachAll('inline', $this->boundary[3]); 1820 1892 $body .= $this->LE; … … class PHPMailer 1824 1896 break; 1825 1897 default: 1826 1898 // catch case 'plain' and case '' 1827 $body .= $this->encodeString($this->Body, $ this->Encoding);1899 $body .= $this->encodeString($this->Body, $bodyEncoding); 1828 1900 break; 1829 1901 } 1830 1902 … … class PHPMailer 1835 1907 if (!defined('PKCS7_TEXT')) { 1836 1908 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); 1837 1909 } 1910 //TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 1838 1911 $file = tempnam(sys_get_temp_dir(), 'mail'); 1839 1912 file_put_contents($file, $body); //TODO check this worked 1840 1913 $signed = tempnam(sys_get_temp_dir(), 'signed'); … … class PHPMailer 1854 1927 @unlink($signed); 1855 1928 throw new phpmailerException($this->lang('signing') . openssl_error_string()); 1856 1929 } 1857 } catch (phpmailerException $e ) {1930 } catch (phpmailerException $exc) { 1858 1931 $body = ''; 1859 1932 if ($this->exceptions) { 1860 throw $e ;1933 throw $exc; 1861 1934 } 1862 1935 } 1863 1936 } … … class PHPMailer 1886 1959 $encoding = $this->Encoding; 1887 1960 } 1888 1961 $result .= $this->textLine('--' . $boundary); 1889 $result .= sprintf( "Content-Type: %s; charset=%s", $contentType, $charSet);1962 $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet); 1890 1963 $result .= $this->LE; 1891 $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); 1964 //RFC1341 part 5 says 7bit is assumed if not specified 1965 if ($encoding != '7bit') { 1966 $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); 1967 } 1892 1968 $result .= $this->LE; 1893 1969 1894 1970 return $result; … … class PHPMailer 1916 1992 { 1917 1993 $this->message_type = array(); 1918 1994 if ($this->alternativeExists()) { 1919 $this->message_type[] = "alt";1995 $this->message_type[] = 'alt'; 1920 1996 } 1921 1997 if ($this->inlineImageExists()) { 1922 $this->message_type[] = "inline";1998 $this->message_type[] = 'inline'; 1923 1999 } 1924 2000 if ($this->attachmentExists()) { 1925 $this->message_type[] = "attach";2001 $this->message_type[] = 'attach'; 1926 2002 } 1927 $this->message_type = implode( "_", $this->message_type);1928 if ($this->message_type == "") {1929 $this->message_type = "plain";2003 $this->message_type = implode('_', $this->message_type); 2004 if ($this->message_type == '') { 2005 $this->message_type = 'plain'; 1930 2006 } 1931 2007 } 1932 2008 … … class PHPMailer 1992 2068 7 => 0 1993 2069 ); 1994 2070 1995 } catch (phpmailerException $e) { 1996 $this->setError($e->getMessage()); 2071 } catch (phpmailerException $exc) { 2072 $this->setError($exc->getMessage()); 2073 $this->edebug($exc->getMessage()); 1997 2074 if ($this->exceptions) { 1998 throw $e ;2075 throw $exc; 1999 2076 } 2000 $this->edebug($e->getMessage() . "\n");2001 2077 return false; 2002 2078 } 2003 2079 return true; … … class PHPMailer 2056 2132 } 2057 2133 $cidUniq[$cid] = true; 2058 2134 2059 $mime[] = sprintf( "--%s%s", $boundary, $this->LE);2135 $mime[] = sprintf('--%s%s', $boundary, $this->LE); 2060 2136 $mime[] = sprintf( 2061 "Content-Type: %s; name=\"%s\"%s",2137 'Content-Type: %s; name="%s"%s', 2062 2138 $type, 2063 2139 $this->encodeHeader($this->secureHeader($name)), 2064 2140 $this->LE 2065 2141 ); 2066 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); 2142 //RFC1341 part 5 says 7bit is assumed if not specified 2143 if ($encoding != '7bit') { 2144 $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); 2145 } 2067 2146 2068 2147 if ($disposition == 'inline') { 2069 $mime[] = sprintf( "Content-ID: <%s>%s", $cid, $this->LE);2148 $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE); 2070 2149 } 2071 2150 2072 2151 // If a filename contains any of these chars, it should be quoted, … … class PHPMailer 2076 2155 if (!(empty($disposition))) { 2077 2156 if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) { 2078 2157 $mime[] = sprintf( 2079 "Content-Disposition: %s; filename=\"%s\"%s",2158 'Content-Disposition: %s; filename="%s"%s', 2080 2159 $disposition, 2081 2160 $this->encodeHeader($this->secureHeader($name)), 2082 2161 $this->LE . $this->LE 2083 2162 ); 2084 2163 } else { 2085 2164 $mime[] = sprintf( 2086 "Content-Disposition: %s; filename=%s%s",2165 'Content-Disposition: %s; filename=%s%s', 2087 2166 $disposition, 2088 2167 $this->encodeHeader($this->secureHeader($name)), 2089 2168 $this->LE . $this->LE … … class PHPMailer 2110 2189 } 2111 2190 } 2112 2191 2113 $mime[] = sprintf( "--%s--%s", $boundary, $this->LE);2192 $mime[] = sprintf('--%s--%s', $boundary, $this->LE); 2114 2193 2115 return implode( "", $mime);2194 return implode('', $mime); 2116 2195 } 2117 2196 2118 2197 /** … … class PHPMailer 2149 2228 } 2150 2229 } 2151 2230 return $file_buffer; 2152 } catch (Exception $e ) {2153 $this->setError($e ->getMessage());2231 } catch (Exception $exc) { 2232 $this->setError($exc->getMessage()); 2154 2233 return ''; 2155 2234 } 2156 2235 } … … class PHPMailer 2201 2280 */ 2202 2281 public function encodeHeader($str, $position = 'text') 2203 2282 { 2204 $ x= 0;2283 $matchcount = 0; 2205 2284 switch (strtolower($position)) { 2206 2285 case 'phrase': 2207 2286 if (!preg_match('/[\200-\377]/', $str)) { 2208 // Can't use addslashes as we don't know what value hasmagic_quotes_sybase2287 // Can't use addslashes as we don't know the value of magic_quotes_sybase 2209 2288 $encoded = addcslashes($str, "\0..\37\177\\\""); 2210 2289 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { 2211 2290 return ($encoded); … … class PHPMailer 2213 2292 return ("\"$encoded\""); 2214 2293 } 2215 2294 } 2216 $ x= preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);2295 $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); 2217 2296 break; 2218 2297 /** @noinspection PhpMissingBreakStatementInspection */ 2219 2298 case 'comment': 2220 $ x= preg_match_all('/[()"]/', $str, $matches);2299 $matchcount = preg_match_all('/[()"]/', $str, $matches); 2221 2300 // Intentional fall-through 2222 2301 case 'text': 2223 2302 default: 2224 $ x+= preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);2303 $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); 2225 2304 break; 2226 2305 } 2227 2306 2228 if ($ x== 0) { //There are no chars that need encoding2307 if ($matchcount == 0) { //There are no chars that need encoding 2229 2308 return ($str); 2230 2309 } 2231 2310 2232 2311 $maxlen = 75 - 7 - strlen($this->CharSet); 2233 2312 // Try to select the encoding which should produce the shortest output 2234 if ($ x> strlen($str) / 3) {2313 if ($matchcount > strlen($str) / 3) { 2235 2314 //More than a third of the content will need encoding, so B encoding will be most efficient 2236 2315 $encoding = 'B'; 2237 2316 if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) { … … class PHPMailer 2250 2329 $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded)); 2251 2330 } 2252 2331 2253 $encoded = preg_replace('/^(.*)$/m', " =?". $this->CharSet . "?$encoding?\\1?=", $encoded);2332 $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded); 2254 2333 $encoded = trim(str_replace("\n", $this->LE, $encoded)); 2255 2334 2256 2335 return $encoded; … … class PHPMailer 2272 2351 } 2273 2352 2274 2353 /** 2354 * Does a string contain any 8-bit chars (in any charset)? 2355 * @param string $text 2356 * @return bool 2357 */ 2358 public function has8bitChars($text) 2359 { 2360 return (bool)preg_match('/[\x80-\xFF]/', $text); 2361 } 2362 2363 /** 2275 2364 * Encode and wrap long multibyte strings for mail headers 2276 2365 * without breaking lines within a character. 2277 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php 2366 * Adapted from a function by paravoid 2367 * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 2278 2368 * @access public 2279 2369 * @param string $str multi-byte text to wrap encode 2280 * @param string $l fstring to use as linefeed/end-of-line2370 * @param string $linebreak string to use as linefeed/end-of-line 2281 2371 * @return string 2282 2372 */ 2283 public function base64EncodeWrapMB($str, $l f= null)2373 public function base64EncodeWrapMB($str, $linebreak = null) 2284 2374 { 2285 $start = "=?" . $this->CharSet . "?B?";2286 $end = "?=";2287 $encoded = "";2288 if ($l f=== null) {2289 $l f= $this->LE;2375 $start = '=?' . $this->CharSet . '?B?'; 2376 $end = '?='; 2377 $encoded = ''; 2378 if ($linebreak === null) { 2379 $linebreak = $this->LE; 2290 2380 } 2291 2381 2292 2382 $mb_length = mb_strlen($str, $this->CharSet); … … class PHPMailer 2305 2395 $chunk = base64_encode($chunk); 2306 2396 $lookBack++; 2307 2397 } while (strlen($chunk) > $length); 2308 $encoded .= $chunk . $l f;2398 $encoded .= $chunk . $linebreak; 2309 2399 } 2310 2400 2311 2401 // Chomp the last linefeed 2312 $encoded = substr($encoded, 0, -strlen($l f));2402 $encoded = substr($encoded, 0, -strlen($linebreak)); 2313 2403 return $encoded; 2314 2404 } 2315 2405 … … class PHPMailer 2320 2410 * @param string $string The text to encode 2321 2411 * @param integer $line_max Number of chars allowed on a line before wrapping 2322 2412 * @return string 2323 * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#894172413 * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment 2324 2414 */ 2325 2415 public function encodeQP($string, $line_max = 76) 2326 2416 { 2327 2417 if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) 2328 return quoted_printable_encode($string);2418 return $this->fixEOL(quoted_printable_encode($string)); 2329 2419 } 2330 2420 //Fall back to a pure PHP implementation 2331 2421 $string = str_replace( … … class PHPMailer 2334 2424 rawurlencode($string) 2335 2425 ); 2336 2426 $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); 2337 return $ string;2427 return $this->fixEOL($string); 2338 2428 } 2339 2429 2340 2430 /** … … class PHPMailer 2390 2480 if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { 2391 2481 //If the string contains an '=', make sure it's the first thing we replace 2392 2482 //so as to avoid double-encoding 2393 $ s= array_search('=', $matches[0]);2394 if ($ s!== false) {2395 unset($matches[0][$ s]);2483 $eqkey = array_search('=', $matches[0]); 2484 if ($eqkey !== false) { 2485 unset($matches[0][$eqkey]); 2396 2486 array_unshift($matches[0], '='); 2397 2487 } 2398 2488 foreach (array_unique($matches[0]) as $char) { … … class PHPMailer 2680 2770 */ 2681 2771 protected function serverHostname() 2682 2772 { 2773 $result = 'localhost.localdomain'; 2683 2774 if (!empty($this->Hostname)) { 2684 2775 $result = $this->Hostname; 2685 } elseif (isset($_SERVER ['SERVER_NAME'])) {2776 } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { 2686 2777 $result = $_SERVER['SERVER_NAME']; 2687 } else { 2688 $result = 'localhost.localdomain'; 2778 } elseif (function_exists('gethostname') && gethostname() !== false) { 2779 $result = gethostname(); 2780 } elseif (php_uname('n') !== false) { 2781 $result = php_uname('n'); 2689 2782 } 2690 2691 2783 return $result; 2692 2784 } 2693 2785 … … class PHPMailer 2770 2862 */ 2771 2863 public function msgHTML($message, $basedir = '', $advanced = false) 2772 2864 { 2773 preg_match_all( "/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);2865 preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); 2774 2866 if (isset($images[2])) { 2775 foreach ($images[2] as $i => $url) {2867 foreach ($images[2] as $imgindex => $url) { 2776 2868 // do not change urls for absolute images (thanks to corvuscorax) 2777 2869 if (!preg_match('#^[A-z]+://#', $url)) { 2778 2870 $filename = basename($url); … … class PHPMailer 2796 2888 ) 2797 2889 ) { 2798 2890 $message = preg_replace( 2799 "/" . $images[1][$i] . "=[\"']" . preg_quote($url, '/') . "[\"']/Ui",2800 $images[1][$i ] . "=\"cid:" . $cid . "\"",2891 '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', 2892 $images[1][$imgindex] . '="cid:' . $cid . '"', 2801 2893 $message 2802 2894 ); 2803 2895 } … … class PHPMailer 2805 2897 } 2806 2898 } 2807 2899 $this->isHTML(true); 2808 if (empty($this->AltBody)) {2809 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";2810 }2811 2900 //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better 2812 2901 $this->Body = $this->normalizeBreaks($message); 2813 2902 $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); 2903 if (empty($this->AltBody)) { 2904 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . 2905 self::CRLF . self::CRLF; 2906 } 2814 2907 return $this->Body; 2815 2908 } 2816 2909 … … class PHPMailer 2824 2917 { 2825 2918 if ($advanced) { 2826 2919 require_once 'extras/class.html2text.php'; 2827 $h = new html2text($html);2828 return $h ->get_text();2920 $htmlconverter = new html2text($html); 2921 return $htmlconverter->get_text(); 2829 2922 } 2830 2923 return html_entity_decode( 2831 2924 trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), … … class PHPMailer 2920 3013 'txt' => 'text/plain', 2921 3014 'rtx' => 'text/richtext', 2922 3015 'rtf' => 'text/rtf', 3016 'vcf' => 'text/vcard', 3017 'vcard' => 'text/vcard', 2923 3018 'xml' => 'text/xml', 2924 3019 'xsl' => 'text/xml', 2925 3020 'mpeg' => 'video/mpeg', … … class PHPMailer 2966 3061 public static function mb_pathinfo($path, $options = null) 2967 3062 { 2968 3063 $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); 2969 $ m= array();2970 preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $ m);2971 if (array_key_exists(1, $ m)) {2972 $ret['dirname'] = $ m[1];3064 $pathinfo = array(); 3065 preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo); 3066 if (array_key_exists(1, $pathinfo)) { 3067 $ret['dirname'] = $pathinfo[1]; 2973 3068 } 2974 if (array_key_exists(2, $ m)) {2975 $ret['basename'] = $ m[2];3069 if (array_key_exists(2, $pathinfo)) { 3070 $ret['basename'] = $pathinfo[2]; 2976 3071 } 2977 if (array_key_exists(5, $ m)) {2978 $ret['extension'] = $ m[5];3072 if (array_key_exists(5, $pathinfo)) { 3073 $ret['extension'] = $pathinfo[5]; 2979 3074 } 2980 if (array_key_exists(3, $ m)) {2981 $ret['filename'] = $ m[3];3075 if (array_key_exists(3, $pathinfo)) { 3076 $ret['filename'] = $pathinfo[3]; 2982 3077 } 2983 3078 switch ($options) { 2984 3079 case PATHINFO_DIRNAME: … … class PHPMailer 3024 3119 } else { 3025 3120 throw new phpmailerException($this->lang('variable_set') . $name, self::STOP_CRITICAL); 3026 3121 } 3027 } catch (Exception $e ) {3028 $this->setError($e ->getMessage());3029 if ($e ->getCode() == self::STOP_CRITICAL) {3122 } catch (Exception $exc) { 3123 $this->setError($exc->getMessage()); 3124 if ($exc->getCode() == self::STOP_CRITICAL) { 3030 3125 return false; 3031 3126 } 3032 3127 } … … class PHPMailer 3061 3156 3062 3157 3063 3158 /** 3064 * Set the p rivate key fileand password for S/MIME signing.3159 * Set the public and private key files and password for S/MIME signing. 3065 3160 * @access public 3066 3161 * @param string $cert_filename 3067 3162 * @param string $key_filename … … class PHPMailer 3088 3183 if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { 3089 3184 $line .= $txt[$i]; 3090 3185 } else { 3091 $line .= "=" . sprintf("%02X", $ord);3186 $line .= '=' . sprintf('%02X', $ord); 3092 3187 } 3093 3188 } 3094 3189 return $line; … … class PHPMailer 3097 3192 /** 3098 3193 * Generate a DKIM signature. 3099 3194 * @access public 3100 * @param string $s Header3195 * @param string $signheader Header 3101 3196 * @throws phpmailerException 3102 3197 * @return string 3103 3198 */ 3104 public function DKIM_Sign($s )3199 public function DKIM_Sign($signheader) 3105 3200 { 3106 3201 if (!defined('PKCS7_TEXT')) { 3107 3202 if ($this->exceptions) { 3108 throw new phpmailerException($this->lang( "signing") . ' OpenSSL extension missing.');3203 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); 3109 3204 } 3110 3205 return ''; 3111 3206 } … … class PHPMailer 3115 3210 } else { 3116 3211 $privKey = $privKeyStr; 3117 3212 } 3118 if (openssl_sign($s , $signature, $privKey)) {3213 if (openssl_sign($signheader, $signature, $privKey)) { 3119 3214 return base64_encode($signature); 3120 3215 } 3121 3216 return ''; … … class PHPMailer 3124 3219 /** 3125 3220 * Generate a DKIM canonicalization header. 3126 3221 * @access public 3127 * @param string $s Header3222 * @param string $signheader Header 3128 3223 * @return string 3129 3224 */ 3130 public function DKIM_HeaderC($s )3225 public function DKIM_HeaderC($signheader) 3131 3226 { 3132 $s = preg_replace("/\r\n\s+/", " ", $s);3133 $lines = explode("\r\n", $s );3227 $signheader = preg_replace('/\r\n\s+/', ' ', $signheader); 3228 $lines = explode("\r\n", $signheader); 3134 3229 foreach ($lines as $key => $line) { 3135 list($heading, $value) = explode( ":", $line, 2);3230 list($heading, $value) = explode(':', $line, 2); 3136 3231 $heading = strtolower($heading); 3137 $value = preg_replace( "/\s+/", " ", $value); // Compress useless spaces3138 $lines[$key] = $heading . ":". trim($value); // Don't forget to remove WSP around the value3232 $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces 3233 $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value 3139 3234 } 3140 $s = implode("\r\n", $lines);3141 return $s ;3235 $signheader = implode("\r\n", $lines); 3236 return $signheader; 3142 3237 } 3143 3238 3144 3239 /** … … class PHPMailer 3205 3300 ); // Copied header fields (dkim-quoted-printable) 3206 3301 $body = $this->DKIM_BodyC($body); 3207 3302 $DKIMlen = strlen($body); // Length of body 3208 $DKIMb64 = base64_encode(pack( "H*", sha1($body))); // Base64 of packed binary SHA-1 hash of body3209 $ident = ($this->DKIM_identity == '') ? '' : " i=" . $this->DKIM_identity . ";";3210 $dkimhdrs = "DKIM-Signature: v=1; a=".3211 $DKIMsignatureType . "; q=".3212 $DKIMquery . "; l=".3213 $DKIMlen . "; s=".3303 $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body 3304 $ident = ($this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';'; 3305 $dkimhdrs = 'DKIM-Signature: v=1; a=' . 3306 $DKIMsignatureType . '; q=' . 3307 $DKIMquery . '; l=' . 3308 $DKIMlen . '; s=' . 3214 3309 $this->DKIM_selector . 3215 3310 ";\r\n" . 3216 "\tt=" . $DKIMtime . "; c=". $DKIMcanonicalization . ";\r\n" .3311 "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . 3217 3312 "\th=From:To:Subject;\r\n" . 3218 "\td=" . $this->DKIM_domain . ";". $ident . "\r\n" .3313 "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . 3219 3314 "\tz=$from\r\n" . 3220 3315 "\t|$to\r\n" . 3221 3316 "\t|$subject;\r\n" . … … class PHPMailer 3229 3324 } 3230 3325 3231 3326 /** 3327 * Allows for public read access to 'to' property. 3328 * @access public 3329 * @return array 3330 */ 3331 public function getToAddresses() 3332 { 3333 return $this->to; 3334 } 3335 3336 /** 3337 * Allows for public read access to 'cc' property. 3338 * @access public 3339 * @return array 3340 */ 3341 public function getCcAddresses() 3342 { 3343 return $this->cc; 3344 } 3345 3346 /** 3347 * Allows for public read access to 'bcc' property. 3348 * @access public 3349 * @return array 3350 */ 3351 public function getBccAddresses() 3352 { 3353 return $this->bcc; 3354 } 3355 3356 /** 3357 * Allows for public read access to 'ReplyTo' property. 3358 * @access public 3359 * @return array 3360 */ 3361 public function getReplyToAddresses() 3362 { 3363 return $this->ReplyTo; 3364 } 3365 3366 /** 3367 * Allows for public read access to 'all_recipients' property. 3368 * @access public 3369 * @return array 3370 */ 3371 public function getAllRecipientAddresses() 3372 { 3373 return $this->all_recipients; 3374 } 3375 3376 /** 3232 3377 * Perform a callback. 3233 3378 * @param bool $isSent 3234 3379 * @param string $to -
src/wp-includes/class-pop3.php
diff --git a/src/wp-includes/class-pop3.php b/src/wp-includes/class-pop3.php index d0455d7..71dffac 100644
a b 1 1 <?php 2 2 /** 3 * mail_fetch/setup.php 4 * 5 * Copyright (c) 1999-2011 CDI (cdi@thewebmasters.net) All Rights Reserved 6 * Modified by Philippe Mingo 2001-2009 mingo@rotedic.com 7 * An RFC 1939 compliant wrapper class for the POP3 protocol. 8 * 9 * Licensed under the GNU GPL. For full terms see the file COPYING. 10 * 11 * POP3 class 12 * 13 * @copyright 1999-2011 The SquirrelMail Project Team 14 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 15 * @package plugins 16 * @subpackage mail_fetch 3 * PHPMailer POP-Before-SMTP Authentication Class. 4 * PHP Version 5 5 * @package PHPMailer 6 * @link https://github.com/PHPMailer/PHPMailer/ 7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 10 * @author Brent R. Matzelle (original founder) 11 * @copyright 2012 - 2014 Marcus Bointon 12 * @copyright 2010 - 2012 Jim Jagielski 13 * @copyright 2004 - 2009 Andy Prevost 14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 15 * @note This program is distributed in the hope that it will be useful - WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. 17 18 */ 18 19 19 class POP3 { 20 var $ERROR = ''; // Error string. 21 22 var $TIMEOUT = 60; // Default timeout before giving up on a 23 // network operation. 24 25 var $COUNT = -1; // Mailbox msg count 26 27 var $BUFFER = 512; // Socket buffer for socket fgets() calls. 28 // Per RFC 1939 the returned line a POP3 29 // server can send is 512 bytes. 30 31 var $FP = ''; // The connection to the server's 32 // file descriptor 33 34 var $MAILSERVER = ''; // Set this to hard code the server name 35 36 var $DEBUG = FALSE; // set to true to echo pop3 37 // commands and responses to error_log 38 // this WILL log passwords! 39 40 var $BANNER = ''; // Holds the banner returned by the 41 // pop server - used for apop() 42 43 var $ALLOWAPOP = FALSE; // Allow or disallow apop() 44 // This must be set to true 45 // manually 46 47 function POP3 ( $server = '', $timeout = '' ) { 48 settype($this->BUFFER,"integer"); 49 if( !empty($server) ) { 50 // Do not allow programs to alter MAILSERVER 51 // if it is already specified. They can get around 52 // this if they -really- want to, so don't count on it. 53 if(empty($this->MAILSERVER)) 54 $this->MAILSERVER = $server; 55 } 56 if(!empty($timeout)) { 57 settype($timeout,"integer"); 58 $this->TIMEOUT = $timeout; 59 if (!ini_get('safe_mode')) 60 set_time_limit($timeout); 61 } 62 return true; 20 /** 21 * PHPMailer POP-Before-SMTP Authentication Class. 22 * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication. 23 * Does not support APOP. 24 * @package PHPMailer 25 * @author Richard Davey (original author) <rich@corephp.co.uk> 26 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 27 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 28 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 29 */ 30 class POP3 31 { 32 /** 33 * The POP3 PHPMailer Version number. 34 * @type string 35 * @access public 36 */ 37 public $Version = '5.2.8'; 38 39 /** 40 * Default POP3 port number. 41 * @type int 42 * @access public 43 */ 44 public $POP3_PORT = 110; 45 46 /** 47 * Default timeout in seconds. 48 * @type int 49 * @access public 50 */ 51 public $POP3_TIMEOUT = 30; 52 53 /** 54 * POP3 Carriage Return + Line Feed. 55 * @type string 56 * @access public 57 * @deprecated Use the constant instead 58 */ 59 public $CRLF = "\r\n"; 60 61 /** 62 * Debug display level. 63 * Options: 0 = no, 1+ = yes 64 * @type int 65 * @access public 66 */ 67 public $do_debug = 0; 68 69 /** 70 * POP3 mail server hostname. 71 * @type string 72 * @access public 73 */ 74 public $host; 75 76 /** 77 * POP3 port number. 78 * @type int 79 * @access public 80 */ 81 public $port; 82 83 /** 84 * POP3 Timeout Value in seconds. 85 * @type int 86 * @access public 87 */ 88 public $tval; 89 90 /** 91 * POP3 username 92 * @type string 93 * @access public 94 */ 95 public $username; 96 97 /** 98 * POP3 password. 99 * @type string 100 * @access public 101 */ 102 public $password; 103 104 /** 105 * Resource handle for the POP3 connection socket. 106 * @type resource 107 * @access private 108 */ 109 private $pop_conn; 110 111 /** 112 * Are we connected? 113 * @type bool 114 * @access private 115 */ 116 private $connected; 117 118 /** 119 * Error container. 120 * @type array 121 * @access private 122 */ 123 private $error; 124 125 /** 126 * Line break constant 127 */ 128 const CRLF = "\r\n"; 129 130 /** 131 * Constructor. 132 * @access public 133 */ 134 public function __construct() 135 { 136 $this->pop_conn = 0; 137 $this->connected = false; 138 $this->error = null; 63 139 } 64 140 65 function update_timer () { 66 if (!ini_get('safe_mode')) 67 set_time_limit($this->TIMEOUT); 68 return true; 141 /** 142 * Simple static wrapper for all-in-one POP before SMTP 143 * @param $host 144 * @param bool $port 145 * @param bool $tval 146 * @param string $username 147 * @param string $password 148 * @param int $debug_level 149 * @return bool 150 */ 151 public static function popBeforeSmtp( 152 $host, 153 $port = false, 154 $tval = false, 155 $username = '', 156 $password = '', 157 $debug_level = 0 158 ) { 159 $pop = new POP3; 160 return $pop->authorise($host, $port, $tval, $username, $password, $debug_level); 69 161 } 70 162 71 function connect ($server, $port = 110) { 72 // Opens a socket to the specified server. Unless overridden, 73 // port defaults to 110. Returns true on success, false on fail 74 75 // If MAILSERVER is set, override $server with it's value 76 77 if (!isset($port) || !$port) {$port = 110;} 78 if(!empty($this->MAILSERVER)) 79 $server = $this->MAILSERVER; 80 81 if(empty($server)){ 82 $this->ERROR = "POP3 connect: " . _("No server specified"); 83 unset($this->FP); 84 return false; 85 } 86 87 $fp = @fsockopen("$server", $port, $errno, $errstr); 88 89 if(!$fp) { 90 $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]"; 91 unset($this->FP); 92 return false; 93 } 94 95 socket_set_blocking($fp,-1); 96 $this->update_timer(); 97 $reply = fgets($fp,$this->BUFFER); 98 $reply = $this->strip_clf($reply); 99 if($this->DEBUG) 100 error_log("POP3 SEND [connect: $server] GOT [$reply]",0); 101 if(!$this->is_ok($reply)) { 102 $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]"; 103 unset($this->FP); 104 return false; 105 } 106 $this->FP = $fp; 107 $this->BANNER = $this->parse_banner($reply); 108 return true; 109 } 110 111 function user ($user = "") { 112 // Sends the USER command, returns true or false 113 114 if( empty($user) ) { 115 $this->ERROR = "POP3 user: " . _("no login ID submitted"); 116 return false; 117 } elseif(!isset($this->FP)) { 118 $this->ERROR = "POP3 user: " . _("connection not established"); 119 return false; 163 /** 164 * Authenticate with a POP3 server. 165 * A connect, login, disconnect sequence 166 * appropriate for POP-before SMTP authorisation. 167 * @access public 168 * @param string $host 169 * @param bool|int $port 170 * @param bool|int $tval 171 * @param string $username 172 * @param string $password 173 * @param int $debug_level 174 * @return bool 175 */ 176 public function authorise($host, $port = false, $tval = false, $username = '', $password = '', $debug_level = 0) 177 { 178 $this->host = $host; 179 // If no port value provided, use default 180 if ($port === false) { 181 $this->port = $this->POP3_PORT; 120 182 } else { 121 $reply = $this->send_cmd("USER $user"); 122 if(!$this->is_ok($reply)) { 123 $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]"; 124 return false; 125 } else 126 return true; 183 $this->port = $port; 127 184 } 128 } 129 130 function pass ($pass = "") { 131 // Sends the PASS command, returns # of msgs in mailbox, 132 // returns false (undef) on Auth failure 133 134 if(empty($pass)) { 135 $this->ERROR = "POP3 pass: " . _("No password submitted"); 136 return false; 137 } elseif(!isset($this->FP)) { 138 $this->ERROR = "POP3 pass: " . _("connection not established"); 139 return false; 185 // If no timeout value provided, use default 186 if ($tval === false) { 187 $this->tval = $this->POP3_TIMEOUT; 140 188 } else { 141 $reply = $this->send_cmd("PASS $pass"); 142 if(!$this->is_ok($reply)) { 143 $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]"; 144 $this->quit(); 145 return false; 146 } else { 147 // Auth successful. 148 $count = $this->last("count"); 149 $this->COUNT = $count; 150 return $count; 189 $this->tval = $tval; 190 } 191 $this->do_debug = $debug_level; 192 $this->username = $username; 193 $this->password = $password; 194 // Refresh the error log 195 $this->error = null; 196 // connect 197 $result = $this->connect($this->host, $this->port, $this->tval); 198 if ($result) { 199 $login_result = $this->login($this->username, $this->password); 200 if ($login_result) { 201 $this->disconnect(); 202 return true; 151 203 } 152 204 } 205 // We need to disconnect regardless of whether the login succeeded 206 $this->disconnect(); 207 return false; 153 208 } 154 209 155 function apop ($login,$pass) { 156 // Attempts an APOP login. If this fails, it'll 157 // try a standard login. YOUR SERVER MUST SUPPORT 158 // THE USE OF THE APOP COMMAND! 159 // (apop is optional per rfc1939) 160 161 if(!isset($this->FP)) { 162 $this->ERROR = "POP3 apop: " . _("No connection to server"); 163 return false; 164 } elseif(!$this->ALLOWAPOP) { 165 $retVal = $this->login($login,$pass); 166 return $retVal; 167 } elseif(empty($login)) { 168 $this->ERROR = "POP3 apop: " . _("No login ID submitted"); 169 return false; 170 } elseif(empty($pass)) { 171 $this->ERROR = "POP3 apop: " . _("No password submitted"); 172 return false; 173 } else { 174 $banner = $this->BANNER; 175 if( (!$banner) or (empty($banner)) ) { 176 $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort"); 177 $retVal = $this->login($login,$pass); 178 return $retVal; 179 } else { 180 $AuthString = $banner; 181 $AuthString .= $pass; 182 $APOPString = md5($AuthString); 183 $cmd = "APOP $login $APOPString"; 184 $reply = $this->send_cmd($cmd); 185 if(!$this->is_ok($reply)) { 186 $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort"); 187 $retVal = $this->login($login,$pass); 188 return $retVal; 189 } else { 190 // Auth successful. 191 $count = $this->last("count"); 192 $this->COUNT = $count; 193 return $count; 194 } 210 /** 211 * Connect to a POP3 server. 212 * @access public 213 * @param string $host 214 * @param bool|int $port 215 * @param integer $tval 216 * @return boolean 217 */ 218 public function connect($host, $port = false, $tval = 30) 219 { 220 // Are we already connected? 221 if ($this->connected) { 222 return true; 223 } 224 225 //On Windows this will raise a PHP Warning error if the hostname doesn't exist. 226 //Rather than suppress it with @fsockopen, capture it cleanly instead 227 set_error_handler(array($this, 'catchWarning')); 228 229 // connect to the POP3 server 230 $this->pop_conn = fsockopen( 231 $host, // POP3 Host 232 $port, // Port # 233 $errno, // Error Number 234 $errstr, // Error Message 235 $tval 236 ); // Timeout (seconds) 237 // Restore the error handler 238 restore_error_handler(); 239 // Does the Error Log now contain anything? 240 if ($this->error && $this->do_debug >= 1) { 241 $this->displayErrors(); 242 } 243 // Did we connect? 244 if ($this->pop_conn == false) { 245 // It would appear not... 246 $this->error = array( 247 'error' => "Failed to connect to server $host on port $port", 248 'errno' => $errno, 249 'errstr' => $errstr 250 ); 251 if ($this->do_debug >= 1) { 252 $this->displayErrors(); 195 253 } 254 return false; 196 255 } 197 }198 256 199 function login ($login = "", $pass = "") { 200 // Sends both user and pass. Returns # of msgs in mailbox or 201 // false on failure (or -1, if the error occurs while getting 202 // the number of messages.) 203 204 if( !isset($this->FP) ) { 205 $this->ERROR = "POP3 login: " . _("No connection to server"); 206 return false; 257 // Increase the stream time-out 258 // Check for PHP 4.3.0 or later 259 if (version_compare(phpversion(), '5.0.0', 'ge')) { 260 stream_set_timeout($this->pop_conn, $tval, 0); 207 261 } else { 208 $fp = $this->FP; 209 if( !$this->user( $login ) ) { 210 // Preserve the error generated by user() 211 return false; 212 } else { 213 $count = $this->pass($pass); 214 if( (!$count) || ($count == -1) ) { 215 // Preserve the error generated by last() and pass() 216 return false; 217 } else 218 return $count; 262 // Does not work on Windows 263 if (substr(PHP_OS, 0, 3) !== 'WIN') { 264 socket_set_timeout($this->pop_conn, $tval, 0); 219 265 } 220 266 } 221 }222 223 function top ($msgNum, $numLines = "0") {224 // Gets the header and first $numLines of the msg body225 // returns data in an array with each returned line being226 // an array element. If $numLines is empty, returns227 // only the header information, and none of the body.228 229 if(!isset($this->FP)) {230 $this->ERROR = "POP3 top: " . _("No connection to server");231 return false;232 }233 $this->update_timer();234 235 $fp = $this->FP;236 $buffer = $this->BUFFER;237 $cmd = "TOP $msgNum $numLines";238 fwrite($fp, "TOP $msgNum $numLines\r\n");239 $reply = fgets($fp, $buffer);240 $reply = $this->strip_clf($reply);241 if($this->DEBUG) {242 @error_log("POP3 SEND [$cmd] GOT [$reply]",0);243 }244 if(!$this->is_ok($reply))245 {246 $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]";247 return false;248 }249 267 250 $count = 0; 251 $MsgArray = array(); 252 253 $line = fgets($fp,$buffer); 254 while ( !preg_match('/^\.\r\n/',$line)) 255 { 256 $MsgArray[$count] = $line; 257 $count++; 258 $line = fgets($fp,$buffer); 259 if(empty($line)) { break; } 268 // Get the POP3 server response 269 $pop3_response = $this->getResponse(); 270 // Check for the +OK 271 if ($this->checkResponse($pop3_response)) { 272 // The connection is established and the POP3 server is talking 273 $this->connected = true; 274 return true; 260 275 } 261 262 return $MsgArray; 276 return false; 263 277 } 264 278 265 function pop_list ($msgNum = "") { 266 // If called with an argument, returns that msgs' size in octets 267 // No argument returns an associative array of undeleted 268 // msg numbers and their sizes in octets 269 270 if(!isset($this->FP)) 271 { 272 $this->ERROR = "POP3 pop_list: " . _("No connection to server"); 273 return false; 274 } 275 $fp = $this->FP; 276 $Total = $this->COUNT; 277 if( (!$Total) or ($Total == -1) ) 278 { 279 return false; 280 } 281 if($Total == 0) 282 { 283 return array("0","0"); 284 // return -1; // mailbox empty 285 } 286 287 $this->update_timer(); 279 /** 280 * Log in to the POP3 server. 281 * Does not support APOP (RFC 2828, 4949). 282 * @access public 283 * @param string $username 284 * @param string $password 285 * @return boolean 286 */ 287 public function login($username = '', $password = '') 288 { 289 if ($this->connected == false) { 290 $this->error = 'Not connected to POP3 server'; 288 291 289 if(!empty($msgNum)) 290 { 291 $cmd = "LIST $msgNum"; 292 fwrite($fp,"$cmd\r\n"); 293 $reply = fgets($fp,$this->BUFFER); 294 $reply = $this->strip_clf($reply); 295 if($this->DEBUG) { 296 @error_log("POP3 SEND [$cmd] GOT [$reply]",0); 292 if ($this->do_debug >= 1) { 293 $this->displayErrors(); 297 294 } 298 if(!$this->is_ok($reply))299 {300 $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]";301 return false;302 }303 list($junk,$num,$size) = preg_split('/\s+/',$reply);304 return $size;305 295 } 306 $cmd = "LIST"; 307 $reply = $this->send_cmd($cmd); 308 if(!$this->is_ok($reply)) 309 { 310 $reply = $this->strip_clf($reply); 311 $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; 312 return false; 296 if (empty($username)) { 297 $username = $this->username; 313 298 } 314 $MsgArray = array(); 315 $MsgArray[0] = $Total; 316 for($msgC=1;$msgC <= $Total; $msgC++) 317 { 318 if($msgC > $Total) { break; } 319 $line = fgets($fp,$this->BUFFER); 320 $line = $this->strip_clf($line); 321 if(strpos($line, '.') === 0) 322 { 323 $this->ERROR = "POP3 pop_list: " . _("Premature end of list"); 324 return false; 325 } 326 list($thisMsg,$msgSize) = preg_split('/\s+/',$line); 327 settype($thisMsg,"integer"); 328 if($thisMsg != $msgC) 329 { 330 $MsgArray[$msgC] = "deleted"; 331 } 332 else 333 { 334 $MsgArray[$msgC] = $msgSize; 335 } 299 if (empty($password)) { 300 $password = $this->password; 336 301 } 337 return $MsgArray;338 }339 340 function get ($msgNum) {341 // Retrieve the specified msg number. Returns an array342 // where each line of the msg is an array element.343 302 344 if(!isset($this->FP)) 345 { 346 $this->ERROR = "POP3 get: " . _("No connection to server"); 347 return false; 348 } 349 350 $this->update_timer(); 351 352 $fp = $this->FP; 353 $buffer = $this->BUFFER; 354 $cmd = "RETR $msgNum"; 355 $reply = $this->send_cmd($cmd); 356 357 if(!$this->is_ok($reply)) 358 { 359 $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]"; 360 return false; 361 } 362 363 $count = 0; 364 $MsgArray = array(); 365 366 $line = fgets($fp,$buffer); 367 while ( !preg_match('/^\.\r\n/',$line)) 368 { 369 if ( $line{0} == '.' ) { $line = substr($line,1); } 370 $MsgArray[$count] = $line; 371 $count++; 372 $line = fgets($fp,$buffer); 373 if(empty($line)) { break; } 374 } 375 return $MsgArray; 376 } 377 378 function last ( $type = "count" ) { 379 // Returns the highest msg number in the mailbox. 380 // returns -1 on error, 0+ on success, if type != count 381 // results in a popstat() call (2 element array returned) 382 383 $last = -1; 384 if(!isset($this->FP)) 385 { 386 $this->ERROR = "POP3 last: " . _("No connection to server"); 387 return $last; 388 } 389 390 $reply = $this->send_cmd("STAT"); 391 if(!$this->is_ok($reply)) 392 { 393 $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]"; 394 return $last; 395 } 396 397 $Vars = preg_split('/\s+/',$reply); 398 $count = $Vars[1]; 399 $size = $Vars[2]; 400 settype($count,"integer"); 401 settype($size,"integer"); 402 if($type != "count") 403 { 404 return array($count,$size); 405 } 406 return $count; 407 } 408 409 function reset () { 410 // Resets the status of the remote server. This includes 411 // resetting the status of ALL msgs to not be deleted. 412 // This method automatically closes the connection to the server. 413 414 if(!isset($this->FP)) 415 { 416 $this->ERROR = "POP3 reset: " . _("No connection to server"); 417 return false; 418 } 419 $reply = $this->send_cmd("RSET"); 420 if(!$this->is_ok($reply)) 421 { 422 // The POP3 RSET command -never- gives a -ERR 423 // response - if it ever does, something truely 424 // wild is going on. 425 426 $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]"; 427 @error_log("POP3 reset: ERROR [$reply]",0); 303 // Send the Username 304 $this->sendString("USER $username" . self::CRLF); 305 $pop3_response = $this->getResponse(); 306 if ($this->checkResponse($pop3_response)) { 307 // Send the Password 308 $this->sendString("PASS $password" . self::CRLF); 309 $pop3_response = $this->getResponse(); 310 if ($this->checkResponse($pop3_response)) { 311 return true; 312 } 428 313 } 429 $this->quit(); 430 return true; 314 return false; 431 315 } 432 316 433 function send_cmd ( $cmd = "" ) 317 /** 318 * Disconnect from the POP3 server. 319 * @access public 320 */ 321 public function disconnect() 434 322 { 435 // Sends a user defined command string to the 436 // POP server and returns the results. Useful for 437 // non-compliant or custom POP servers. 438 // Do NOT includ the \r\n as part of your command 439 // string - it will be appended automatically. 440 441 // The return value is a standard fgets() call, which 442 // will read up to $this->BUFFER bytes of data, until it 443 // encounters a new line, or EOF, whichever happens first. 444 445 // This method works best if $cmd responds with only 446 // one line of data. 447 448 if(!isset($this->FP)) 449 { 450 $this->ERROR = "POP3 send_cmd: " . _("No connection to server"); 451 return false; 452 } 453 454 if(empty($cmd)) 455 { 456 $this->ERROR = "POP3 send_cmd: " . _("Empty command string"); 457 return ""; 458 } 459 460 $fp = $this->FP; 461 $buffer = $this->BUFFER; 462 $this->update_timer(); 463 fwrite($fp,"$cmd\r\n"); 464 $reply = fgets($fp,$buffer); 465 $reply = $this->strip_clf($reply); 466 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 467 return $reply; 323 $this->sendString('QUIT'); 324 //The QUIT command may cause the daemon to exit, which will kill our connection 325 //So ignore errors here 326 @fclose($this->pop_conn); 468 327 } 469 328 470 function quit() { 471 // Closes the connection to the POP3 server, deleting 472 // any msgs marked as deleted. 473 474 if(!isset($this->FP)) 475 { 476 $this->ERROR = "POP3 quit: " . _("connection does not exist"); 477 return false; 478 } 479 $fp = $this->FP; 480 $cmd = "QUIT"; 481 fwrite($fp,"$cmd\r\n"); 482 $reply = fgets($fp,$this->BUFFER); 483 $reply = $this->strip_clf($reply); 484 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 485 fclose($fp); 486 unset($this->FP); 487 return true; 488 } 489 490 function popstat () { 491 // Returns an array of 2 elements. The number of undeleted 492 // msgs in the mailbox, and the size of the mbox in octets. 493 494 $PopArray = $this->last("array"); 495 496 if($PopArray == -1) { return false; } 497 498 if( (!$PopArray) or (empty($PopArray)) ) 499 { 500 return false; 329 /** 330 * Get a response from the POP3 server. 331 * $size is the maximum number of bytes to retrieve 332 * @param integer $size 333 * @return string 334 * @access private 335 */ 336 private function getResponse($size = 128) 337 { 338 $response = fgets($this->pop_conn, $size); 339 if ($this->do_debug >= 1) { 340 echo "Server -> Client: $response"; 501 341 } 502 return $ PopArray;342 return $response; 503 343 } 504 344 505 function uidl ($msgNum = "") 345 /** 346 * Send raw data to the POP3 server. 347 * @param string $string 348 * @return integer 349 * @access private 350 */ 351 private function sendString($string) 506 352 { 507 // Returns the UIDL of the msg specified. If called with 508 // no arguments, returns an associative array where each 509 // undeleted msg num is a key, and the msg's uidl is the element 510 // Array element 0 will contain the total number of msgs 511 512 if(!isset($this->FP)) { 513 $this->ERROR = "POP3 uidl: " . _("No connection to server"); 514 return false; 515 } 516 517 $fp = $this->FP; 518 $buffer = $this->BUFFER; 519 520 if(!empty($msgNum)) { 521 $cmd = "UIDL $msgNum"; 522 $reply = $this->send_cmd($cmd); 523 if(!$this->is_ok($reply)) 524 { 525 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; 526 return false; 353 if ($this->pop_conn) { 354 if ($this->do_debug >= 2) { //Show client messages when debug >= 2 355 echo "Client -> Server: $string"; 527 356 } 528 list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply); 529 return $myUidl; 530 } else { 531 $this->update_timer(); 532 533 $UIDLArray = array(); 534 $Total = $this->COUNT; 535 $UIDLArray[0] = $Total; 536 537 if ($Total < 1) 538 { 539 return $UIDLArray; 540 } 541 $cmd = "UIDL"; 542 fwrite($fp, "UIDL\r\n"); 543 $reply = fgets($fp, $buffer); 544 $reply = $this->strip_clf($reply); 545 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 546 if(!$this->is_ok($reply)) 547 { 548 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; 549 return false; 550 } 551 552 $line = ""; 553 $count = 1; 554 $line = fgets($fp,$buffer); 555 while ( !preg_match('/^\.\r\n/',$line)) { 556 list ($msg,$msgUidl) = preg_split('/\s+/',$line); 557 $msgUidl = $this->strip_clf($msgUidl); 558 if($count == $msg) { 559 $UIDLArray[$msg] = $msgUidl; 560 } 561 else 562 { 563 $UIDLArray[$count] = 'deleted'; 564 } 565 $count++; 566 $line = fgets($fp,$buffer); 567 } 568 } 569 return $UIDLArray; 570 } 571 572 function delete ($msgNum = "") { 573 // Flags a specified msg as deleted. The msg will not 574 // be deleted until a quit() method is called. 575 576 if(!isset($this->FP)) 577 { 578 $this->ERROR = "POP3 delete: " . _("No connection to server"); 579 return false; 580 } 581 if(empty($msgNum)) 582 { 583 $this->ERROR = "POP3 delete: " . _("No msg number submitted"); 584 return false; 585 } 586 $reply = $this->send_cmd("DELE $msgNum"); 587 if(!$this->is_ok($reply)) 588 { 589 $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]"; 590 return false; 357 return fwrite($this->pop_conn, $string, strlen($string)); 591 358 } 592 return true;359 return 0; 593 360 } 594 361 595 // ********************************************************* 596 597 // The following methods are internal to the class. 598 599 function is_ok ($cmd = "") { 600 // Return true or false on +OK or -ERR 601 602 if( empty($cmd) ) 362 /** 363 * Checks the POP3 server response. 364 * Looks for for +OK or -ERR. 365 * @param string $string 366 * @return boolean 367 * @access private 368 */ 369 private function checkResponse($string) 370 { 371 if (substr($string, 0, 3) !== '+OK') { 372 $this->error = array( 373 'error' => "Server reported an error: $string", 374 'errno' => 0, 375 'errstr' => '' 376 ); 377 if ($this->do_debug >= 1) { 378 $this->displayErrors(); 379 } 603 380 return false; 604 else 605 return( stripos($cmd, '+OK') !== false ); 606 } 607 608 function strip_clf ($text = "") { 609 // Strips \r\n from server responses 610 611 if(empty($text)) 612 return $text; 613 else { 614 $stripped = str_replace(array("\r","\n"),'',$text); 615 return $stripped; 381 } else { 382 return true; 616 383 } 617 384 } 618 385 619 function parse_banner ( $server_text ) { 620 $outside = true; 621 $banner = ""; 622 $length = strlen($server_text); 623 for($count =0; $count < $length; $count++) 624 { 625 $digit = substr($server_text,$count,1); 626 if(!empty($digit)) { 627 if( (!$outside) && ($digit != '<') && ($digit != '>') ) 628 { 629 $banner .= $digit; 630 } 631 if ($digit == '<') 632 { 633 $outside = false; 634 } 635 if($digit == '>') 636 { 637 $outside = true; 638 } 639 } 386 /** 387 * Display errors if debug is enabled. 388 * @access private 389 */ 390 private function displayErrors() 391 { 392 echo '<pre>'; 393 foreach ($this->error as $single_error) { 394 print_r($single_error); 640 395 } 641 $banner = $this->strip_clf($banner); // Just in case 642 return "<$banner>"; 396 echo '</pre>'; 643 397 } 644 398 645 } // End class 646 647 // For php4 compatibility 648 if (!function_exists("stripos")) { 649 function stripos($haystack, $needle){ 650 return strpos($haystack, stristr( $haystack, $needle )); 399 /** 400 * POP3 connection error handler. 401 * @param integer $errno 402 * @param string $errstr 403 * @param string $errfile 404 * @param integer $errline 405 * @access private 406 */ 407 private function catchWarning($errno, $errstr, $errfile, $errline) 408 { 409 $this->error[] = array( 410 'error' => "Connecting to the POP3 server raised a PHP warning: ", 411 'errno' => $errno, 412 'errstr' => $errstr, 413 'errfile' => $errfile, 414 'errline' => $errline 415 ); 651 416 } 652 417 } -
src/wp-includes/class-smtp.php
diff --git a/src/wp-includes/class-smtp.php b/src/wp-includes/class-smtp.php index e6b4522..ec75ca5 100644
a b 1 1 <?php 2 2 /** 3 3 * PHPMailer RFC821 SMTP email transport class. 4 * Version 5.2.7 5 * PHP version 5.0.0 6 * @category PHP 7 * @package PHPMailer 8 * @link https://github.com/PHPMailer/PHPMailer/ 9 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk> 4 * PHP Version 5 5 * @package PHPMailer 6 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project 7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> 10 8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com> 11 9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> 12 * @ copyright 2013 Marcus Bointon13 * @copyright 20 04 - 2008 Andy Prevost10 * @author Brent R. Matzelle (original founder) 11 * @copyright 2014 Marcus Bointon 14 12 * @copyright 2010 - 2012 Jim Jagielski 15 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 13 * @copyright 2004 - 2009 Andy Prevost 14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 15 * @note This program is distributed in the hope that it will be useful - WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. 16 18 */ 17 19 18 20 /** 19 21 * PHPMailer RFC821 SMTP email transport class. 20 * 21 * Implements RFC 821 SMTP commands 22 * and provides some utility methods for sending mail to an SMTP server. 23 * 24 * PHP Version 5.0.0 25 * 26 * @category PHP 27 * @package PHPMailer 28 * @link https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php 29 * @author Chris Ryan <unknown@example.com> 30 * @author Marcus Bointon <phpmailer@synchromedia.co.uk> 31 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 22 * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. 23 * @package PHPMailer 24 * @author Chris Ryan <unknown@example.com> 25 * @author Marcus Bointon <phpmailer@synchromedia.co.uk> 32 26 */ 33 34 27 class SMTP 35 28 { 36 29 /** 37 * The PHPMailer SMTP Version number. 30 * The PHPMailer SMTP version number. 31 * @type string 38 32 */ 39 const VERSION = '5.2. 7';33 const VERSION = '5.2.8'; 40 34 41 35 /** 42 36 * SMTP line break constant. 37 * @type string 43 38 */ 44 39 const CRLF = "\r\n"; 45 40 46 41 /** 47 42 * The SMTP port to use if one is not specified. 43 * @type int 48 44 */ 49 45 const DEFAULT_SMTP_PORT = 25; 50 46 51 47 /** 48 * The maximum line length allowed by RFC 2822 section 2.1.1 49 * @type int 50 */ 51 const MAX_LINE_LENGTH = 998; 52 53 /** 52 54 * The PHPMailer SMTP Version number. 53 55 * @type string 54 * @deprecated This should be a constant56 * @deprecated Use the constant instead 55 57 * @see SMTP::VERSION 56 58 */ 57 public $Version = '5.2. 7';59 public $Version = '5.2.8'; 58 60 59 61 /** 60 62 * SMTP server port number. 61 63 * @type int 62 * @deprecated This is only ever u ed as default value, so should be a constant64 * @deprecated This is only ever used as a default value, so use the constant instead 63 65 * @see SMTP::DEFAULT_SMTP_PORT 64 66 */ 65 67 public $SMTP_PORT = 25; 66 68 67 69 /** 68 * SMTP reply line ending 70 * SMTP reply line ending. 69 71 * @type string 70 * @deprecated Use the c lass constant instead72 * @deprecated Use the constant instead 71 73 * @see SMTP::CRLF 72 74 */ 73 75 public $CRLF = "\r\n"; 74 76 75 77 /** 76 78 * Debug output level. 77 * Options: 0 for no output, 1 for commands, 2 for data and commands 79 * Options: 80 * * `0` No output 81 * * `1` Commands 82 * * `2` Data and commands 83 * * `3` As 2 plus connection status 84 * * `4` Low-level data output 78 85 * @type int 79 86 */ 80 87 public $do_debug = 0; 81 88 82 89 /** 83 * The function/method to use for debugging output. 84 * Options: 'echo', 'html' or 'error_log' 90 * How to handle debug output. 91 * Options: 92 * * `echo` Output plain-text as-is, appropriate for CLI 93 * * `html` Output escaped, line breaks converted to <br>, appropriate for browser output 94 * * `error_log` Output to error log as configured in php.ini 85 95 * @type string 86 96 */ 87 97 public $Debugoutput = 'echo'; 88 98 89 99 /** 90 100 * Whether to use VERP. 101 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 102 * @link http://www.postfix.org/VERP_README.html Info on VERP 91 103 * @type bool 92 104 */ 93 105 public $do_verp = false; 94 106 95 107 /** 96 * The SMTP timeout value for reads, in seconds. 108 * The timeout value for connection, in seconds. 109 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 110 * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. 111 * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 97 112 * @type int 98 113 */ 99 public $Timeout = 15;114 public $Timeout = 300; 100 115 101 116 /** 102 117 * The SMTP timelimit value for reads, in seconds. … … class SMTP 137 152 $this->smtp_conn = 0; 138 153 $this->error = null; 139 154 $this->helo_rply = null; 140 141 155 $this->do_debug = 0; 142 156 } 143 157 … … class SMTP 164 178 break; 165 179 case 'echo': 166 180 default: 167 //Just echoes whatever was received 168 echo $str; 181 echo gmdate('Y-m-d H:i:s')."\t".trim($str)."\n"; 169 182 } 170 183 } 171 184 172 185 /** 173 186 * Connect to an SMTP server. 174 * @param string $host 175 * @param int $port 187 * @param string $host SMTP server IP or host name 188 * @param int $port The port number to connect to 176 189 * @param int $timeout How long to wait for the connection to open 177 190 * @param array $options An array of options for stream_context_create() 178 191 * @access public … … class SMTP 182 195 { 183 196 // Clear errors to avoid confusion 184 197 $this->error = null; 185 186 198 // Make sure we are __not__ connected 187 199 if ($this->connected()) { 188 200 // Already connected, generate error 189 201 $this->error = array('error' => 'Already connected to a server'); 190 202 return false; 191 203 } 192 193 204 if (empty($port)) { 194 205 $port = self::DEFAULT_SMTP_PORT; 195 206 } 196 197 207 // Connect to the SMTP server 208 if ($this->do_debug >= 3) { 209 $this->edebug('Connection: opening'); 210 } 198 211 $errno = 0; 199 212 $errstr = ''; 200 213 $socket_context = stream_context_create($options); … … class SMTP 207 220 STREAM_CLIENT_CONNECT, 208 221 $socket_context 209 222 ); 210 211 223 // Verify we connected properly 212 224 if (empty($this->smtp_conn)) { 213 225 $this->error = array( … … class SMTP 217 229 ); 218 230 if ($this->do_debug >= 1) { 219 231 $this->edebug( 220 'SMTP ->ERROR: ' . $this->error['error']232 'SMTP ERROR: ' . $this->error['error'] 221 233 . ": $errstr ($errno)" 222 234 ); 223 235 } 224 236 return false; 225 237 } 226 238 if ($this->do_debug >= 3) { 239 $this->edebug('Connection: opened'); 240 } 227 241 // SMTP server can take longer to respond, give longer timeout for first read 228 242 // Windows does not have support for this timeout function 229 243 if (substr(PHP_OS, 0, 3) != 'WIN') { … … class SMTP 233 247 } 234 248 stream_set_timeout($this->smtp_conn, $timeout, 0); 235 249 } 236 237 250 // Get any announcement 238 251 $announce = $this->get_lines(); 239 240 252 if ($this->do_debug >= 2) { 241 $this->edebug('S MTP -> FROM SERVER:' . $announce);253 $this->edebug('SERVER -> CLIENT: ' . $announce); 242 254 } 243 244 255 return true; 245 256 } 246 257 … … class SMTP 251 262 */ 252 263 public function startTLS() 253 264 { 254 if (!$this->sendCommand( "STARTTLS", "STARTTLS", 220)) {265 if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { 255 266 return false; 256 267 } 257 268 // Begin encrypted connection … … class SMTP 259 270 $this->smtp_conn, 260 271 true, 261 272 STREAM_CRYPTO_METHOD_TLS_CLIENT 262 ) 263 ) { 273 )) { 264 274 return false; 265 275 } 266 276 return true; … … class SMTP 288 298 if (empty($authtype)) { 289 299 $authtype = 'LOGIN'; 290 300 } 291 292 301 switch ($authtype) { 293 302 case 'PLAIN': 294 303 // Start authentication … … class SMTP 351 360 ) { 352 361 return false; 353 362 } 354 355 363 //Though 0 based, there is a white space after the 3 digit number 356 364 //msg2 357 365 $challenge = substr($this->last_reply, 3); … … class SMTP 411 419 // Eliminates the need to install mhash to compute a HMAC 412 420 // Hacked by Lance Rushing 413 421 414 $b = 64; // byte length for md5415 if (strlen($key) > $b ) {422 $bytelen = 64; // byte length for md5 423 if (strlen($key) > $bytelen) { 416 424 $key = pack('H*', md5($key)); 417 425 } 418 $key = str_pad($key, $b , chr(0x00));419 $ipad = str_pad('', $b , chr(0x36));420 $opad = str_pad('', $b , chr(0x5c));426 $key = str_pad($key, $bytelen, chr(0x00)); 427 $ipad = str_pad('', $bytelen, chr(0x36)); 428 $opad = str_pad('', $bytelen, chr(0x5c)); 421 429 $k_ipad = $key ^ $ipad; 422 430 $k_opad = $key ^ $opad; 423 431 … … class SMTP 437 445 // the socket is valid but we are not connected 438 446 if ($this->do_debug >= 1) { 439 447 $this->edebug( 440 'SMTP ->NOTICE: EOF caught while checking if connected'448 'SMTP NOTICE: EOF caught while checking if connected' 441 449 ); 442 450 } 443 451 $this->close(); … … class SMTP 462 470 if (!empty($this->smtp_conn)) { 463 471 // close the connection and cleanup 464 472 fclose($this->smtp_conn); 473 if ($this->do_debug >= 3) { 474 $this->edebug('Connection: closed'); 475 } 465 476 $this->smtp_conn = 0; 466 477 } 467 478 } … … class SMTP 483 494 if (!$this->sendCommand('DATA', 'DATA', 354)) { 484 495 return false; 485 496 } 486 487 497 /* The server is ready to accept data! 488 * according to rfc821 we should not send more than 1000 489 * including the CRLF 490 * characters on a single line so we will break the data up 491 * into lines by \r and/or \n then if needed we will break 492 * each of those into smaller lines to fit within the limit. 493 * in addition we will be looking for lines that start with 494 * a period '.' and append and additional period '.' to that 495 * line. NOTE: this does not count towards limit. 498 * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) 499 * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into 500 * smaller lines to fit within the limit. 501 * We will also look for lines that start with a '.' and prepend an additional '.'. 502 * NOTE: this does not count towards line-length limit. 496 503 */ 497 504 498 // Normalize the line breaks before exploding 499 $msg_data = str_replace("\r\n", "\n", $msg_data); 500 $msg_data = str_replace("\r", "\n", $msg_data); 501 $lines = explode("\n", $msg_data); 502 503 /* We need to find a good way to determine if headers are 504 * in the msg_data or if it is a straight msg body 505 * currently I am assuming rfc822 definitions of msg headers 506 * and if the first field of the first line (':' separated) 507 * does not contain a space then it _should_ be a header 508 * and we can process all lines before a blank "" line as 509 * headers. 505 // Normalize line breaks before exploding 506 $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); 507 508 /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field 509 * of the first line (':' separated) does not contain a space then it _should_ be a header and we will 510 * process all lines before a blank line as headers. 510 511 */ 511 512 512 513 $field = substr($lines[0], 0, strpos($lines[0], ':')); 513 514 $in_headers = false; 514 if (!empty($field) && !strstr($field, ' ')) {515 if (!empty($field) && strpos($field, ' ') === false) { 515 516 $in_headers = true; 516 517 } 517 518 518 //RFC 2822 section 2.1.1 limit519 $max_line_length = 998;520 521 519 foreach ($lines as $line) { 522 $lines_out = null;523 if ($ line == '' && $in_headers) {520 $lines_out = array(); 521 if ($in_headers and $line == '') { 524 522 $in_headers = false; 525 523 } 526 524 // ok we need to break this line up into several smaller lines 527 while (strlen($line) > $max_line_length) { 528 $pos = strrpos(substr($line, 0, $max_line_length), ' '); 529 530 // Patch to fix DOS attack 531 if (!$pos) { 532 $pos = $max_line_length - 1; 525 //This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len) 526 while (isset($line[self::MAX_LINE_LENGTH])) { 527 //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on 528 //so as to avoid breaking in the middle of a word 529 $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); 530 if (!$pos) { //Deliberately matches both false and 0 531 //No nice break found, add a hard break 532 $pos = self::MAX_LINE_LENGTH - 1; 533 533 $lines_out[] = substr($line, 0, $pos); 534 534 $line = substr($line, $pos); 535 535 } else { 536 //Break at the found point 536 537 $lines_out[] = substr($line, 0, $pos); 538 //Move along by the amount we dealt with 537 539 $line = substr($line, $pos + 1); 538 540 } 539 540 541 /* If processing headers add a LWSP-char to the front of new line 541 * rfc822 on long msg headers542 * RFC822 section 3.1.1 542 543 */ 543 544 if ($in_headers) { 544 545 $line = "\t" . $line; … … class SMTP 546 547 } 547 548 $lines_out[] = $line; 548 549 549 // send the lines to the server 550 while (list(, $line_out) = @each($lines_out)) { 551 if (strlen($line_out) > 0) { 552 if (substr($line_out, 0, 1) == '.') { 553 $line_out = '.' . $line_out; 554 } 550 // Send the lines to the server 551 foreach ($lines_out as $line_out) { 552 //RFC2821 section 4.5.2 553 if (!empty($line_out) and $line_out[0] == '.') { 554 $line_out = '.' . $line_out; 555 555 } 556 556 $this->client_send($line_out . self::CRLF); 557 557 } … … class SMTP 565 565 * Send an SMTP HELO or EHLO command. 566 566 * Used to identify the sending server to the receiving server. 567 567 * This makes sure that client and server are in a known state. 568 * Implements fromRFC 821: HELO <SP> <domain> <CRLF>568 * Implements RFC 821: HELO <SP> <domain> <CRLF> 569 569 * and RFC 2821 EHLO. 570 570 * @param string $host The host name or IP to connect to 571 571 * @access public … … class SMTP 574 574 public function hello($host = '') 575 575 { 576 576 // Try extended hello first (RFC 2821) 577 if (!$this->sendHello('EHLO', $host)) { 578 if (!$this->sendHello('HELO', $host)) { 579 return false; 580 } 581 } 582 583 return true; 577 return (bool)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); 584 578 } 585 579 586 580 /** … … class SMTP 588 582 * Low-level implementation used by hello() 589 583 * @see hello() 590 584 * @param string $hello The HELO string 591 * @param string $host 585 * @param string $host The hostname to say we are 592 586 * @access protected 593 587 * @return bool 594 588 */ … … class SMTP 631 625 public function quit($close_on_error = true) 632 626 { 633 627 $noerror = $this->sendCommand('QUIT', 'QUIT', 221); 634 $e = $this->error; //Save any error628 $err = $this->error; //Save any error 635 629 if ($noerror or $close_on_error) { 636 630 $this->close(); 637 $this->error = $e ; //Restore any error from the quit command631 $this->error = $err; //Restore any error from the quit command 638 632 } 639 633 return $noerror; 640 634 } 641 635 642 636 /** 643 637 * Send an SMTP RCPT command. 644 * Sets the TO argument to $to .638 * Sets the TO argument to $toaddr. 645 639 * Returns true if the recipient was accepted false if it was rejected. 646 640 * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> 647 * @param string $to The address the message is being sent to641 * @param string $toaddr The address the message is being sent to 648 642 * @access public 649 643 * @return bool 650 644 */ 651 public function recipient($to )645 public function recipient($toaddr) 652 646 { 653 647 return $this->sendCommand( 654 'RCPT TO 655 'RCPT TO:<' . $to . '>',648 'RCPT TO', 649 'RCPT TO:<' . $toaddr . '>', 656 650 array(250, 251) 657 651 ); 658 652 } … … class SMTP 681 675 { 682 676 if (!$this->connected()) { 683 677 $this->error = array( 684 "error"=> "Called $command without being connected"678 'error' => "Called $command without being connected" 685 679 ); 686 680 return false; 687 681 } … … class SMTP 691 685 $code = substr($reply, 0, 3); 692 686 693 687 if ($this->do_debug >= 2) { 694 $this->edebug('S MTP -> FROM SERVER:' . $reply);688 $this->edebug('SERVER -> CLIENT: ' . $reply); 695 689 } 696 690 697 691 if (!in_array($code, (array)$expect)) { 698 692 $this->last_reply = null; 699 693 $this->error = array( 700 "error"=> "$command command failed",701 "smtp_code"=> $code,702 "detail"=> substr($reply, 4)694 'error' => "$command command failed", 695 'smtp_code' => $code, 696 'detail' => substr($reply, 4) 703 697 ); 704 698 if ($this->do_debug >= 1) { 705 699 $this->edebug( 706 'SMTP ->ERROR: ' . $this->error['error'] . ': ' . $reply700 'SMTP ERROR: ' . $this->error['error'] . ': ' . $reply 707 701 ); 708 702 } 709 703 return false; … … class SMTP 729 723 */ 730 724 public function sendAndMail($from) 731 725 { 732 return $this->sendCommand( "SAML", "SAML FROM:$from", 250);726 return $this->sendCommand('SAML', "SAML FROM:$from", 250); 733 727 } 734 728 735 729 /** … … class SMTP 740 734 */ 741 735 public function verify($name) 742 736 { 743 return $this->sendCommand( "VRFY", "VRFY $name", array(250, 251));737 return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); 744 738 } 745 739 746 740 /** … … class SMTP 751 745 */ 752 746 public function noop() 753 747 { 754 return $this->sendCommand( "NOOP", "NOOP", 250);748 return $this->sendCommand('NOOP', 'NOOP', 250); 755 749 } 756 750 757 751 /** 758 752 * Send an SMTP TURN command. 759 753 * This is an optional command for SMTP that this class does not support. 760 * This method is here to make the RFC821 Definition 761 * complete for this class and __may__ be implemented in future754 * This method is here to make the RFC821 Definition complete for this class 755 * and _may_ be implemented in future 762 756 * Implements from rfc 821: TURN <CRLF> 763 757 * @access public 764 758 * @return bool … … class SMTP 769 763 'error' => 'The SMTP TURN command is not implemented' 770 764 ); 771 765 if ($this->do_debug >= 1) { 772 $this->edebug('SMTP ->NOTICE: ' . $this->error['error']);766 $this->edebug('SMTP NOTICE: ' . $this->error['error']); 773 767 } 774 768 return false; 775 769 } … … class SMTP 778 772 * Send raw data to the server. 779 773 * @param string $data The data to send 780 774 * @access public 781 * @return int|bool The number of bytes sent to the server or FALSEon error775 * @return int|bool The number of bytes sent to the server or false on error 782 776 */ 783 777 public function client_send($data) 784 778 { 785 779 if ($this->do_debug >= 1) { 786 $this->edebug("CLIENT -> S MTP: $data");780 $this->edebug("CLIENT -> SERVER: $data"); 787 781 } 788 782 return fwrite($this->smtp_conn, $data); 789 783 } … … class SMTP 819 813 */ 820 814 protected function get_lines() 821 815 { 822 $data = ''; 823 $endtime = 0; 824 // If the connection is bad, give up now 816 // If the connection is bad, give up straight away 825 817 if (!is_resource($this->smtp_conn)) { 826 return $data;818 return ''; 827 819 } 820 $data = ''; 821 $endtime = 0; 828 822 stream_set_timeout($this->smtp_conn, $this->Timeout); 829 823 if ($this->Timelimit > 0) { 830 824 $endtime = time() + $this->Timelimit; … … class SMTP 839 833 if ($this->do_debug >= 4) { 840 834 $this->edebug("SMTP -> get_lines(): \$data is \"$data\""); 841 835 } 842 // if 4th character is a space, we are done reading, break the loop843 if ( substr($str, 3, 1) == ' ') {836 // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen 837 if ((isset($str[3]) and $str[3] == ' ')) { 844 838 break; 845 839 } 846 840 // Timed-out? Log and break … … class SMTP 854 848 break; 855 849 } 856 850 // Now check if reads took too long 857 if ($endtime) { 858 if (time() > $endtime) { 859 if ($this->do_debug >= 4) { 860 $this->edebug( 861 'SMTP -> get_lines(): timelimit reached (' 862 . $this->Timelimit . ' sec)' 863 ); 864 } 865 break; 851 if ($endtime and time() > $endtime) { 852 if ($this->do_debug >= 4) { 853 $this->edebug( 854 'SMTP -> get_lines(): timelimit reached ('. 855 $this->Timelimit . ' sec)' 856 ); 866 857 } 858 break; 867 859 } 868 860 } 869 861 return $data;