Changeset 39725
- Timestamp:
- 01/06/2017 05:42:02 AM (8 years ago)
- Location:
- branches/4.3
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/4.3
- Property svn:mergeinfo changed
/trunk merged: 36083,39645
- Property svn:mergeinfo changed
-
branches/4.3/src/wp-includes/class-phpmailer.php
r33142 r39725 30 30 /** 31 31 * The PHPMailer Version number. 32 * @ typestring33 */ 34 public $Version = '5.2. 10';32 * @var string 33 */ 34 public $Version = '5.2.21'; 35 35 36 36 /** 37 37 * Email priority. 38 * Options: 1 = High, 3 = Normal, 5 = low. 39 * @type integer 40 */ 41 public $Priority = 3; 38 * Options: null (default), 1 = High, 3 = Normal, 5 = low. 39 * When null, the header is not set at all. 40 * @var integer 41 */ 42 public $Priority = null; 42 43 43 44 /** 44 45 * The character set of the message. 45 * @ typestring46 * @var string 46 47 */ 47 48 public $CharSet = 'iso-8859-1'; … … 49 50 /** 50 51 * The MIME Content-type of the message. 51 * @ typestring52 * @var string 52 53 */ 53 54 public $ContentType = 'text/plain'; … … 56 57 * The message encoding. 57 58 * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable". 58 * @ typestring59 * @var string 59 60 */ 60 61 public $Encoding = '8bit'; … … 62 63 /** 63 64 * Holds the most recent mailer error message. 64 * @ typestring65 * @var string 65 66 */ 66 67 public $ErrorInfo = ''; … … 68 69 /** 69 70 * The From email address for the message. 70 * @ typestring71 * @var string 71 72 */ 72 73 public $From = 'root@localhost'; … … 74 75 /** 75 76 * The From name of the message. 76 * @ typestring77 * @var string 77 78 */ 78 79 public $FromName = 'Root User'; … … 81 82 * The Sender email (Return-Path) of the message. 82 83 * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. 83 * @ typestring84 * @var string 84 85 */ 85 86 public $Sender = ''; … … 88 89 * The Return-Path of the message. 89 90 * If empty, it will be set to either From or Sender. 90 * @ typestring91 * @var string 91 92 * @deprecated Email senders should never set a return-path header; 92 93 * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. … … 97 98 /** 98 99 * The Subject of the message. 99 * @ typestring100 * @var string 100 101 */ 101 102 public $Subject = ''; … … 104 105 * An HTML or plain text message body. 105 106 * If HTML then call isHTML(true). 106 * @ typestring107 * @var string 107 108 */ 108 109 public $Body = ''; … … 113 114 * capability such as mutt & Eudora. 114 115 * Clients that can read HTML will view the normal Body. 115 * @ typestring116 * @var string 116 117 */ 117 118 public $AltBody = ''; … … 123 124 * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ 124 125 * @link http://kigkonsult.se/iCalcreator/ 125 * @ typestring126 * @var string 126 127 */ 127 128 public $Ical = ''; … … 130 131 * The complete compiled MIME message body. 131 132 * @access protected 132 * @ typestring133 * @var string 133 134 */ 134 135 protected $MIMEBody = ''; … … 136 137 /** 137 138 * The complete compiled MIME message headers. 138 * @ typestring139 * @var string 139 140 * @access protected 140 141 */ … … 143 144 /** 144 145 * Extra headers that createHeader() doesn't fold in. 145 * @ typestring146 * @var string 146 147 * @access protected 147 148 */ … … 151 152 * Word-wrap the message body to this number of chars. 152 153 * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. 153 * @ typeinteger154 * @var integer 154 155 */ 155 156 public $WordWrap = 0; … … 158 159 * Which method to use to send mail. 159 160 * Options: "mail", "sendmail", or "smtp". 160 * @ typestring161 * @var string 161 162 */ 162 163 public $Mailer = 'mail'; … … 164 165 /** 165 166 * The path to the sendmail program. 166 * @ typestring167 * @var string 167 168 */ 168 169 public $Sendmail = '/usr/sbin/sendmail'; … … 171 172 * Whether mail() uses a fully sendmail-compatible MTA. 172 173 * One which supports sendmail's "-oi -f" options. 173 * @ typeboolean174 * @var boolean 174 175 */ 175 176 public $UseSendmailOptions = true; … … 178 179 * Path to PHPMailer plugins. 179 180 * Useful if the SMTP class is not in the PHP include path. 180 * @ typestring181 * @var string 181 182 * @deprecated Should not be needed now there is an autoloader. 182 183 */ … … 184 185 185 186 /** 186 * The email address that a reading confirmation should be sent to .187 * @ typestring187 * The email address that a reading confirmation should be sent to, also known as read receipt. 188 * @var string 188 189 */ 189 190 public $ConfirmReadingTo = ''; 190 191 191 192 /** 192 * The hostname to use in Message-Id and Received headers193 * and as default HELO string.194 * If empty, the value returned195 * by SERVER_NAME is used or'localhost.localdomain'.196 * @ typestring193 * The hostname to use in the Message-ID header and as default HELO string. 194 * If empty, PHPMailer attempts to find one with, in order, 195 * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value 196 * 'localhost.localdomain'. 197 * @var string 197 198 */ 198 199 public $Hostname = ''; 199 200 200 201 /** 201 * An ID to be used in the Message-I dheader.202 * An ID to be used in the Message-ID header. 202 203 * If empty, a unique id will be generated. 203 * @type string 204 * You can set your own, but it must be in the format "<id@domain>", 205 * as defined in RFC5322 section 3.6.4 or it will be ignored. 206 * @see https://tools.ietf.org/html/rfc5322#section-3.6.4 207 * @var string 204 208 */ 205 209 public $MessageID = ''; … … 208 212 * The message Date to be used in the Date header. 209 213 * If empty, the current date will be added. 210 * @ typestring214 * @var string 211 215 */ 212 216 public $MessageDate = ''; … … 221 225 * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). 222 226 * Hosts will be tried in order. 223 * @ typestring227 * @var string 224 228 */ 225 229 public $Host = 'localhost'; … … 227 231 /** 228 232 * The default SMTP server port. 229 * @ typeinteger233 * @var integer 230 234 * @TODO Why is this needed when the SMTP class takes care of it? 231 235 */ … … 234 238 /** 235 239 * The SMTP HELO of the message. 236 * Default is $Hostname. 237 * @type string 240 * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find 241 * one with the same method described above for $Hostname. 242 * @var string 238 243 * @see PHPMailer::$Hostname 239 244 */ … … 243 248 * What kind of encryption to use on the SMTP connection. 244 249 * Options: '', 'ssl' or 'tls' 245 * @ typestring250 * @var string 246 251 */ 247 252 public $SMTPSecure = ''; … … 251 256 * even if `SMTPSecure` is not set to 'tls'. 252 257 * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. 253 * @ typeboolean258 * @var boolean 254 259 */ 255 260 public $SMTPAutoTLS = true; … … 258 263 * Whether to use SMTP authentication. 259 264 * Uses the Username and Password properties. 260 * @ typeboolean265 * @var boolean 261 266 * @see PHPMailer::$Username 262 267 * @see PHPMailer::$Password … … 266 271 /** 267 272 * Options array passed to stream_context_create when connecting via SMTP. 268 * @ typearray273 * @var array 269 274 */ 270 275 public $SMTPOptions = array(); … … 272 277 /** 273 278 * SMTP username. 274 * @ typestring279 * @var string 275 280 */ 276 281 public $Username = ''; … … 278 283 /** 279 284 * SMTP password. 280 * @ typestring285 * @var string 281 286 */ 282 287 public $Password = ''; … … 284 289 /** 285 290 * SMTP auth type. 286 * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5287 * @ typestring291 * Options are CRAM-MD5, LOGIN, PLAIN, attempted in that order if not specified 292 * @var string 288 293 */ 289 294 public $AuthType = ''; … … 292 297 * SMTP realm. 293 298 * Used for NTLM auth 294 * @ typestring299 * @var string 295 300 */ 296 301 public $Realm = ''; … … 299 304 * SMTP workstation. 300 305 * Used for NTLM auth 301 * @ typestring306 * @var string 302 307 */ 303 308 public $Workstation = ''; … … 306 311 * The SMTP server timeout in seconds. 307 312 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 308 * @ typeinteger313 * @var integer 309 314 */ 310 315 public $Timeout = 300; … … 319 324 * * `3` As 2 plus connection status 320 325 * * `4` Low-level data output 321 * @ typeinteger326 * @var integer 322 327 * @see SMTP::$do_debug 323 328 */ … … 335 340 * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; 336 341 * </code> 337 * @ typestring|callable342 * @var string|callable 338 343 * @see SMTP::$Debugoutput 339 344 */ … … 344 349 * If this is set to true then to close the connection 345 350 * requires an explicit call to smtpClose(). 346 * @ typeboolean351 * @var boolean 347 352 */ 348 353 public $SMTPKeepAlive = false; … … 351 356 * Whether to split multiple to addresses into multiple messages 352 357 * or send them all in one message. 353 * @type boolean 358 * Only supported in `mail` and `sendmail` transports, not in SMTP. 359 * @var boolean 354 360 */ 355 361 public $SingleTo = false; … … 357 363 /** 358 364 * Storage for addresses when SingleTo is enabled. 359 * @ typearray365 * @var array 360 366 * @TODO This should really not be public 361 367 */ … … 365 371 * Whether to generate VERP addresses on send. 366 372 * Only applicable when sending via SMTP. 367 * @link http ://en.wikipedia.org/wiki/Variable_envelope_return_path373 * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path 368 374 * @link http://www.postfix.org/VERP_README.html Postfix VERP info 369 * @ typeboolean375 * @var boolean 370 376 */ 371 377 public $do_verp = false; … … 373 379 /** 374 380 * Whether to allow sending messages with an empty body. 375 * @ typeboolean381 * @var boolean 376 382 */ 377 383 public $AllowEmpty = false; … … 381 387 * @note The default remains "\n". We force CRLF where we know 382 388 * it must be used via self::CRLF. 383 * @ typestring389 * @var string 384 390 */ 385 391 public $LE = "\n"; … … 387 393 /** 388 394 * DKIM selector. 389 * @ typestring395 * @var string 390 396 */ 391 397 public $DKIM_selector = ''; … … 393 399 /** 394 400 * DKIM Identity. 395 * Usually the email address used as the source of the email 396 * @ typestring401 * Usually the email address used as the source of the email. 402 * @var string 397 403 */ 398 404 public $DKIM_identity = ''; … … 401 407 * DKIM passphrase. 402 408 * Used if your key is encrypted. 403 * @ typestring409 * @var string 404 410 */ 405 411 public $DKIM_passphrase = ''; … … 408 414 * DKIM signing domain name. 409 415 * @example 'example.com' 410 * @ typestring416 * @var string 411 417 */ 412 418 public $DKIM_domain = ''; … … 414 420 /** 415 421 * DKIM private key file path. 416 * @ typestring422 * @var string 417 423 */ 418 424 public $DKIM_private = ''; 425 426 /** 427 * DKIM private key string. 428 * If set, takes precedence over `$DKIM_private`. 429 * @var string 430 */ 431 public $DKIM_private_string = ''; 419 432 420 433 /** … … 434 447 * string $body the email body 435 448 * string $from email address of sender 436 * @ typestring449 * @var string 437 450 */ 438 451 public $action_function = ''; … … 441 454 * What to put in the X-Mailer header. 442 455 * Options: An empty string for PHPMailer default, whitespace for none, or a string to use 443 * @ typestring456 * @var string 444 457 */ 445 458 public $XMailer = ''; 446 459 447 460 /** 461 * Which validator to use by default when validating email addresses. 462 * May be a callable to inject your own validator, but there are several built-in validators. 463 * @see PHPMailer::validateAddress() 464 * @var string|callable 465 * @static 466 */ 467 public static $validator = 'auto'; 468 469 /** 448 470 * An instance of the SMTP sender class. 449 * @ typeSMTP471 * @var SMTP 450 472 * @access protected 451 473 */ … … 453 475 454 476 /** 455 * The array of 'to' addresses.456 * @ typearray477 * The array of 'to' names and addresses. 478 * @var array 457 479 * @access protected 458 480 */ … … 460 482 461 483 /** 462 * The array of 'cc' addresses.463 * @ typearray484 * The array of 'cc' names and addresses. 485 * @var array 464 486 * @access protected 465 487 */ … … 467 489 468 490 /** 469 * The array of 'bcc' addresses.470 * @ typearray491 * The array of 'bcc' names and addresses. 492 * @var array 471 493 * @access protected 472 494 */ … … 475 497 /** 476 498 * The array of reply-to names and addresses. 477 * @ typearray499 * @var array 478 500 * @access protected 479 501 */ … … 483 505 * An array of all kinds of addresses. 484 506 * Includes all of $to, $cc, $bcc 485 * @ typearray507 * @var array 486 508 * @access protected 509 * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc 487 510 */ 488 511 protected $all_recipients = array(); 489 512 490 513 /** 514 * An array of names and addresses queued for validation. 515 * In send(), valid and non duplicate entries are moved to $all_recipients 516 * and one of $to, $cc, or $bcc. 517 * This array is used only for addresses with IDN. 518 * @var array 519 * @access protected 520 * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc 521 * @see PHPMailer::$all_recipients 522 */ 523 protected $RecipientsQueue = array(); 524 525 /** 526 * An array of reply-to names and addresses queued for validation. 527 * In send(), valid and non duplicate entries are moved to $ReplyTo. 528 * This array is used only for addresses with IDN. 529 * @var array 530 * @access protected 531 * @see PHPMailer::$ReplyTo 532 */ 533 protected $ReplyToQueue = array(); 534 535 /** 491 536 * The array of attachments. 492 * @ typearray537 * @var array 493 538 * @access protected 494 539 */ … … 497 542 /** 498 543 * The array of custom headers. 499 * @ typearray544 * @var array 500 545 * @access protected 501 546 */ … … 504 549 /** 505 550 * The most recent Message-ID (including angular brackets). 506 * @ typestring551 * @var string 507 552 * @access protected 508 553 */ … … 511 556 /** 512 557 * The message's MIME type. 513 * @ typestring558 * @var string 514 559 * @access protected 515 560 */ … … 518 563 /** 519 564 * The array of MIME boundary strings. 520 * @ typearray565 * @var array 521 566 * @access protected 522 567 */ … … 525 570 /** 526 571 * The array of available languages. 527 * @ typearray572 * @var array 528 573 * @access protected 529 574 */ … … 532 577 /** 533 578 * The number of errors encountered. 534 * @ typeinteger579 * @var integer 535 580 * @access protected 536 581 */ … … 539 584 /** 540 585 * The S/MIME certificate file path. 541 * @ typestring586 * @var string 542 587 * @access protected 543 588 */ … … 546 591 /** 547 592 * The S/MIME key file path. 548 * @ typestring593 * @var string 549 594 * @access protected 550 595 */ … … 553 598 /** 554 599 * The optional S/MIME extra certificates ("CA Chain") file path. 555 * @ typestring600 * @var string 556 601 * @access protected 557 602 */ … … 561 606 * The S/MIME password for the key. 562 607 * Used only if the key is encrypted. 563 * @ typestring608 * @var string 564 609 * @access protected 565 610 */ … … 568 613 /** 569 614 * Whether to throw exceptions for errors. 570 * @ typeboolean615 * @var boolean 571 616 * @access protected 572 617 */ … … 575 620 /** 576 621 * Unique ID used for message ID and boundaries. 577 * @ typestring622 * @var string 578 623 * @access protected 579 624 */ … … 602 647 /** 603 648 * The maximum line length allowed by RFC 2822 section 2.1.1 604 * @ typeinteger649 * @var integer 605 650 */ 606 651 const MAX_LINE_LENGTH = 998; … … 610 655 * @param boolean $exceptions Should we throw external exceptions? 611 656 */ 612 public function __construct($exceptions = false) 613 { 614 $this->exceptions = (boolean)$exceptions; 657 public function __construct($exceptions = null) 658 { 659 if ($exceptions !== null) { 660 $this->exceptions = (boolean)$exceptions; 661 } 615 662 } 616 663 … … 621 668 { 622 669 //Close any open SMTP connection nicely 623 if ($this->Mailer == 'smtp') { 624 $this->smtpClose(); 625 } 670 $this->smtpClose(); 626 671 } 627 672 … … 647 692 $subject = $this->encodeHeader($this->secureHeader($subject)); 648 693 } 649 if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { 694 695 //Can't use additional_parameters in safe_mode, calling mail() with null params breaks 696 //@link http://php.net/manual/en/function.mail.php 697 if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) { 650 698 $result = @mail($to, $subject, $body, $header); 651 699 } else { … … 654 702 return $result; 655 703 } 656 657 704 /** 658 705 * Output debugging info via user-defined method. … … 689 736 default: 690 737 //Normalize line breaks 691 $str = preg_replace('/ (\r\n|\r|\n)/ms', "\n", $str);738 $str = preg_replace('/\r\n?/ms', "\n", $str); 692 739 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( 693 740 "\n", … … 764 811 /** 765 812 * Add a "To" address. 766 * @param string $address 813 * @param string $address The email address to send to 767 814 * @param string $name 768 * @return boolean true on success, false if address already used 815 * @return boolean true on success, false if address already used or invalid in some way 769 816 */ 770 817 public function addAddress($address, $name = '') 771 818 { 772 return $this->add AnAddress('to', $address, $name);819 return $this->addOrEnqueueAnAddress('to', $address, $name); 773 820 } 774 821 … … 776 823 * Add a "CC" address. 777 824 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. 778 * @param string $address 825 * @param string $address The email address to send to 779 826 * @param string $name 780 * @return boolean true on success, false if address already used 827 * @return boolean true on success, false if address already used or invalid in some way 781 828 */ 782 829 public function addCC($address, $name = '') 783 830 { 784 return $this->add AnAddress('cc', $address, $name);831 return $this->addOrEnqueueAnAddress('cc', $address, $name); 785 832 } 786 833 … … 788 835 * Add a "BCC" address. 789 836 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. 790 * @param string $address 837 * @param string $address The email address to send to 791 838 * @param string $name 792 * @return boolean true on success, false if address already used 839 * @return boolean true on success, false if address already used or invalid in some way 793 840 */ 794 841 public function addBCC($address, $name = '') 795 842 { 796 return $this->add AnAddress('bcc', $address, $name);797 } 798 799 /** 800 * Add a "Reply- to" address.801 * @param string $address 843 return $this->addOrEnqueueAnAddress('bcc', $address, $name); 844 } 845 846 /** 847 * Add a "Reply-To" address. 848 * @param string $address The email address to reply to 802 849 * @param string $name 803 * @return boolean 850 * @return boolean true on success, false if address already used or invalid in some way 804 851 */ 805 852 public function addReplyTo($address, $name = '') 806 853 { 807 return $this->addAnAddress('Reply-To', $address, $name); 808 } 809 810 /** 811 * Add an address to one of the recipient arrays. 812 * Addresses that have been added already return false, but do not throw exceptions 813 * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' 814 * @param string $address The email address to send to 854 return $this->addOrEnqueueAnAddress('Reply-To', $address, $name); 855 } 856 857 /** 858 * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer 859 * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still 860 * be modified after calling this function), addition of such addresses is delayed until send(). 861 * Addresses that have been added already return false, but do not throw exceptions. 862 * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' 863 * @param string $address The email address to send, resp. to reply to 815 864 * @param string $name 816 865 * @throws phpmailerException … … 818 867 * @access protected 819 868 */ 820 protected function addAnAddress($kind, $address, $name = '') 821 { 822 if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { 823 $this->setError($this->lang('Invalid recipient array') . ': ' . $kind); 824 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind); 825 if ($this->exceptions) { 826 throw new phpmailerException('Invalid recipient array: ' . $kind); 827 } 828 return false; 829 } 869 protected function addOrEnqueueAnAddress($kind, $address, $name) 870 { 830 871 $address = trim($address); 831 872 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 873 if (($pos = strrpos($address, '@')) === false) { 874 // At-sign is misssing. 875 $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; 876 $this->setError($error_message); 877 $this->edebug($error_message); 878 if ($this->exceptions) { 879 throw new phpmailerException($error_message); 880 } 881 return false; 882 } 883 $params = array($kind, $address, $name); 884 // Enqueue addresses with IDN until we know the PHPMailer::$CharSet. 885 if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) { 886 if ($kind != 'Reply-To') { 887 if (!array_key_exists($address, $this->RecipientsQueue)) { 888 $this->RecipientsQueue[$address] = $params; 889 return true; 890 } 891 } else { 892 if (!array_key_exists($address, $this->ReplyToQueue)) { 893 $this->ReplyToQueue[$address] = $params; 894 return true; 895 } 896 } 897 return false; 898 } 899 // Immediately add standard addresses without IDN. 900 return call_user_func_array(array($this, 'addAnAddress'), $params); 901 } 902 903 /** 904 * Add an address to one of the recipient arrays or to the ReplyTo array. 905 * Addresses that have been added already return false, but do not throw exceptions. 906 * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' 907 * @param string $address The email address to send, resp. to reply to 908 * @param string $name 909 * @throws phpmailerException 910 * @return boolean true on success, false if address already used or invalid in some way 911 * @access protected 912 */ 913 protected function addAnAddress($kind, $address, $name = '') 914 { 915 if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) { 916 $error_message = $this->lang('Invalid recipient kind: ') . $kind; 917 $this->setError($error_message); 918 $this->edebug($error_message); 919 if ($this->exceptions) { 920 throw new phpmailerException($error_message); 921 } 922 return false; 923 } 832 924 if (!$this->validateAddress($address)) { 833 $this->setError($this->lang('invalid_address') . ': ' . $address); 834 $this->edebug($this->lang('invalid_address') . ': ' . $address); 925 $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; 926 $this->setError($error_message); 927 $this->edebug($error_message); 835 928 if ($this->exceptions) { 836 throw new phpmailerException($ this->lang('invalid_address') . ': ' . $address);929 throw new phpmailerException($error_message); 837 930 } 838 931 return false; 839 932 } 840 933 if ($kind != 'Reply-To') { 841 if (! isset($this->all_recipients[strtolower($address)])) {934 if (!array_key_exists(strtolower($address), $this->all_recipients)) { 842 935 array_push($this->$kind, array($address, $name)); 843 936 $this->all_recipients[strtolower($address)] = true; … … 851 944 } 852 945 return false; 946 } 947 948 /** 949 * Parse and validate a string containing one or more RFC822-style comma-separated email addresses 950 * of the form "display name <address>" into an array of name/address pairs. 951 * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. 952 * Note that quotes in the name part are removed. 953 * @param string $addrstr The address list string 954 * @param bool $useimap Whether to use the IMAP extension to parse the list 955 * @return array 956 * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation 957 */ 958 public function parseAddresses($addrstr, $useimap = true) 959 { 960 $addresses = array(); 961 if ($useimap and function_exists('imap_rfc822_parse_adrlist')) { 962 //Use this built-in parser if it's available 963 $list = imap_rfc822_parse_adrlist($addrstr, ''); 964 foreach ($list as $address) { 965 if ($address->host != '.SYNTAX-ERROR.') { 966 if ($this->validateAddress($address->mailbox . '@' . $address->host)) { 967 $addresses[] = array( 968 'name' => (property_exists($address, 'personal') ? $address->personal : ''), 969 'address' => $address->mailbox . '@' . $address->host 970 ); 971 } 972 } 973 } 974 } else { 975 //Use this simpler parser 976 $list = explode(',', $addrstr); 977 foreach ($list as $address) { 978 $address = trim($address); 979 //Is there a separate name part? 980 if (strpos($address, '<') === false) { 981 //No separate name, just use the whole thing 982 if ($this->validateAddress($address)) { 983 $addresses[] = array( 984 'name' => '', 985 'address' => $address 986 ); 987 } 988 } else { 989 list($name, $email) = explode('<', $address); 990 $email = trim(str_replace('>', '', $email)); 991 if ($this->validateAddress($email)) { 992 $addresses[] = array( 993 'name' => trim(str_replace(array('"', "'"), '', $name)), 994 'address' => $email 995 ); 996 } 997 } 998 } 999 } 1000 return $addresses; 853 1001 } 854 1002 … … 865 1013 $address = trim($address); 866 1014 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 867 if (!$this->validateAddress($address)) { 868 $this->setError($this->lang('invalid_address') . ': ' . $address); 869 $this->edebug($this->lang('invalid_address') . ': ' . $address); 1015 // Don't validate now addresses with IDN. Will be done in send(). 1016 if (($pos = strrpos($address, '@')) === false or 1017 (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and 1018 !$this->validateAddress($address)) { 1019 $error_message = $this->lang('invalid_address') . " (setFrom) $address"; 1020 $this->setError($error_message); 1021 $this->edebug($error_message); 870 1022 if ($this->exceptions) { 871 throw new phpmailerException($ this->lang('invalid_address') . ': ' . $address);1023 throw new phpmailerException($error_message); 872 1024 } 873 1025 return false; … … 898 1050 * Check that a string looks like an email address. 899 1051 * @param string $address The email address to check 900 * @param string $patternselect A selector for the validation pattern to use :901 * * `auto` Pick strictest oneautomatically;1052 * @param string|callable $patternselect A selector for the validation pattern to use : 1053 * * `auto` Pick best pattern automatically; 902 1054 * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; 903 1055 * * `pcre` Use old PCRE implementation; 904 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains;1056 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; 905 1057 * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. 906 1058 * * `noregex` Don't use a regex: super fast, really dumb. 1059 * Alternatively you may pass in a callable to inject your own validator, for example: 1060 * PHPMailer::validateAddress('user@example.com', function($address) { 1061 * return (strpos($address, '@') !== false); 1062 * }); 1063 * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator. 907 1064 * @return boolean 908 1065 * @static 909 1066 * @access public 910 1067 */ 911 public static function validateAddress($address, $patternselect = 'auto') 912 { 1068 public static function validateAddress($address, $patternselect = null) 1069 { 1070 if (is_null($patternselect)) { 1071 $patternselect = self::$validator; 1072 } 1073 if (is_callable($patternselect)) { 1074 return call_user_func($patternselect, $address); 1075 } 1076 //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 1077 if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { 1078 return false; 1079 } 913 1080 if (!$patternselect or $patternselect == 'auto') { 914 1081 //Check this constant first so it works when extension_loaded() is disabled by safe mode … … 991 1158 992 1159 /** 1160 * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the 1161 * "intl" and "mbstring" PHP extensions. 1162 * @return bool "true" if required functions for IDN support are present 1163 */ 1164 public function idnSupported() 1165 { 1166 // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2. 1167 return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding'); 1168 } 1169 1170 /** 1171 * Converts IDN in given email address to its ASCII form, also known as punycode, if possible. 1172 * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet. 1173 * This function silently returns unmodified address if: 1174 * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form) 1175 * - Conversion to punycode is impossible (e.g. required PHP functions are not available) 1176 * or fails for any reason (e.g. domain has characters not allowed in an IDN) 1177 * @see PHPMailer::$CharSet 1178 * @param string $address The email address to convert 1179 * @return string The encoded address in ASCII form 1180 */ 1181 public function punyencodeAddress($address) 1182 { 1183 // Verify we have required functions, CharSet, and at-sign. 1184 if ($this->idnSupported() and 1185 !empty($this->CharSet) and 1186 ($pos = strrpos($address, '@')) !== false) { 1187 $domain = substr($address, ++$pos); 1188 // Verify CharSet string is a valid one, and domain properly encoded in this CharSet. 1189 if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) { 1190 $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet); 1191 if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ? 1192 idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) : 1193 idn_to_ascii($domain)) !== false) { 1194 return substr($address, 0, $pos) . $punycode; 1195 } 1196 } 1197 } 1198 return $address; 1199 } 1200 1201 /** 993 1202 * Create a message and send it. 994 1203 * Uses the sending method specified by $Mailer. … … 1021 1230 { 1022 1231 try { 1232 $this->error_count = 0; // Reset errors 1023 1233 $this->mailHeader = ''; 1234 1235 // Dequeue recipient and Reply-To addresses with IDN 1236 foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) { 1237 $params[1] = $this->punyencodeAddress($params[1]); 1238 call_user_func_array(array($this, 'addAnAddress'), $params); 1239 } 1024 1240 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { 1025 1241 throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); 1026 1242 } 1027 1243 1244 // Validate From, Sender, and ConfirmReadingTo addresses 1245 foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) { 1246 $this->$address_kind = trim($this->$address_kind); 1247 if (empty($this->$address_kind)) { 1248 continue; 1249 } 1250 $this->$address_kind = $this->punyencodeAddress($this->$address_kind); 1251 if (!$this->validateAddress($this->$address_kind)) { 1252 $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind; 1253 $this->setError($error_message); 1254 $this->edebug($error_message); 1255 if ($this->exceptions) { 1256 throw new phpmailerException($error_message); 1257 } 1258 return false; 1259 } 1260 } 1261 1028 1262 // Set whether the message is multipart/alternative 1029 if ( !empty($this->AltBody)) {1263 if ($this->alternativeExists()) { 1030 1264 $this->ContentType = 'multipart/alternative'; 1031 1265 } 1032 1266 1033 $this->error_count = 0; // Reset errors1034 1267 $this->setMessageType(); 1035 1268 // Refuse to send an empty message unless we are specifically allowing it … … 1062 1295 // Sign with DKIM if enabled 1063 1296 if (!empty($this->DKIM_domain) 1064 && !empty($this->DKIM_private)1065 1297 && !empty($this->DKIM_selector) 1066 && file_exists($this->DKIM_private)) { 1298 && (!empty($this->DKIM_private_string) 1299 || (!empty($this->DKIM_private) && file_exists($this->DKIM_private)) 1300 ) 1301 ) { 1067 1302 $header_dkim = $this->DKIM_Add( 1068 1303 $this->MIMEHeader . $this->mailHeader, … … 1130 1365 protected function sendmailSend($header, $body) 1131 1366 { 1132 if ($this->Sender != '') { 1367 // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. 1368 if (!empty($this->Sender) and self::isShellSafe($this->Sender)) { 1133 1369 if ($this->Mailer == 'qmail') { 1134 $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));1370 $sendmailFmt = '%s -f%s'; 1135 1371 } else { 1136 $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));1372 $sendmailFmt = '%s -oi -f%s -t'; 1137 1373 } 1138 1374 } else { 1139 1375 if ($this->Mailer == 'qmail') { 1140 $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));1376 $sendmailFmt = '%s'; 1141 1377 } else { 1142 $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); 1143 } 1144 } 1378 $sendmailFmt = '%s -oi -t'; 1379 } 1380 } 1381 1382 // TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing. 1383 $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender); 1384 1145 1385 if ($this->SingleTo) { 1146 1386 foreach ($this->SingleToArray as $toAddr) { … … 1172 1412 fputs($mail, $body); 1173 1413 $result = pclose($mail); 1174 $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); 1414 $this->doCallback( 1415 ($result == 0), 1416 $this->to, 1417 $this->cc, 1418 $this->bcc, 1419 $this->Subject, 1420 $body, 1421 $this->From 1422 ); 1175 1423 if ($result != 0) { 1176 1424 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 1177 1425 } 1178 1426 } 1427 return true; 1428 } 1429 1430 /** 1431 * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters. 1432 * 1433 * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. 1434 * @param string $string The string to be validated 1435 * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report 1436 * @access protected 1437 * @return boolean 1438 */ 1439 protected static function isShellSafe($string) 1440 { 1441 // Future-proof 1442 if (escapeshellcmd($string) !== $string 1443 or !in_array(escapeshellarg($string), array("'$string'", "\"$string\"")) 1444 ) { 1445 return false; 1446 } 1447 1448 $length = strlen($string); 1449 1450 for ($i = 0; $i < $length; $i++) { 1451 $c = $string[$i]; 1452 1453 // All other characters have a special meaning in at least one common shell, including = and +. 1454 // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here. 1455 // Note that this does permit non-Latin alphanumeric characters based on the current locale. 1456 if (!ctype_alnum($c) && strpos('@_-.', $c) === false) { 1457 return false; 1458 } 1459 } 1460 1179 1461 return true; 1180 1462 } … … 1197 1479 $to = implode(', ', $toArr); 1198 1480 1199 if (empty($this->Sender)) { 1200 $params = ' '; 1201 } else { 1202 $params = sprintf('-f%s', $this->Sender); 1203 } 1204 if ($this->Sender != '' and !ini_get('safe_mode')) { 1481 $params = null; 1482 //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver 1483 if (!empty($this->Sender) and $this->validateAddress($this->Sender)) { 1484 // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. 1485 if (self::isShellSafe($this->Sender)) { 1486 $params = sprintf('-f%s', $this->Sender); 1487 } 1488 } 1489 if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) { 1205 1490 $old_from = ini_get('sendmail_from'); 1206 1491 ini_set('sendmail_from', $this->Sender); 1207 1492 } 1208 1493 $result = false; 1209 if ($this->SingleTo &&count($toArr) > 1) {1494 if ($this->SingleTo and count($toArr) > 1) { 1210 1495 foreach ($toArr as $toAddr) { 1211 1496 $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); … … 1257 1542 throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); 1258 1543 } 1259 if ('' == $this->Sender) { 1544 if (!empty($this->Sender) and $this->validateAddress($this->Sender)) { 1545 $smtp_from = $this->Sender; 1546 } else { 1260 1547 $smtp_from = $this->From; 1261 } else {1262 $smtp_from = $this->Sender;1263 1548 } 1264 1549 if (!$this->smtp->mail($smtp_from)) { … … 1314 1599 * @return boolean 1315 1600 */ 1316 public function smtpConnect($options = array())1601 public function smtpConnect($options = null) 1317 1602 { 1318 1603 if (is_null($this->smtp)) { 1319 1604 $this->smtp = $this->getSMTPInstance(); 1605 } 1606 1607 //If no options are provided, use whatever is set in the instance 1608 if (is_null($options)) { 1609 $options = $this->SMTPOptions; 1320 1610 } 1321 1611 … … 1389 1679 throw new phpmailerException($this->lang('connect_host')); 1390 1680 } 1391 // We must resend HELO after tlsnegotiation1681 // We must resend EHLO after TLS negotiation 1392 1682 $this->smtp->hello($hello); 1393 1683 } … … 1428 1718 public function smtpClose() 1429 1719 { 1430 if ( $this->smtp !== null) {1720 if (is_a($this->smtp, 'SMTP')) { 1431 1721 if ($this->smtp->connected()) { 1432 1722 $this->smtp->quit(); … … 1447 1737 public function setLanguage($langcode = 'en', $lang_path = '') 1448 1738 { 1739 // Backwards compatibility for renamed language codes 1740 $renamed_langcodes = array( 1741 'br' => 'pt_br', 1742 'cz' => 'cs', 1743 'dk' => 'da', 1744 'no' => 'nb', 1745 'se' => 'sv', 1746 ); 1747 1748 if (isset($renamed_langcodes[$langcode])) { 1749 $langcode = $renamed_langcodes[$langcode]; 1750 } 1751 1449 1752 // Define full set of translatable strings in English 1450 1753 $PHPMAILER_LANG = array( … … 1459 1762 'from_failed' => 'The following From address failed: ', 1460 1763 'instantiate' => 'Could not instantiate mail function.', 1461 'invalid_address' => 'Invalid address ',1764 'invalid_address' => 'Invalid address: ', 1462 1765 'mailer_not_supported' => ' mailer is not supported.', 1463 1766 'provide_address' => 'You must provide at least one recipient email address.', … … 1472 1775 // Calculate an absolute path so it can work if CWD is not here 1473 1776 $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; 1777 } 1778 //Validate $langcode 1779 if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) { 1780 $langcode = 'en'; 1474 1781 } 1475 1782 $foundlang = true; … … 1724 2031 $result .= $this->headerLine('Date', $this->MessageDate); 1725 2032 1726 1727 2033 // To be created automatically by mail() 1728 2034 if ($this->SingleTo) { … … 1767 2073 } 1768 2074 1769 if ($this->MessageID != '') { 2075 // Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4 2076 // https://tools.ietf.org/html/rfc5322#section-3.6.4 2077 if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) { 1770 2078 $this->lastMessageID = $this->MessageID; 1771 2079 } else { 1772 $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this-> ServerHostname());2080 $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname()); 1773 2081 } 1774 2082 $result .= $this->headerLine('Message-ID', $this->lastMessageID); 1775 $result .= $this->headerLine('X-Priority', $this->Priority); 2083 if (!is_null($this->Priority)) { 2084 $result .= $this->headerLine('X-Priority', $this->Priority); 2085 } 1776 2086 if ($this->XMailer == '') { 1777 2087 $result .= $this->headerLine( 1778 2088 'X-Mailer', 1779 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer /)'2089 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer)' 1780 2090 ); 1781 2091 } else { … … 1787 2097 1788 2098 if ($this->ConfirmReadingTo != '') { 1789 $result .= $this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo). '>');2099 $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>'); 1790 2100 } 1791 2101 … … 1867 2177 public function getSentMIMEMessage() 1868 2178 { 1869 return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; 2179 return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody; 2180 } 2181 2182 /** 2183 * Create unique ID 2184 * @return string 2185 */ 2186 protected function generateId() { 2187 return md5(uniqid(time())); 1870 2188 } 1871 2189 … … 1881 2199 $body = ''; 1882 2200 //Create unique IDs and preset boundaries 1883 $this->uniqueid = md5(uniqid(time()));2201 $this->uniqueid = $this->generateId(); 1884 2202 $this->boundary[1] = 'b1_' . $this->uniqueid; 1885 2203 $this->boundary[2] = 'b2_' . $this->uniqueid; … … 1897 2215 if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { 1898 2216 $bodyEncoding = '7bit'; 2217 //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit 1899 2218 $bodyCharSet = 'us-ascii'; 1900 2219 } 1901 //If lines are too long, change to quoted-printable transfer encoding1902 if (self::hasLineLongerThanMax($this->Body)) {1903 $this->Encoding = 'quoted-printable';2220 //If lines are too long, and we're not already using an encoding that will shorten them, 2221 //change to quoted-printable transfer encoding for the body part only 2222 if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) { 1904 2223 $bodyEncoding = 'quoted-printable'; 1905 2224 } … … 1910 2229 if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { 1911 2230 $altBodyEncoding = '7bit'; 2231 //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit 1912 2232 $altBodyCharSet = 'us-ascii'; 1913 2233 } 1914 //If lines are too long, change to quoted-printable transfer encoding 1915 if (self::hasLineLongerThanMax($this->AltBody)) { 2234 //If lines are too long, and we're not already using an encoding that will shorten them, 2235 //change to quoted-printable transfer encoding for the alt body part only 2236 if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) { 1916 2237 $altBodyEncoding = 'quoted-printable'; 1917 2238 } … … 2016 2337 break; 2017 2338 default: 2018 // catch case 'plain' and case '' 2019 $body .= $this->encodeString($this->Body, $bodyEncoding); 2339 // Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types 2340 //Reset the `Encoding` property in case we changed it for line length reasons 2341 $this->Encoding = $bodyEncoding; 2342 $body .= $this->encodeString($this->Body, $this->Encoding); 2020 2343 break; 2021 2344 } … … 2123 2446 /** 2124 2447 * Set the message type. 2125 * PHPMailer only supports some preset message types, 2126 * not arbitrary MIME structures. 2448 * PHPMailer only supports some preset message types, not arbitrary MIME structures. 2127 2449 * @access protected 2128 2450 * @return void … … 2142 2464 $this->message_type = implode('_', $type); 2143 2465 if ($this->message_type == '') { 2466 //The 'plain' message_type refers to the message having a single body element, not that it is plain-text 2144 2467 $this->message_type = 'plain'; 2145 2468 } … … 2267 2590 $disposition = $attachment[6]; 2268 2591 $cid = $attachment[7]; 2269 if ($disposition == 'inline' && isset($cidUniq[$cid])) {2592 if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) { 2270 2593 continue; 2271 2594 } … … 2273 2596 2274 2597 $mime[] = sprintf('--%s%s', $boundary, $this->LE); 2275 $mime[] = sprintf( 2276 'Content-Type: %s; name="%s"%s', 2277 $type, 2278 $this->encodeHeader($this->secureHeader($name)), 2279 $this->LE 2280 ); 2598 //Only include a filename property if we have one 2599 if (!empty($name)) { 2600 $mime[] = sprintf( 2601 'Content-Type: %s; name="%s"%s', 2602 $type, 2603 $this->encodeHeader($this->secureHeader($name)), 2604 $this->LE 2605 ); 2606 } else { 2607 $mime[] = sprintf( 2608 'Content-Type: %s%s', 2609 $type, 2610 $this->LE 2611 ); 2612 } 2281 2613 // RFC1341 part 5 says 7bit is assumed if not specified 2282 2614 if ($encoding != '7bit') { … … 2302 2634 ); 2303 2635 } else { 2304 $mime[] = sprintf( 2305 'Content-Disposition: %s; filename=%s%s', 2306 $disposition, 2307 $encoded_name, 2308 $this->LE . $this->LE 2309 ); 2636 if (!empty($encoded_name)) { 2637 $mime[] = sprintf( 2638 'Content-Disposition: %s; filename=%s%s', 2639 $disposition, 2640 $encoded_name, 2641 $this->LE . $this->LE 2642 ); 2643 } else { 2644 $mime[] = sprintf( 2645 'Content-Disposition: %s%s', 2646 $disposition, 2647 $this->LE . $this->LE 2648 ); 2649 } 2310 2650 } 2311 2651 } else { … … 2341 2681 * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' 2342 2682 * @throws phpmailerException 2343 * @see EncodeFile(encodeFile2344 2683 * @access protected 2345 2684 * @return string … … 2561 2900 // Use native function if it's available (>= PHP5.3) 2562 2901 if (function_exists('quoted_printable_encode')) { 2563 return $this->fixEOL(quoted_printable_encode($string));2902 return quoted_printable_encode($string); 2564 2903 } 2565 2904 // Fall back to a pure PHP implementation … … 2569 2908 rawurlencode($string) 2570 2909 ); 2571 $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); 2572 return $this->fixEOL($string); 2910 return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); 2573 2911 } 2574 2912 … … 2639 2977 } 2640 2978 2641 2642 2979 /** 2643 2980 * Add a string or binary attachment (non-filesystem). … … 2745 3082 ) { 2746 3083 // If a MIME type is not specified, try to work it out from the name 2747 if ($type == '' ) {3084 if ($type == '' and !empty($name)) { 2748 3085 $type = self::filenameToType($name); 2749 3086 } … … 2802 3139 2803 3140 /** 3141 * Clear queued addresses of given kind. 3142 * @access protected 3143 * @param string $kind 'to', 'cc', or 'bcc' 3144 * @return void 3145 */ 3146 public function clearQueuedAddresses($kind) 3147 { 3148 $RecipientsQueue = $this->RecipientsQueue; 3149 foreach ($RecipientsQueue as $address => $params) { 3150 if ($params[0] == $kind) { 3151 unset($this->RecipientsQueue[$address]); 3152 } 3153 } 3154 } 3155 3156 /** 2804 3157 * Clear all To recipients. 2805 3158 * @return void … … 2811 3164 } 2812 3165 $this->to = array(); 3166 $this->clearQueuedAddresses('to'); 2813 3167 } 2814 3168 … … 2823 3177 } 2824 3178 $this->cc = array(); 3179 $this->clearQueuedAddresses('cc'); 2825 3180 } 2826 3181 … … 2835 3190 } 2836 3191 $this->bcc = array(); 3192 $this->clearQueuedAddresses('bcc'); 2837 3193 } 2838 3194 … … 2844 3200 { 2845 3201 $this->ReplyTo = array(); 3202 $this->ReplyToQueue = array(); 2846 3203 } 2847 3204 … … 2856 3213 $this->bcc = array(); 2857 3214 $this->all_recipients = array(); 3215 $this->RecipientsQueue = array(); 2858 3216 } 2859 3217 … … 3012 3370 3013 3371 /** 3014 * Returns all custom headers 3015 * 3372 * Returns all custom headers. 3016 3373 * @return array 3017 3374 */ … … 3022 3379 3023 3380 /** 3024 * Create a message from an HTML string. 3025 * Automatically makes modifications for inline images and backgrounds 3026 * and creates a plain-text version by converting the HTML. 3027 * Overwrites any existing values in $this->Body and $this->AltBody 3381 * Create a message body from an HTML string. 3382 * Automatically inlines images and creates a plain-text version by converting the HTML, 3383 * overwriting any existing values in Body and AltBody. 3384 * $basedir is used when handling relative image paths, e.g. <img src="images/a.png"> 3385 * will look for an image file in $basedir/images/a.png and convert it to inline. 3386 * If you don't want to apply these transformations to your HTML, just set Body and AltBody yourself. 3028 3387 * @access public 3029 3388 * @param string $message HTML message string 3030 * @param string $basedir base line directory for path3389 * @param string $basedir base directory for relative paths to images 3031 3390 * @param boolean|callable $advanced Whether to use the internal HTML to text converter 3032 * or your own custom converter @see html2text()3033 * @return string $message 3391 * or your own custom converter @see PHPMailer::html2text() 3392 * @return string $message The transformed message Body 3034 3393 */ 3035 3394 public function msgHTML($message, $basedir = '', $advanced = false) 3036 3395 { 3037 3396 preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); 3038 if ( isset($images[2])) {3397 if (array_key_exists(2, $images)) { 3039 3398 foreach ($images[2] as $imgindex => $url) { 3040 3399 // Convert data URIs into embedded images … … 3047 3406 } 3048 3407 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 3049 if ($this->addStringEmbeddedImage($data, $cid, ' ', 'base64', $match[1])) {3408 if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { 3050 3409 $message = str_replace( 3051 3410 $images[0][$imgindex], … … 3054 3413 ); 3055 3414 } 3056 } elseif ( !preg_match('#^[A-z]+://#', $url)) {3415 } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) { 3057 3416 // Do not change urls for absolute images (thanks to corvuscorax) 3417 // Do not change urls that are already inline images 3058 3418 $filename = basename($url); 3059 3419 $directory = dirname($url); … … 3089 3449 $this->Body = $this->normalizeBreaks($message); 3090 3450 $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); 3091 if ( empty($this->AltBody)) {3451 if (!$this->alternativeExists()) { 3092 3452 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . 3093 3453 self::CRLF . self::CRLF; … … 3100 3460 * This is used by msgHTML(). 3101 3461 * Note - older versions of this function used a bundled advanced converter 3102 * which was been removed for license reasons in #232 3462 * which was been removed for license reasons in #232. 3103 3463 * Example usage: 3104 3464 * <code> … … 3145 3505 'doc' => 'application/msword', 3146 3506 'word' => 'application/msword', 3507 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 3508 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 3509 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 3510 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 3511 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 3512 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 3513 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 3514 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 3515 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 3516 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 3147 3517 'class' => 'application/octet-stream', 3148 3518 'dll' => 'application/octet-stream', … … 3349 3719 } 3350 3720 3351 3352 3721 /** 3353 3722 * Set the public and private key files and password for S/MIME signing. … … 3391 3760 * @param string $signHeader 3392 3761 * @throws phpmailerException 3393 * @return string 3762 * @return string The DKIM signature value 3394 3763 */ 3395 3764 public function DKIM_Sign($signHeader) … … 3401 3770 return ''; 3402 3771 } 3403 $privKeyStr = file_get_contents($this->DKIM_private);3404 if ( $this->DKIM_passphrase != '') {3772 $privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private); 3773 if ('' != $this->DKIM_passphrase) { 3405 3774 $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); 3406 3775 } else { 3407 $privKey = $privKeyStr; 3408 } 3409 if (openssl_sign($signHeader, $signature, $privKey)) { 3410 return base64_encode($signature); 3411 } 3776 $privKey = openssl_pkey_get_private($privKeyStr); 3777 } 3778 //Workaround for missing digest algorithms in old PHP & OpenSSL versions 3779 //@link http://stackoverflow.com/a/11117338/333340 3780 if (version_compare(PHP_VERSION, '5.3.0') >= 0 and 3781 in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) { 3782 if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { 3783 openssl_pkey_free($privKey); 3784 return base64_encode($signature); 3785 } 3786 } else { 3787 $pinfo = openssl_pkey_get_details($privKey); 3788 $hash = hash('sha256', $signHeader); 3789 //'Magic' constant for SHA256 from RFC3447 3790 //@link https://tools.ietf.org/html/rfc3447#page-43 3791 $t = '3031300d060960864801650304020105000420' . $hash; 3792 $pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3); 3793 $eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t); 3794 3795 if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) { 3796 openssl_pkey_free($privKey); 3797 return base64_encode($signature); 3798 } 3799 } 3800 openssl_pkey_free($privKey); 3412 3801 return ''; 3413 3802 } … … 3426 3815 list($heading, $value) = explode(':', $line, 2); 3427 3816 $heading = strtolower($heading); 3428 $value = preg_replace('/\s +/', ' ', $value); // Compress useless spaces3817 $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces 3429 3818 $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value 3430 3819 } … … 3464 3853 public function DKIM_Add($headers_line, $subject, $body) 3465 3854 { 3466 $DKIMsignatureType = 'rsa-sha 1'; // Signature & hash algorithms3855 $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms 3467 3856 $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body 3468 3857 $DKIMquery = 'dns/txt'; // Query method … … 3472 3861 $from_header = ''; 3473 3862 $to_header = ''; 3863 $date_header = ''; 3474 3864 $current = ''; 3475 3865 foreach ($headers as $header) { … … 3480 3870 $to_header = $header; 3481 3871 $current = 'to_header'; 3872 } elseif (strpos($header, 'Date:') === 0) { 3873 $date_header = $header; 3874 $current = 'date_header'; 3482 3875 } else { 3483 3876 if (!empty($$current) && strpos($header, ' =?') === 0) { … … 3490 3883 $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); 3491 3884 $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); 3885 $date = str_replace('|', '=7C', $this->DKIM_QP($date_header)); 3492 3886 $subject = str_replace( 3493 3887 '|', … … 3497 3891 $body = $this->DKIM_BodyC($body); 3498 3892 $DKIMlen = strlen($body); // Length of body 3499 $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1hash of body3893 $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body 3500 3894 if ('' == $this->DKIM_identity) { 3501 3895 $ident = ''; … … 3510 3904 ";\r\n" . 3511 3905 "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . 3512 "\th=From:To: Subject;\r\n" .3906 "\th=From:To:Date:Subject;\r\n" . 3513 3907 "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . 3514 3908 "\tz=$from\r\n" . 3515 3909 "\t|$to\r\n" . 3910 "\t|$date\r\n" . 3516 3911 "\t|$subject;\r\n" . 3517 3912 "\tbh=" . $DKIMb64 . ";\r\n" . 3518 3913 "\tb="; 3519 3914 $toSign = $this->DKIM_HeaderC( 3520 $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs 3915 $from_header . "\r\n" . 3916 $to_header . "\r\n" . 3917 $date_header . "\r\n" . 3918 $subject_header . "\r\n" . 3919 $dkimhdrs 3521 3920 ); 3522 3921 $signed = $this->DKIM_Sign($toSign); … … 3538 3937 /** 3539 3938 * Allows for public read access to 'to' property. 3939 * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. 3540 3940 * @access public 3541 3941 * @return array … … 3548 3948 /** 3549 3949 * Allows for public read access to 'cc' property. 3950 * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. 3550 3951 * @access public 3551 3952 * @return array … … 3558 3959 /** 3559 3960 * Allows for public read access to 'bcc' property. 3961 * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. 3560 3962 * @access public 3561 3963 * @return array … … 3568 3970 /** 3569 3971 * Allows for public read access to 'ReplyTo' property. 3972 * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. 3570 3973 * @access public 3571 3974 * @return array … … 3578 3981 /** 3579 3982 * Allows for public read access to 'all_recipients' property. 3983 * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. 3580 3984 * @access public 3581 3985 * @return array -
branches/4.3/src/wp-includes/class-smtp.php
r33124 r39725 29 29 /** 30 30 * The PHPMailer SMTP version number. 31 * @ typestring32 */ 33 const VERSION = '5.2. 10';31 * @var string 32 */ 33 const VERSION = '5.2.21'; 34 34 35 35 /** 36 36 * SMTP line break constant. 37 * @ typestring37 * @var string 38 38 */ 39 39 const CRLF = "\r\n"; … … 41 41 /** 42 42 * The SMTP port to use if one is not specified. 43 * @ typeinteger43 * @var integer 44 44 */ 45 45 const DEFAULT_SMTP_PORT = 25; … … 47 47 /** 48 48 * The maximum line length allowed by RFC 2822 section 2.1.1 49 * @ typeinteger49 * @var integer 50 50 */ 51 51 const MAX_LINE_LENGTH = 998; … … 78 78 /** 79 79 * The PHPMailer SMTP Version number. 80 * @ typestring80 * @var string 81 81 * @deprecated Use the `VERSION` constant instead 82 82 * @see SMTP::VERSION 83 83 */ 84 public $Version = '5.2. 10';84 public $Version = '5.2.21'; 85 85 86 86 /** 87 87 * SMTP server port number. 88 * @ typeinteger88 * @var integer 89 89 * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead 90 90 * @see SMTP::DEFAULT_SMTP_PORT … … 94 94 /** 95 95 * SMTP reply line ending. 96 * @ typestring96 * @var string 97 97 * @deprecated Use the `CRLF` constant instead 98 98 * @see SMTP::CRLF … … 108 108 * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status 109 109 * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages 110 * @ typeinteger110 * @var integer 111 111 */ 112 112 public $do_debug = self::DEBUG_OFF; … … 123 123 * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; 124 124 * </code> 125 * @ typestring|callable125 * @var string|callable 126 126 */ 127 127 public $Debugoutput = 'echo'; … … 131 131 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path 132 132 * @link http://www.postfix.org/VERP_README.html Info on VERP 133 * @ typeboolean133 * @var boolean 134 134 */ 135 135 public $do_verp = false; … … 140 140 * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. 141 141 * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 142 * @ typeinteger142 * @var integer 143 143 */ 144 144 public $Timeout = 300; … … 147 147 * How long to wait for commands to complete, in seconds. 148 148 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 149 * @ typeinteger149 * @var integer 150 150 */ 151 151 public $Timelimit = 300; 152 152 153 /** 154 * @var array patterns to extract smtp transaction id from smtp reply 155 * Only first capture group will be use, use non-capturing group to deal with it 156 * Extend this class to override this property to fulfil your needs. 157 */ 158 protected $smtp_transaction_id_patterns = array( 159 'exim' => '/[0-9]{3} OK id=(.*)/', 160 'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/', 161 'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/' 162 ); 163 153 164 /** 154 165 * The socket for the server connection. 155 * @ typeresource166 * @var resource 156 167 */ 157 168 protected $smtp_conn; … … 159 170 /** 160 171 * Error information, if any, for the last SMTP command. 161 * @ typearray172 * @var array 162 173 */ 163 174 protected $error = array( … … 171 182 * The reply the server sent to us for HELO. 172 183 * If null, no HELO string has yet been received. 173 * @ typestring|null184 * @var string|null 174 185 */ 175 186 protected $helo_rply = null; … … 182 193 * Other values can be boolean TRUE or an array containing extension options. 183 194 * If null, no HELO/EHLO string has yet been received. 184 * @ typearray|null195 * @var array|null 185 196 */ 186 197 protected $server_caps = null; … … 188 199 /** 189 200 * The most recent reply received from the server. 190 * @ typestring201 * @var string 191 202 */ 192 203 protected $last_reply = ''; … … 207 218 //Avoid clash with built-in function names 208 219 if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { 209 call_user_func($this->Debugoutput, $str, $ this->do_debug);220 call_user_func($this->Debugoutput, $str, $level); 210 221 return; 211 222 } … … 273 284 if ($streamok) { 274 285 $socket_context = stream_context_create($options); 275 //Suppress errors; connection failures are handled at a higher level276 $this->smtp_conn = @stream_socket_client(286 set_error_handler(array($this, 'errorHandler')); 287 $this->smtp_conn = stream_socket_client( 277 288 $host . ":" . $port, 278 289 $errno, … … 282 293 $socket_context 283 294 ); 295 restore_error_handler(); 284 296 } else { 285 297 //Fall back to fsockopen which should work in more places, but is missing some features … … 288 300 self::DEBUG_CONNECTION 289 301 ); 302 set_error_handler(array($this, 'errorHandler')); 290 303 $this->smtp_conn = fsockopen( 291 304 $host, … … 295 308 $timeout 296 309 ); 310 restore_error_handler(); 297 311 } 298 312 // Verify we connected properly … … 337 351 return false; 338 352 } 353 354 //Allow the best TLS version(s) we can 355 $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; 356 357 //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT 358 //so add them back in manually if we can 359 if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { 360 $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; 361 $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; 362 } 363 339 364 // Begin encrypted connection 340 365 if (!stream_socket_enable_crypto( 341 366 $this->smtp_conn, 342 367 true, 343 STREAM_CRYPTO_METHOD_TLS_CLIENT368 $crypto_method 344 369 )) { 345 370 return false; … … 352 377 * Must be run after hello(). 353 378 * @see hello() 354 * @param string $username 355 * @param string $password 356 * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)357 * @param string $realm 379 * @param string $username The user name 380 * @param string $password The password 381 * @param string $authtype The auth type (PLAIN, LOGIN, CRAM-MD5) 382 * @param string $realm The auth realm for NTLM 358 383 * @param string $workstation The auth workstation for NTLM 359 * @ access public360 * @return bool ean True if successfully authenticated.384 * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth) 385 * @return bool True if successfully authenticated.* @access public 361 386 */ 362 387 public function authenticate( … … 365 390 $authtype = null, 366 391 $realm = '', 367 $workstation = '' 392 $workstation = '', 393 $OAuth = null 368 394 ) { 369 395 if (!$this->server_caps) { … … 389 415 390 416 if (empty($authtype)) { 391 foreach (array(' LOGIN', 'CRAM-MD5', 'PLAIN') as $method) {417 foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN') as $method) { 392 418 if (in_array($method, $this->server_caps['AUTH'])) { 393 419 $authtype = $method; … … 673 699 { 674 700 $this->server_caps = array(); 675 $lines = explode("\n", $this->last_reply); 701 $lines = explode("\n", $this->helo_rply); 702 676 703 foreach ($lines as $n => $s) { 704 //First 4 chars contain response code followed by - or space 677 705 $s = trim(substr($s, 4)); 678 if ( !$s) {706 if (empty($s)) { 679 707 continue; 680 708 } … … 686 714 } else { 687 715 $name = array_shift($fields); 688 if ($name == 'SIZE') { 689 $fields = ($fields) ? $fields[0] : 0; 716 switch ($name) { 717 case 'SIZE': 718 $fields = ($fields ? $fields[0] : 0); 719 break; 720 case 'AUTH': 721 if (!is_array($fields)) { 722 $fields = array(); 723 } 724 break; 725 default: 726 $fields = true; 690 727 } 691 728 } 692 $this->server_caps[$name] = ($fields ? $fields : true);729 $this->server_caps[$name] = $fields; 693 730 } 694 731 } … … 740 777 * Returns true if the recipient was accepted false if it was rejected. 741 778 * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> 742 * @param string $ toaddrThe address the message is being sent to743 * @access public 744 * @return boolean 745 */ 746 public function recipient($ toaddr)779 * @param string $address The address the message is being sent to 780 * @access public 781 * @return boolean 782 */ 783 public function recipient($address) 747 784 { 748 785 return $this->sendCommand( 749 786 'RCPT TO', 750 'RCPT TO:<' . $ toaddr. '>',787 'RCPT TO:<' . $address . '>', 751 788 array(250, 251) 752 789 ); … … 767 804 /** 768 805 * Send a command to an SMTP server and check its return code. 769 * @param string $command 806 * @param string $command The command name - not sent to the server 770 807 * @param string $commandstring The actual command to send 771 * @param integer|array $expect 808 * @param integer|array $expect One or more expected integer success codes 772 809 * @access protected 773 810 * @return boolean True on success. … … 777 814 if (!$this->connected()) { 778 815 $this->setError("Called $command without being connected"); 816 return false; 817 } 818 //Reject line breaks in all commands 819 if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) { 820 $this->setError("Command '$command' contained line breaks"); 779 821 return false; 780 822 } … … 982 1024 while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { 983 1025 $str = @fgets($this->smtp_conn, 515); 984 $this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL);985 $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL);1026 $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL); 1027 $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL); 986 1028 $data .= $str; 987 $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);988 1029 // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen 989 1030 if ((isset($str[3]) and $str[3] == ' ')) { … … 1100 1141 return $this->Timeout; 1101 1142 } 1143 1144 /** 1145 * Reports an error number and string. 1146 * @param integer $errno The error number returned by PHP. 1147 * @param string $errmsg The error message returned by PHP. 1148 */ 1149 protected function errorHandler($errno, $errmsg) 1150 { 1151 $notice = 'Connection: Failed to connect to server.'; 1152 $this->setError( 1153 $notice, 1154 $errno, 1155 $errmsg 1156 ); 1157 $this->edebug( 1158 $notice . ' Error number ' . $errno . '. "Error notice: ' . $errmsg, 1159 self::DEBUG_CONNECTION 1160 ); 1161 } 1162 1163 /** 1164 * Will return the ID of the last smtp transaction based on a list of patterns provided 1165 * in SMTP::$smtp_transaction_id_patterns. 1166 * If no reply has been received yet, it will return null. 1167 * If no pattern has been matched, it will return false. 1168 * @return bool|null|string 1169 */ 1170 public function getLastTransactionID() 1171 { 1172 $reply = $this->getLastReply(); 1173 1174 if (empty($reply)) { 1175 return null; 1176 } 1177 1178 foreach($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) { 1179 if(preg_match($smtp_transaction_id_pattern, $reply, $matches)) { 1180 return $matches[1]; 1181 } 1182 } 1183 1184 return false; 1185 } 1102 1186 }
Note: See TracChangeset
for help on using the changeset viewer.