Ticket #15912: 15912.001.diff
| File 15912.001.diff, 156.4 KB (added by cnorris23, 2 years ago) |
|---|
-
wp-includes/class-phpmailer.php
2 2 /*~ class.phpmailer.php 3 3 .---------------------------------------------------------------------------. 4 4 | Software: PHPMailer - PHP email class | 5 | Version: 2.0.4|6 | Contact: via sourceforge.net support pages (also www. codeworxtech.com)|5 | Version: 5.1 | 6 | Contact: via sourceforge.net support pages (also www.worxware.com) | 7 7 | Info: http://phpmailer.sourceforge.net | 8 8 | Support: http://sourceforge.net/projects/phpmailer/ | 9 9 | ------------------------------------------------------------------------- | 10 | Author: Andy Prevost (project admininistrator) | 11 | Author: Brent R. Matzelle (original founder) | 12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. | 10 | Admin: Andy Prevost (project admininistrator) | 11 | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 12 | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | 13 | Founder: Brent R. Matzelle (original founder) | 14 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | 13 15 | Copyright (c) 2001-2003, Brent R. Matzelle | 14 16 | ------------------------------------------------------------------------- | 15 17 | License: Distributed under the Lesser General Public License (LGPL) | … … 18 20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 19 21 | FITNESS FOR A PARTICULAR PURPOSE. | 20 22 | ------------------------------------------------------------------------- | 21 | We offer a number of paid services (www. codeworxtech.com):|23 | We offer a number of paid services (www.worxware.com): | 22 24 | - Web Hosting on highly optimized fast and secure servers | 23 25 | - Technology Consulting | 24 26 | - Oursourcing (highly qualified programmers and graphic designers) | 25 27 '---------------------------------------------------------------------------' 26 */ 28 */ 29 27 30 /** 28 31 * PHPMailer - PHP email transport class 32 * NOTE: Requires PHP version 5 or later 29 33 * @package PHPMailer 30 34 * @author Andy Prevost 35 * @author Marcus Bointon 31 36 * @copyright 2004 - 2009 Andy Prevost 37 * @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $ 38 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 32 39 */ 33 40 41 if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n"); 42 34 43 class PHPMailer { 35 44 36 45 ///////////////////////////////////////////////// … … 41 50 * Email priority (1 = High, 3 = Normal, 5 = low). 42 51 * @var int 43 52 */ 44 var$Priority = 3;53 public $Priority = 3; 45 54 46 55 /** 47 56 * Sets the CharSet of the message. 48 57 * @var string 49 58 */ 50 var$CharSet = 'iso-8859-1';59 public $CharSet = 'iso-8859-1'; 51 60 52 61 /** 53 62 * Sets the Content-type of the message. 54 63 * @var string 55 64 */ 56 var $ContentType= 'text/plain';65 public $ContentType = 'text/plain'; 57 66 58 67 /** 59 * Sets the Encoding of the message. Options for this are "8bit",60 * "7bit", "binary", "base64", and "quoted-printable".68 * Sets the Encoding of the message. Options for this are 69 * "8bit", "7bit", "binary", "base64", and "quoted-printable". 61 70 * @var string 62 71 */ 63 var$Encoding = '8bit';72 public $Encoding = '8bit'; 64 73 65 74 /** 66 75 * Holds the most recent mailer error message. 67 76 * @var string 68 77 */ 69 var$ErrorInfo = '';78 public $ErrorInfo = ''; 70 79 71 80 /** 72 81 * Sets the From email address for the message. 73 82 * @var string 74 83 */ 75 var$From = 'root@localhost';84 public $From = 'root@localhost'; 76 85 77 86 /** 78 87 * Sets the From name of the message. 79 88 * @var string 80 89 */ 81 var$FromName = 'Root User';90 public $FromName = 'Root User'; 82 91 83 92 /** 84 93 * Sets the Sender email (Return-Path) of the message. If not empty, 85 94 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. 86 95 * @var string 87 96 */ 88 var$Sender = '';97 public $Sender = ''; 89 98 90 99 /** 91 100 * Sets the Subject of the message. 92 101 * @var string 93 102 */ 94 var$Subject = '';103 public $Subject = ''; 95 104 96 105 /** 97 106 * Sets the Body of the message. This can be either an HTML or text body. 98 107 * If HTML then run IsHTML(true). 99 108 * @var string 100 109 */ 101 var$Body = '';110 public $Body = ''; 102 111 103 112 /** 104 113 * Sets the text-only body of the message. This automatically sets the … … 107 116 * that can read HTML will view the normal Body. 108 117 * @var string 109 118 */ 110 var$AltBody = '';119 public $AltBody = ''; 111 120 112 121 /** 113 122 * Sets word wrapping on the body of the message to a given number of 114 123 * characters. 115 124 * @var int 116 125 */ 117 var$WordWrap = 0;126 public $WordWrap = 0; 118 127 119 128 /** 120 129 * Method to send mail: ("mail", "sendmail", or "smtp"). 121 130 * @var string 122 131 */ 123 var$Mailer = 'mail';132 public $Mailer = 'mail'; 124 133 125 134 /** 126 135 * Sets the path of the sendmail program. 127 136 * @var string 128 137 */ 129 var$Sendmail = '/usr/sbin/sendmail';138 public $Sendmail = '/usr/sbin/sendmail'; 130 139 131 140 /** 132 * Path to PHPMailer plugins. This is now only useful if the SMTP class141 * Path to PHPMailer plugins. Useful if the SMTP class 133 142 * is in a different directory than the PHP include path. 134 143 * @var string 135 144 */ 136 var$PluginDir = '';145 public $PluginDir = ''; 137 146 138 147 /** 139 * Holds PHPMailer version.140 * @var string141 */142 var $Version = "2.0.4";143 144 /**145 148 * Sets the email address that a reading confirmation will be sent. 146 149 * @var string 147 150 */ 148 var$ConfirmReadingTo = '';151 public $ConfirmReadingTo = ''; 149 152 150 153 /** 151 154 * Sets the hostname to use in Message-Id and Received headers … … 153 156 * by SERVER_NAME is used or 'localhost.localdomain'. 154 157 * @var string 155 158 */ 156 var$Hostname = '';159 public $Hostname = ''; 157 160 158 161 /** 159 162 * Sets the message ID to be used in the Message-Id header. 160 163 * If empty, a unique id will be generated. 161 164 * @var string 162 165 */ 163 var$MessageID = '';166 public $MessageID = ''; 164 167 165 168 ///////////////////////////////////////////////// 166 169 // PROPERTIES FOR SMTP … … 174 177 * Hosts will be tried in order. 175 178 * @var string 176 179 */ 177 var $Host= 'localhost';180 public $Host = 'localhost'; 178 181 179 182 /** 180 183 * Sets the default SMTP server port. 181 184 * @var int 182 185 */ 183 var $Port= 25;186 public $Port = 25; 184 187 185 188 /** 186 189 * Sets the SMTP HELO of the message (Default is $Hostname). 187 190 * @var string 188 191 */ 189 var $Helo= '';192 public $Helo = ''; 190 193 191 194 /** 192 195 * Sets connection prefix. 193 196 * Options are "", "ssl" or "tls" 194 197 * @var string 195 198 */ 196 var $SMTPSecure = "";199 public $SMTPSecure = ''; 197 200 198 201 /** 199 202 * Sets SMTP authentication. Utilizes the Username and Password variables. 200 203 * @var bool 201 204 */ 202 var $SMTPAuth= false;205 public $SMTPAuth = false; 203 206 204 207 /** 205 208 * Sets SMTP username. 206 209 * @var string 207 210 */ 208 var $Username= '';211 public $Username = ''; 209 212 210 213 /** 211 214 * Sets SMTP password. 212 215 * @var string 213 216 */ 214 var $Password= '';217 public $Password = ''; 215 218 216 219 /** 217 * Sets the SMTP server timeout in seconds. This function will not218 * work with the win32 version.220 * Sets the SMTP server timeout in seconds. 221 * This function will not work with the win32 version. 219 222 * @var int 220 223 */ 221 var $Timeout= 10;224 public $Timeout = 10; 222 225 223 226 /** 224 227 * Sets SMTP class debugging on or off. 225 228 * @var bool 226 229 */ 227 var $SMTPDebug= false;230 public $SMTPDebug = false; 228 231 229 232 /** 230 233 * Prevents the SMTP connection from being closed after each mail … … 232 235 * requires an explicit call to SmtpClose(). 233 236 * @var bool 234 237 */ 235 var$SMTPKeepAlive = false;238 public $SMTPKeepAlive = false; 236 239 237 240 /** 238 241 * Provides the ability to have the TO field process individual 239 242 * emails, instead of sending to entire TO addresses 240 243 * @var bool 241 244 */ 242 var $SingleTo= false;245 public $SingleTo = false; 243 246 247 /** 248 * If SingleTo is true, this provides the array to hold the email addresses 249 * @var bool 250 */ 251 public $SingleToArray = array(); 252 253 /** 254 * Provides the ability to change the line ending 255 * @var string 256 */ 257 public $LE = "\n"; 258 259 /** 260 * Used with DKIM DNS Resource Record 261 * @var string 262 */ 263 public $DKIM_selector = 'phpmailer'; 264 265 /** 266 * Used with DKIM DNS Resource Record 267 * optional, in format of email address 'you@yourdomain.com' 268 * @var string 269 */ 270 public $DKIM_identity = ''; 271 272 /** 273 * Used with DKIM DNS Resource Record 274 * optional, in format of email address 'you@yourdomain.com' 275 * @var string 276 */ 277 public $DKIM_domain = ''; 278 279 /** 280 * Used with DKIM DNS Resource Record 281 * optional, in format of email address 'you@yourdomain.com' 282 * @var string 283 */ 284 public $DKIM_private = ''; 285 286 /** 287 * Callback Action function name 288 * the function that handles the result of the send email action. Parameters: 289 * bool $result result of the send action 290 * string $to email address of the recipient 291 * string $cc cc email addresses 292 * string $bcc bcc email addresses 293 * string $subject the subject 294 * string $body the email body 295 * @var string 296 */ 297 public $action_function = ''; //'callbackAction'; 298 299 /** 300 * Sets the PHPMailer Version number 301 * @var string 302 */ 303 public $Version = '5.1'; 304 244 305 ///////////////////////////////////////////////// 245 // PROPERTIES, PRIVATE 306 // PROPERTIES, PRIVATE AND PROTECTED 246 307 ///////////////////////////////////////////////// 247 308 248 var $smtp = NULL; 249 var $to = array(); 250 var $cc = array(); 251 var $bcc = array(); 252 var $ReplyTo = array(); 253 var $attachment = array(); 254 var $CustomHeader = array(); 255 var $message_type = ''; 256 var $boundary = array(); 257 var $language = array(); 258 var $error_count = 0; 259 var $LE = "\n"; 260 var $sign_cert_file = ""; 261 var $sign_key_file = ""; 262 var $sign_key_pass = ""; 309 private $smtp = NULL; 310 private $to = array(); 311 private $cc = array(); 312 private $bcc = array(); 313 private $ReplyTo = array(); 314 private $all_recipients = array(); 315 private $attachment = array(); 316 private $CustomHeader = array(); 317 private $message_type = ''; 318 private $boundary = array(); 319 protected $language = array(); 320 private $error_count = 0; 321 private $sign_cert_file = ""; 322 private $sign_key_file = ""; 323 private $sign_key_pass = ""; 324 private $exceptions = false; 263 325 264 326 ///////////////////////////////////////////////// 327 // CONSTANTS 328 ///////////////////////////////////////////////// 329 330 const STOP_MESSAGE = 0; // message only, continue processing 331 const STOP_CONTINUE = 1; // message?, likely ok to continue processing 332 const STOP_CRITICAL = 2; // message, plus full stop, critical error reached 333 334 ///////////////////////////////////////////////// 265 335 // METHODS, VARIABLES 266 336 ///////////////////////////////////////////////// 267 337 268 338 /** 339 * Constructor 340 * @param boolean $exceptions Should we throw external exceptions? 341 */ 342 public function __construct($exceptions = false) { 343 $this->exceptions = ($exceptions == true); 344 } 345 346 /** 269 347 * Sets message type to HTML. 270 * @param bool $ bool348 * @param bool $ishtml 271 349 * @return void 272 350 */ 273 function IsHTML($bool) {274 if ($bool == true) {351 public function IsHTML($ishtml = true) { 352 if ($ishtml) { 275 353 $this->ContentType = 'text/html'; 276 354 } else { 277 355 $this->ContentType = 'text/plain'; … … 282 360 * Sets Mailer to send message using SMTP. 283 361 * @return void 284 362 */ 285 function IsSMTP() {363 public function IsSMTP() { 286 364 $this->Mailer = 'smtp'; 287 365 } 288 366 … … 290 368 * Sets Mailer to send message using PHP mail() function. 291 369 * @return void 292 370 */ 293 function IsMail() {371 public function IsMail() { 294 372 $this->Mailer = 'mail'; 295 373 } 296 374 … … 298 376 * Sets Mailer to send message using the $Sendmail program. 299 377 * @return void 300 378 */ 301 function IsSendmail() { 379 public function IsSendmail() { 380 if (!stristr(ini_get('sendmail_path'), 'sendmail')) { 381 $this->Sendmail = '/var/qmail/bin/sendmail'; 382 } 302 383 $this->Mailer = 'sendmail'; 303 384 } 304 385 … … 306 387 * Sets Mailer to send message using the qmail MTA. 307 388 * @return void 308 389 */ 309 function IsQmail() { 310 $this->Sendmail = '/var/qmail/bin/sendmail'; 390 public function IsQmail() { 391 if (stristr(ini_get('sendmail_path'), 'qmail')) { 392 $this->Sendmail = '/var/qmail/bin/sendmail'; 393 } 311 394 $this->Mailer = 'sendmail'; 312 395 } 313 396 … … 319 402 * Adds a "To" address. 320 403 * @param string $address 321 404 * @param string $name 322 * @return void405 * @return boolean true on success, false if address already used 323 406 */ 324 function AddAddress($address, $name = '') { 325 $cur = count($this->to); 326 $this->to[$cur][0] = trim($address); 327 $this->to[$cur][1] = $name; 407 public function AddAddress($address, $name = '') { 408 return $this->AddAnAddress('to', $address, $name); 328 409 } 329 410 330 411 /** 331 * Adds a "Cc" address. Note: this function works 332 * with the SMTP mailer on win32, not with the "mail" 333 * mailer. 412 * Adds a "Cc" address. 413 * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. 334 414 * @param string $address 335 415 * @param string $name 336 * @return void416 * @return boolean true on success, false if address already used 337 417 */ 338 function AddCC($address, $name = '') { 339 $cur = count($this->cc); 340 $this->cc[$cur][0] = trim($address); 341 $this->cc[$cur][1] = $name; 418 public function AddCC($address, $name = '') { 419 return $this->AddAnAddress('cc', $address, $name); 342 420 } 343 421 344 422 /** 345 * Adds a "Bcc" address. Note: this function works 346 * with the SMTP mailer on win32, not with the "mail" 347 * mailer. 423 * Adds a "Bcc" address. 424 * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. 348 425 * @param string $address 349 426 * @param string $name 350 * @return void427 * @return boolean true on success, false if address already used 351 428 */ 352 function AddBCC($address, $name = '') { 353 $cur = count($this->bcc); 354 $this->bcc[$cur][0] = trim($address); 355 $this->bcc[$cur][1] = $name; 429 public function AddBCC($address, $name = '') { 430 return $this->AddAnAddress('bcc', $address, $name); 356 431 } 357 432 358 433 /** 359 * Adds a "Reply- To" address.434 * Adds a "Reply-to" address. 360 435 * @param string $address 361 436 * @param string $name 362 * @return void437 * @return boolean 363 438 */ 364 function AddReplyTo($address, $name = '') { 365 $cur = count($this->ReplyTo); 366 $this->ReplyTo[$cur][0] = trim($address); 367 $this->ReplyTo[$cur][1] = $name; 439 public function AddReplyTo($address, $name = '') { 440 return $this->AddAnAddress('ReplyTo', $address, $name); 368 441 } 369 442 443 /** 444 * Adds an address to one of the recipient arrays 445 * Addresses that have been added already return false, but do not throw exceptions 446 * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' 447 * @param string $address The email address to send to 448 * @param string $name 449 * @return boolean true on success, false if address already used or invalid in some way 450 * @access private 451 */ 452 private function AddAnAddress($kind, $address, $name = '') { 453 if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) { 454 echo 'Invalid recipient array: ' . kind; 455 return false; 456 } 457 $address = trim($address); 458 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 459 if (!self::ValidateAddress($address)) { 460 $this->SetError($this->Lang('invalid_address').': '. $address); 461 if ($this->exceptions) { 462 throw new phpmailerException($this->Lang('invalid_address').': '.$address); 463 } 464 echo $this->Lang('invalid_address').': '.$address; 465 return false; 466 } 467 if ($kind != 'ReplyTo') { 468 if (!isset($this->all_recipients[strtolower($address)])) { 469 array_push($this->$kind, array($address, $name)); 470 $this->all_recipients[strtolower($address)] = true; 471 return true; 472 } 473 } else { 474 if (!array_key_exists(strtolower($address), $this->ReplyTo)) { 475 $this->ReplyTo[strtolower($address)] = array($address, $name); 476 return true; 477 } 478 } 479 return false; 480 } 481 482 /** 483 * Set the From and FromName properties 484 * @param string $address 485 * @param string $name 486 * @return boolean 487 */ 488 public function SetFrom($address, $name = '',$auto=1) { 489 $address = trim($address); 490 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim 491 if (!self::ValidateAddress($address)) { 492 $this->SetError($this->Lang('invalid_address').': '. $address); 493 if ($this->exceptions) { 494 throw new phpmailerException($this->Lang('invalid_address').': '.$address); 495 } 496 echo $this->Lang('invalid_address').': '.$address; 497 return false; 498 } 499 $this->From = $address; 500 $this->FromName = $name; 501 if ($auto) { 502 if (empty($this->ReplyTo)) { 503 $this->AddAnAddress('ReplyTo', $address, $name); 504 } 505 if (empty($this->Sender)) { 506 $this->Sender = $address; 507 } 508 } 509 return true; 510 } 511 512 /** 513 * Check that a string looks roughly like an email address should 514 * Static so it can be used without instantiation 515 * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator 516 * Conforms approximately to RFC2822 517 * @link http://www.hexillion.com/samples/#Regex Original pattern found here 518 * @param string $address The email address to check 519 * @return boolean 520 * @static 521 * @access public 522 */ 523 public static function ValidateAddress($address) { 524 if (function_exists('filter_var')) { //Introduced in PHP 5.2 525 if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { 526 return false; 527 } else { 528 return true; 529 } 530 } else { 531 return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); 532 } 533 } 534 370 535 ///////////////////////////////////////////////// 371 536 // METHODS, MAIL SENDING 372 537 ///////////////////////////////////////////////// … … 377 542 * variable to view description of the error. 378 543 * @return bool 379 544 */ 380 function Send() { 381 $header = ''; 382 $body = ''; 383 $result = true; 545 public function Send() { 546 try { 547 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { 548 throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL); 549 } 384 550 385 if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {386 $this->SetError($this->Lang('provide_address'));387 return false;388 }551 // Set whether the message is multipart/alternative 552 if(!empty($this->AltBody)) { 553 $this->ContentType = 'multipart/alternative'; 554 } 389 555 390 /* Set whether the message is multipart/alternative */391 if(!empty($this->AltBody)) {392 $ this->ContentType = 'multipart/alternative';393 }556 $this->error_count = 0; // reset errors 557 $this->SetMessageType(); 558 $header = $this->CreateHeader(); 559 $body = $this->CreateBody(); 394 560 395 $this->error_count = 0; // reset errors 396 $this->SetMessageType(); 397 $header .= $this->CreateHeader(); 398 $body = $this->CreateBody(); 561 if (empty($this->Body)) { 562 throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); 563 } 399 564 400 if($body == '') { 565 // digitally sign with DKIM if enabled 566 if ($this->DKIM_domain && $this->DKIM_private) { 567 $header_dkim = $this->DKIM_Add($header,$this->Subject,$body); 568 $header = str_replace("\r\n","\n",$header_dkim) . $header; 569 } 570 571 // Choose the mailer and send through it 572 switch($this->Mailer) { 573 case 'sendmail': 574 return $this->SendmailSend($header, $body); 575 case 'smtp': 576 return $this->SmtpSend($header, $body); 577 default: 578 return $this->MailSend($header, $body); 579 } 580 581 } catch (phpmailerException $e) { 582 $this->SetError($e->getMessage()); 583 if ($this->exceptions) { 584 throw $e; 585 } 586 echo $e->getMessage()."\n"; 401 587 return false; 402 588 } 403 404 /* Choose the mailer */405 switch($this->Mailer) {406 case 'sendmail':407 $result = $this->SendmailSend($header, $body);408 break;409 case 'smtp':410 $result = $this->SmtpSend($header, $body);411 break;412 case 'mail':413 $result = $this->MailSend($header, $body);414 break;415 default:416 $result = $this->MailSend($header, $body);417 break;418 //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));419 //$result = false;420 //break;421 }422 423 return $result;424 589 } 425 590 426 591 /** 427 592 * Sends mail using the $Sendmail program. 428 * @access private 593 * @param string $header The message headers 594 * @param string $body The message body 595 * @access protected 429 596 * @return bool 430 597 */ 431 function SendmailSend($header, $body) {598 protected function SendmailSend($header, $body) { 432 599 if ($this->Sender != '') { 433 600 $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 434 601 } else { 435 602 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); 436 603 } 437 438 if(!@$mail = popen($sendmail, 'w')) { 439 $this->SetError($this->Lang('execute') . $this->Sendmail); 440 return false; 604 if ($this->SingleTo === true) { 605 foreach ($this->SingleToArray as $key => $val) { 606 if(!@$mail = popen($sendmail, 'w')) { 607 throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 608 } 609 fputs($mail, "To: " . $val . "\n"); 610 fputs($mail, $header); 611 fputs($mail, $body); 612 $result = pclose($mail); 613 // implement call back function if it exists 614 $isSent = ($result == 0) ? 1 : 0; 615 $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); 616 if($result != 0) { 617 throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 618 } 619 } 620 } else { 621 if(!@$mail = popen($sendmail, 'w')) { 622 throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 623 } 624 fputs($mail, $header); 625 fputs($mail, $body); 626 $result = pclose($mail); 627 // implement call back function if it exists 628 $isSent = ($result == 0) ? 1 : 0; 629 $this->doCallback($isSent,$this->to,$this->cc,$this->bcc,$this->Subject,$body); 630 if($result != 0) { 631 throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); 632 } 441 633 } 442 443 fputs($mail, $header);444 fputs($mail, $body);445 446 $result = pclose($mail);447 if (version_compare(phpversion(), '4.2.3') == -1) {448 $result = $result >> 8 & 0xFF;449 }450 if($result != 0) {451 $this->SetError($this->Lang('execute') . $this->Sendmail);452 return false;453 }454 634 return true; 455 635 } 456 636 457 637 /** 458 638 * Sends mail using the PHP mail() function. 459 * @access private 639 * @param string $header The message headers 640 * @param string $body The message body 641 * @access protected 460 642 * @return bool 461 643 */ 462 function MailSend($header, $body) { 463 464 $to = ''; 465 for($i = 0; $i < count($this->to); $i++) { 466 if($i != 0) { $to .= ', '; } 467 $to .= $this->AddrFormat($this->to[$i]); 644 protected function MailSend($header, $body) { 645 $toArr = array(); 646 foreach($this->to as $t) { 647 $toArr[] = $this->AddrFormat($t); 468 648 } 649 $to = implode(', ', $toArr); 469 650 470 $toArr = split(',', $to);471 472 651 $params = sprintf("-oi -f %s", $this->Sender); 473 if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {652 if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) { 474 653 $old_from = ini_get('sendmail_from'); 475 654 ini_set('sendmail_from', $this->Sender); 476 655 if ($this->SingleTo === true && count($toArr) > 1) { 477 656 foreach ($toArr as $key => $val) { 478 657 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 658 // implement call back function if it exists 659 $isSent = ($rt == 1) ? 1 : 0; 660 $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); 479 661 } 480 662 } else { 481 663 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 664 // implement call back function if it exists 665 $isSent = ($rt == 1) ? 1 : 0; 666 $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); 482 667 } 483 668 } else { 484 669 if ($this->SingleTo === true && count($toArr) > 1) { 485 670 foreach ($toArr as $key => $val) { 486 671 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 672 // implement call back function if it exists 673 $isSent = ($rt == 1) ? 1 : 0; 674 $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); 487 675 } 488 676 } else { 489 677 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); 678 // implement call back function if it exists 679 $isSent = ($rt == 1) ? 1 : 0; 680 $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); 490 681 } 491 682 } 492 493 683 if (isset($old_from)) { 494 684 ini_set('sendmail_from', $old_from); 495 685 } 496 497 686 if(!$rt) { 498 $this->SetError($this->Lang('instantiate')); 499 return false; 687 throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL); 500 688 } 501 502 689 return true; 503 690 } 504 691 505 692 /** 506 * Sends mail via SMTP using PhpSMTP (Author: 507 * Chris Ryan). Returns bool. Returns false if there is a 508 * bad MAIL FROM, RCPT, or DATA input. 509 * @access private 693 * Sends mail via SMTP using PhpSMTP 694 * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. 695 * @param string $header The message headers 696 * @param string $body The message body 697 * @uses SMTP 698 * @access protected 510 699 * @return bool 511 700 */ 512 function SmtpSend($header, $body) { 513 include_once($this->PluginDir . 'class-smtp.php'); 514 $error = ''; 701 protected function SmtpSend($header, $body) { 702 require_once $this->PluginDir . 'class.smtp.php'; 515 703 $bad_rcpt = array(); 516 704 517 705 if(!$this->SmtpConnect()) { 518 return false;706 throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL); 519 707 } 520 521 708 $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; 522 709 if(!$this->smtp->Mail($smtp_from)) { 523 $error = $this->Lang('from_failed') . $smtp_from; 524 $this->SetError($error); 525 $this->smtp->Reset(); 526 return false; 710 throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL); 527 711 } 528 712 529 /* Attempt to send attach all recipients */ 530 for($i = 0; $i < count($this->to); $i++) { 531 if(!$this->smtp->Recipient($this->to[$i][0])) { 532 $bad_rcpt[] = $this->to[$i][0]; 713 // Attempt to send attach all recipients 714 foreach($this->to as $to) { 715 if (!$this->smtp->Recipient($to[0])) { 716 $bad_rcpt[] = $to[0]; 717 // implement call back function if it exists 718 $isSent = 0; 719 $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); 720 } else { 721 // implement call back function if it exists 722 $isSent = 1; 723 $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); 533 724 } 534 725 } 535 for($i = 0; $i < count($this->cc); $i++) { 536 if(!$this->smtp->Recipient($this->cc[$i][0])) { 537 $bad_rcpt[] = $this->cc[$i][0]; 726 foreach($this->cc as $cc) { 727 if (!$this->smtp->Recipient($cc[0])) { 728 $bad_rcpt[] = $cc[0]; 729 // implement call back function if it exists 730 $isSent = 0; 731 $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); 732 } else { 733 // implement call back function if it exists 734 $isSent = 1; 735 $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); 538 736 } 539 737 } 540 for($i = 0; $i < count($this->bcc); $i++) { 541 if(!$this->smtp->Recipient($this->bcc[$i][0])) { 542 $bad_rcpt[] = $this->bcc[$i][0]; 738 foreach($this->bcc as $bcc) { 739 if (!$this->smtp->Recipient($bcc[0])) { 740 $bad_rcpt[] = $bcc[0]; 741 // implement call back function if it exists 742 $isSent = 0; 743 $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); 744 } else { 745 // implement call back function if it exists 746 $isSent = 1; 747 $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); 543 748 } 544 749 } 545 750 546 if(count($bad_rcpt) > 0) { // Create error message 547 for($i = 0; $i < count($bad_rcpt); $i++) { 548 if($i != 0) { 549 $error .= ', '; 550 } 551 $error .= $bad_rcpt[$i]; 552 } 553 $error = $this->Lang('recipients_failed') . $error; 554 $this->SetError($error); 555 $this->smtp->Reset(); 556 return false; 751 752 if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses 753 $badaddresses = implode(', ', $bad_rcpt); 754 throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses); 557 755 } 558 559 756 if(!$this->smtp->Data($header . $body)) { 560 $this->SetError($this->Lang('data_not_accepted')); 561 $this->smtp->Reset(); 562 return false; 757 throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL); 563 758 } 564 759 if($this->SMTPKeepAlive == true) { 565 760 $this->smtp->Reset(); 566 } else {567 $this->SmtpClose();568 761 } 569 570 762 return true; 571 763 } 572 764 573 765 /** 574 * Initiates a connection to an SMTP server. Returns false if the 575 * operation failed. 576 * @access private 766 * Initiates a connection to an SMTP server. 767 * Returns false if the operation failed. 768 * @uses SMTP 769 * @access public 577 770 * @return bool 578 771 */ 579 function SmtpConnect() {580 if( $this->smtp == NULL) {772 public function SmtpConnect() { 773 if(is_null($this->smtp)) { 581 774 $this->smtp = new SMTP(); 582 775 } 583 776 584 777 $this->smtp->do_debug = $this->SMTPDebug; 585 778 $hosts = explode(';', $this->Host); 586 779 $index = 0; 587 $connection = ($this->smtp->Connected());780 $connection = $this->smtp->Connected(); 588 781 589 /* Retry while there is no connection */ 590 while($index < count($hosts) && $connection == false) { 591 $hostinfo = array(); 592 if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) { 593 $host = $hostinfo[1]; 594 $port = $hostinfo[2]; 595 } else { 596 $host = $hosts[$index]; 597 $port = $this->Port; 598 } 599 600 if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) { 601 if ($this->Helo != '') { 602 $this->smtp->Hello($this->Helo); 782 // Retry while there is no connection 783 try { 784 while($index < count($hosts) && !$connection) { 785 $hostinfo = array(); 786 if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { 787 $host = $hostinfo[1]; 788 $port = $hostinfo[2]; 603 789 } else { 604 $this->smtp->Hello($this->ServerHostname()); 790 $host = $hosts[$index]; 791 $port = $this->Port; 605 792 } 606 793 607 $connection = true; 608 if($this->SMTPAuth) { 609 if(!$this->smtp->Authenticate($this->Username, $this->Password)) { 610 $this->SetError($this->Lang('authenticate')); 611 $this->smtp->Reset(); 612 $connection = false; 794 $tls = ($this->SMTPSecure == 'tls'); 795 $ssl = ($this->SMTPSecure == 'ssl'); 796 797 if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { 798 799 $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); 800 $this->smtp->Hello($hello); 801 802 if ($tls) { 803 if (!$this->smtp->StartTLS()) { 804 throw new phpmailerException($this->Lang('tls')); 805 } 806 807 //We must resend HELO after tls negotiation 808 $this->smtp->Hello($hello); 613 809 } 810 811 $connection = true; 812 if ($this->SMTPAuth) { 813 if (!$this->smtp->Authenticate($this->Username, $this->Password)) { 814 throw new phpmailerException($this->Lang('authenticate')); 815 } 816 } 614 817 } 818 $index++; 819 if (!$connection) { 820 throw new phpmailerException($this->Lang('connect_host')); 821 } 615 822 } 616 $index++; 823 } catch (phpmailerException $e) { 824 $this->smtp->Reset(); 825 throw $e; 617 826 } 618 if(!$connection) { 619 $this->SetError($this->Lang('connect_host')); 620 } 621 622 return $connection; 827 return true; 623 828 } 624 829 625 830 /** 626 831 * Closes the active SMTP session if one exists. 627 832 * @return void 628 833 */ 629 function SmtpClose() {630 if( $this->smtp != NULL) {834 public function SmtpClose() { 835 if(!is_null($this->smtp)) { 631 836 if($this->smtp->Connected()) { 632 837 $this->smtp->Quit(); 633 838 $this->smtp->Close(); … … 636 841 } 637 842 638 843 /** 639 * Sets the language for all class error messages. Returns false 640 * if it cannot load the language file. The default language type 641 * is English. 642 * @param string $lang_type Type of language (e.g. Portuguese: "br") 643 * @param string $lang_path Path to the language file directory 644 * @access public 645 * @return bool 646 */ 647 function SetLanguage($lang_type, $lang_path = 'language/') { 648 if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) { 649 include($lang_path.'phpmailer.lang-'.$lang_type.'.php'); 650 } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) { 651 include($lang_path.'phpmailer.lang-en.php'); 652 } else { 653 $PHPMAILER_LANG = array(); 654 $PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' . 655 $PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.'; 656 $PHPMAILER_LANG["execute"] = 'Could not execute: '; 657 $PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.'; 658 $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.'; 659 $PHPMAILER_LANG["from_failed"] = 'The following From address failed: '; 660 $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' . 661 $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.'; 662 $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.'; 663 $PHPMAILER_LANG["file_access"] = 'Could not access file: '; 664 $PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: '; 665 $PHPMAILER_LANG["encoding"] = 'Unknown encoding: '; 666 $PHPMAILER_LANG["signing"] = 'Signing Error: '; 844 * Sets the language for all class error messages. 845 * Returns false if it cannot load the language file. The default language is English. 846 * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") 847 * @param string $lang_path Path to the language file directory 848 * @access public 849 */ 850 function SetLanguage($langcode = 'en', $lang_path = 'language/') { 851 //Define full set of translatable strings 852 $PHPMAILER_LANG = array( 853 'provide_address' => 'You must provide at least one recipient email address.', 854 'mailer_not_supported' => ' mailer is not supported.', 855 'execute' => 'Could not execute: ', 856 'instantiate' => 'Could not instantiate mail function.', 857 'authenticate' => 'SMTP Error: Could not authenticate.', 858 'from_failed' => 'The following From address failed: ', 859 'recipients_failed' => 'SMTP Error: The following recipients failed: ', 860 'data_not_accepted' => 'SMTP Error: Data not accepted.', 861 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', 862 'file_access' => 'Could not access file: ', 863 'file_open' => 'File Error: Could not open file: ', 864 'encoding' => 'Unknown encoding: ', 865 'signing' => 'Signing Error: ', 866 'smtp_error' => 'SMTP server error: ', 867 'empty_message' => 'Message body empty', 868 'invalid_address' => 'Invalid address', 869 'variable_set' => 'Cannot set or reset variable: ' 870 ); 871 //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"! 872 $l = true; 873 if ($langcode != 'en') { //There is no English translation file 874 $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php'; 667 875 } 668 876 $this->language = $PHPMAILER_LANG; 877 return ($l == true); //Returns false if language not found 878 } 669 879 670 return true; 880 /** 881 * Return the current array of language strings 882 * @return array 883 */ 884 public function GetTranslations() { 885 return $this->language; 671 886 } 672 887 673 888 ///////////////////////////////////////////////// … … 676 891 677 892 /** 678 893 * Creates recipient headers. 679 * @access p rivate894 * @access public 680 895 * @return string 681 896 */ 682 function AddrAppend($type, $addr) {897 public function AddrAppend($type, $addr) { 683 898 $addr_str = $type . ': '; 684 $addr_str .= $this->AddrFormat($addr[0]); 685 if(count($addr) > 1) { 686 for($i = 1; $i < count($addr); $i++) { 687 $addr_str .= ', ' . $this->AddrFormat($addr[$i]); 688 } 899 $addresses = array(); 900 foreach ($addr as $a) { 901 $addresses[] = $this->AddrFormat($a); 689 902 } 903 $addr_str .= implode(', ', $addresses); 690 904 $addr_str .= $this->LE; 691 905 692 906 return $addr_str; … … 694 908 695 909 /** 696 910 * Formats an address correctly. 697 * @access p rivate911 * @access public 698 912 * @return string 699 913 */ 700 function AddrFormat($addr) {701 if (empty($addr[1])) {702 $formatted =$this->SecureHeader($addr[0]);914 public function AddrFormat($addr) { 915 if (empty($addr[1])) { 916 return $this->SecureHeader($addr[0]); 703 917 } else { 704 $formatted =$this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";918 return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; 705 919 } 706 707 return $formatted;708 920 } 709 921 710 922 /** 711 923 * Wraps message for use with mailers that do not 712 924 * automatically perform wrapping and for quoted-printable. 713 925 * Original written by philippe. 714 * @access private 926 * @param string $message The message to wrap 927 * @param integer $length The line length to wrap to 928 * @param boolean $qp_mode Whether to run in Quoted-Printable mode 929 * @access public 715 930 * @return string 716 931 */ 717 function WrapText($message, $length, $qp_mode = false) {932 public function WrapText($message, $length, $qp_mode = false) { 718 933 $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; 719 934 // If utf-8 encoding is used, we will need to make sure we don't 720 935 // split multibyte characters when we wrap … … 791 1006 * Finds last character boundary prior to maxLength in a utf-8 792 1007 * quoted (printable) encoded string. 793 1008 * Original written by Colin Brown. 794 * @access p rivate1009 * @access public 795 1010 * @param string $encodedText utf-8 QP text 796 1011 * @param int $maxLength find last character boundary prior to this length 797 1012 * @return int 798 1013 */ 799 function UTF8CharBoundary($encodedText, $maxLength) {1014 public function UTF8CharBoundary($encodedText, $maxLength) { 800 1015 $foundSplitPos = false; 801 1016 $lookBack = 3; 802 1017 while (!$foundSplitPos) { … … 828 1043 return $maxLength; 829 1044 } 830 1045 1046 831 1047 /** 832 1048 * Set the body wrapping. 833 * @access p rivate1049 * @access public 834 1050 * @return void 835 1051 */ 836 function SetWordWrap() {1052 public function SetWordWrap() { 837 1053 if($this->WordWrap < 1) { 838 1054 return; 839 1055 } 840 1056 841 1057 switch($this->message_type) { 842 1058 case 'alt': 843 /* fall through */844 1059 case 'alt_attachments': 845 1060 $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); 846 1061 break; … … 852 1067 853 1068 /** 854 1069 * Assembles message header. 855 * @access p rivate856 * @return string 1070 * @access public 1071 * @return string The assembled header 857 1072 */ 858 function CreateHeader() {1073 public function CreateHeader() { 859 1074 $result = ''; 860 1075 861 / * Set the boundaries */1076 // Set the boundaries 862 1077 $uniq_id = md5(uniqid(time())); 863 1078 $this->boundary[1] = 'b1_' . $uniq_id; 864 1079 $this->boundary[2] = 'b2_' . $uniq_id; 865 1080 866 $result .= $this->HeaderLine('Date', $this->RFCDate());1081 $result .= $this->HeaderLine('Date', self::RFCDate()); 867 1082 if($this->Sender == '') { 868 1083 $result .= $this->HeaderLine('Return-Path', trim($this->From)); 869 1084 } else { 870 1085 $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); 871 1086 } 872 1087 873 / * To be created automatically by mail() */1088 // To be created automatically by mail() 874 1089 if($this->Mailer != 'mail') { 875 if(count($this->to) > 0) { 876 $result .= $this->AddrAppend('To', $this->to); 877 } elseif (count($this->cc) == 0) { 878 $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); 1090 if ($this->SingleTo === true) { 1091 foreach($this->to as $t) { 1092 $this->SingleToArray[] = $this->AddrFormat($t); 1093 } 1094 } else { 1095 if(count($this->to) > 0) { 1096 $result .= $this->AddrAppend('To', $this->to); 1097 } elseif (count($this->cc) == 0) { 1098 $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); 1099 } 879 1100 } 880 1101 } 881 1102 … … 884 1105 $from[0][1] = $this->FromName; 885 1106 $result .= $this->AddrAppend('From', $from); 886 1107 887 / * sendmail and mail() extract Cc from the header before sending */888 if( (($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {1108 // sendmail and mail() extract Cc from the header before sending 1109 if(count($this->cc) > 0) { 889 1110 $result .= $this->AddrAppend('Cc', $this->cc); 890 1111 } 891 1112 892 / * sendmail and mail() extract Bcc from the header before sending */1113 // sendmail and mail() extract Bcc from the header before sending 893 1114 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { 894 1115 $result .= $this->AddrAppend('Bcc', $this->bcc); 895 1116 } 896 1117 897 1118 if(count($this->ReplyTo) > 0) { 898 $result .= $this->AddrAppend('Reply- To', $this->ReplyTo);1119 $result .= $this->AddrAppend('Reply-to', $this->ReplyTo); 899 1120 } 900 1121 901 / * mail() sets the subject itself */1122 // mail() sets the subject itself 902 1123 if($this->Mailer != 'mail') { 903 1124 $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); 904 1125 } … … 909 1130 $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); 910 1131 } 911 1132 $result .= $this->HeaderLine('X-Priority', $this->Priority); 912 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');1133 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)'); 913 1134 914 1135 if($this->ConfirmReadingTo != '') { 915 1136 $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); … … 929 1150 930 1151 /** 931 1152 * Returns the message MIME. 932 * @access p rivate1153 * @access public 933 1154 * @return string 934 1155 */ 935 function GetMailMIME() {1156 public function GetMailMIME() { 936 1157 $result = ''; 937 1158 switch($this->message_type) { 938 1159 case 'plain': … … 940 1161 $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet); 941 1162 break; 942 1163 case 'attachments': 943 /* fall through */944 1164 case 'alt_attachments': 945 1165 if($this->InlineImageExists()){ 946 1166 $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); … … 964 1184 965 1185 /** 966 1186 * Assembles the message body. Returns an empty string on failure. 967 * @access p rivate968 * @return string 1187 * @access public 1188 * @return string The assembled message body 969 1189 */ 970 function CreateBody() { 971 $result = ''; 1190 public function CreateBody() { 1191 $body = ''; 1192 972 1193 if ($this->sign_key_file) { 973 $ result.= $this->GetMailMIME();1194 $body .= $this->GetMailMIME(); 974 1195 } 975 1196 976 1197 $this->SetWordWrap(); 977 1198 978 1199 switch($this->message_type) { 979 1200 case 'alt': 980 $ result.= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');981 $ result.= $this->EncodeString($this->AltBody, $this->Encoding);982 $ result.= $this->LE.$this->LE;983 $ result.= $this->GetBoundary($this->boundary[1], '', 'text/html', '');984 $ result.= $this->EncodeString($this->Body, $this->Encoding);985 $ result.= $this->LE.$this->LE;986 $ result.= $this->EndBoundary($this->boundary[1]);1201 $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); 1202 $body .= $this->EncodeString($this->AltBody, $this->Encoding); 1203 $body .= $this->LE.$this->LE; 1204 $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); 1205 $body .= $this->EncodeString($this->Body, $this->Encoding); 1206 $body .= $this->LE.$this->LE; 1207 $body .= $this->EndBoundary($this->boundary[1]); 987 1208 break; 988 1209 case 'plain': 989 $ result.= $this->EncodeString($this->Body, $this->Encoding);1210 $body .= $this->EncodeString($this->Body, $this->Encoding); 990 1211 break; 991 1212 case 'attachments': 992 $ result.= $this->GetBoundary($this->boundary[1], '', '', '');993 $ result.= $this->EncodeString($this->Body, $this->Encoding);994 $ result.= $this->LE;995 $ result.= $this->AttachAll();1213 $body .= $this->GetBoundary($this->boundary[1], '', '', ''); 1214 $body .= $this->EncodeString($this->Body, $this->Encoding); 1215 $body .= $this->LE; 1216 $body .= $this->AttachAll(); 996 1217 break; 997 1218 case 'alt_attachments': 998 $ result.= sprintf("--%s%s", $this->boundary[1], $this->LE);999 $ result.= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);1000 $ result.= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body1001 $ result.= $this->EncodeString($this->AltBody, $this->Encoding);1002 $ result.= $this->LE.$this->LE;1003 $ result.= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body1004 $ result.= $this->EncodeString($this->Body, $this->Encoding);1005 $ result.= $this->LE.$this->LE;1006 $ result.= $this->EndBoundary($this->boundary[2]);1007 $ result.= $this->AttachAll();1219 $body .= sprintf("--%s%s", $this->boundary[1], $this->LE); 1220 $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); 1221 $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body 1222 $body .= $this->EncodeString($this->AltBody, $this->Encoding); 1223 $body .= $this->LE.$this->LE; 1224 $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body 1225 $body .= $this->EncodeString($this->Body, $this->Encoding); 1226 $body .= $this->LE.$this->LE; 1227 $body .= $this->EndBoundary($this->boundary[2]); 1228 $body .= $this->AttachAll(); 1008 1229 break; 1009 1230 } 1010 1231 1011 if ($this->IsError()) {1012 $ result= '';1013 } else if ($this->sign_key_file) {1014 $file = tempnam("", "mail");1015 $fp = fopen($file, "w");1016 fwrite($fp, $result);1017 fclose($fp);1018 $signed = tempnam("", "signed");1019 1020 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) {1021 $fp = fopen($signed, "r");1022 $result = fread($fp, filesize($this->sign_key_file));1023 $result = '';1024 while(!feof($fp)){1025 $result = $result . fread($fp, 1024);1232 if ($this->IsError()) { 1233 $body = ''; 1234 } elseif ($this->sign_key_file) { 1235 try { 1236 $file = tempnam('', 'mail'); 1237 file_put_contents($file, $body); //TODO check this worked 1238 $signed = tempnam("", "signed"); 1239 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { 1240 @unlink($file); 1241 @unlink($signed); 1242 $body = file_get_contents($signed); 1243 } else { 1244 @unlink($file); 1245 @unlink($signed); 1246 throw new phpmailerException($this->Lang("signing").openssl_error_string()); 1026 1247 } 1027 fclose($fp); 1028 } else { 1029 $this->SetError($this->Lang("signing").openssl_error_string()); 1030 $result = ''; 1248 } catch (phpmailerException $e) { 1249 $body = ''; 1250 if ($this->exceptions) { 1251 throw $e; 1252 } 1031 1253 } 1032 1033 unlink($file);1034 unlink($signed);1035 1254 } 1036 1255 1037 return $ result;1256 return $body; 1038 1257 } 1039 1258 1040 1259 /** 1041 1260 * Returns the start of a message boundary. 1042 1261 * @access private 1043 1262 */ 1044 function GetBoundary($boundary, $charSet, $contentType, $encoding) {1263 private function GetBoundary($boundary, $charSet, $contentType, $encoding) { 1045 1264 $result = ''; 1046 1265 if($charSet == '') { 1047 1266 $charSet = $this->CharSet; … … 1065 1284 * Returns the end of a message boundary. 1066 1285 * @access private 1067 1286 */ 1068 function EndBoundary($boundary) {1287 private function EndBoundary($boundary) { 1069 1288 return $this->LE . '--' . $boundary . '--' . $this->LE; 1070 1289 } 1071 1290 … … 1074 1293 * @access private 1075 1294 * @return void 1076 1295 */ 1077 function SetMessageType() {1296 private function SetMessageType() { 1078 1297 if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { 1079 1298 $this->message_type = 'plain'; 1080 1299 } else { … … 1090 1309 } 1091 1310 } 1092 1311 1093 /* Returns a formatted header line. 1094 * @access private 1312 /** 1313 * Returns a formatted header line. 1314 * @access public 1095 1315 * @return string 1096 1316 */ 1097 function HeaderLine($name, $value) {1317 public function HeaderLine($name, $value) { 1098 1318 return $name . ': ' . $value . $this->LE; 1099 1319 } 1100 1320 1101 1321 /** 1102 1322 * Returns a formatted mail line. 1103 * @access p rivate1323 * @access public 1104 1324 * @return string 1105 1325 */ 1106 function TextLine($value) {1326 public function TextLine($value) { 1107 1327 return $value . $this->LE; 1108 1328 } 1109 1329 … … 1121 1341 * @param string $type File extension (MIME) type. 1122 1342 * @return bool 1123 1343 */ 1124 function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 1125 if(!@is_file($path)) { 1126 $this->SetError($this->Lang('file_access') . $path); 1127 return false; 1128 } 1344 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 1345 try { 1346 if ( !@is_file($path) ) { 1347 throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); 1348 } 1349 $filename = basename($path); 1350 if ( $name == '' ) { 1351 $name = $filename; 1352 } 1129 1353 1130 $filename = basename($path); 1131 if($name == '') { 1132 $name = $filename; 1354 $this->attachment[] = array( 1355 0 => $path, 1356 1 => $filename, 1357 2 => $name, 1358 3 => $encoding, 1359 4 => $type, 1360 5 => false, // isStringAttachment 1361 6 => 'attachment', 1362 7 => 0 1363 ); 1364 1365 } catch (phpmailerException $e) { 1366 $this->SetError($e->getMessage()); 1367 if ($this->exceptions) { 1368 throw $e; 1369 } 1370 echo $e->getMessage()."\n"; 1371 if ( $e->getCode() == self::STOP_CRITICAL ) { 1372 return false; 1373 } 1133 1374 } 1134 1135 $cur = count($this->attachment);1136 $this->attachment[$cur][0] = $path;1137 $this->attachment[$cur][1] = $filename;1138 $this->attachment[$cur][2] = $name;1139 $this->attachment[$cur][3] = $encoding;1140 $this->attachment[$cur][4] = $type;1141 $this->attachment[$cur][5] = false; // isStringAttachment1142 $this->attachment[$cur][6] = 'attachment';1143 $this->attachment[$cur][7] = 0;1144 1145 1375 return true; 1146 1376 } 1147 1377 1148 1378 /** 1379 * Return the current array of attachments 1380 * @return array 1381 */ 1382 public function GetAttachments() { 1383 return $this->attachment; 1384 } 1385 1386 /** 1149 1387 * Attaches all fs, string, and binary attachments to the message. 1150 1388 * Returns an empty string on failure. 1151 1389 * @access private 1152 1390 * @return string 1153 1391 */ 1154 function AttachAll() {1155 / * Return text of body */1392 private function AttachAll() { 1393 // Return text of body 1156 1394 $mime = array(); 1395 $cidUniq = array(); 1396 $incl = array(); 1157 1397 1158 / * Add all attachments */1159 for ($i = 0; $i < count($this->attachment); $i++) {1160 / * Check for string attachment */1161 $bString = $ this->attachment[$i][5];1398 // Add all attachments 1399 foreach ($this->attachment as $attachment) { 1400 // Check for string attachment 1401 $bString = $attachment[5]; 1162 1402 if ($bString) { 1163 $string = $ this->attachment[$i][0];1403 $string = $attachment[0]; 1164 1404 } else { 1165 $path = $ this->attachment[$i][0];1405 $path = $attachment[0]; 1166 1406 } 1167 1407 1168 $filename = $this->attachment[$i][1]; 1169 $name = $this->attachment[$i][2]; 1170 $encoding = $this->attachment[$i][3]; 1171 $type = $this->attachment[$i][4]; 1172 $disposition = $this->attachment[$i][6]; 1173 $cid = $this->attachment[$i][7]; 1408 if (in_array($attachment[0], $incl)) { continue; } 1409 $filename = $attachment[1]; 1410 $name = $attachment[2]; 1411 $encoding = $attachment[3]; 1412 $type = $attachment[4]; 1413 $disposition = $attachment[6]; 1414 $cid = $attachment[7]; 1415 $incl[] = $attachment[0]; 1416 if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; } 1417 $cidUniq[$cid] = true; 1174 1418 1175 1419 $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); 1176 1420 $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); … … 1182 1426 1183 1427 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); 1184 1428 1185 / * Encode as string attachment */1429 // Encode as string attachment 1186 1430 if($bString) { 1187 1431 $mime[] = $this->EncodeString($string, $encoding); 1188 1432 if($this->IsError()) { … … 1204 1448 } 1205 1449 1206 1450 /** 1207 * Encodes attachment in requested format. Returns an 1208 * empty string on failure. 1451 * Encodes attachment in requested format. 1452 * Returns an empty string on failure. 1453 * @param string $path The full path to the file 1454 * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' 1455 * @see EncodeFile() 1209 1456 * @access private 1210 1457 * @return string 1211 1458 */ 1212 function EncodeFile ($path, $encoding = 'base64') { 1213 if(!@$fd = fopen($path, 'rb')) { 1214 $this->SetError($this->Lang('file_open') . $path); 1459 private function EncodeFile($path, $encoding = 'base64') { 1460 try { 1461 if (!is_readable($path)) { 1462 throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); 1463 } 1464 if (function_exists('get_magic_quotes')) { 1465 function get_magic_quotes() { 1466 return false; 1467 } 1468 } 1469 if (PHP_VERSION < 6) { 1470 $magic_quotes = get_magic_quotes_runtime(); 1471 set_magic_quotes_runtime(0); 1472 } 1473 $file_buffer = file_get_contents($path); 1474 $file_buffer = $this->EncodeString($file_buffer, $encoding); 1475 if (PHP_VERSION < 6) { set_magic_quotes_runtime($magic_quotes); } 1476 return $file_buffer; 1477 } catch (Exception $e) { 1478 $this->SetError($e->getMessage()); 1215 1479 return ''; 1216 1480 } 1217 $magic_quotes = get_magic_quotes_runtime();1218 set_magic_quotes_runtime(0);1219 $file_buffer = fread($fd, filesize($path));1220 $file_buffer = $this->EncodeString($file_buffer, $encoding);1221 fclose($fd);1222 set_magic_quotes_runtime($magic_quotes);1223 1224 return $file_buffer;1225 1481 } 1226 1482 1227 1483 /** 1228 * Encodes string to requested format. Returns an 1229 * empty string on failure. 1230 * @access private 1484 * Encodes string to requested format. 1485 * Returns an empty string on failure. 1486 * @param string $str The text to encode 1487 * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' 1488 * @access public 1231 1489 * @return string 1232 1490 */ 1233 function EncodeString ($str, $encoding = 'base64') {1491 public function EncodeString ($str, $encoding = 'base64') { 1234 1492 $encoded = ''; 1235 1493 switch(strtolower($encoding)) { 1236 1494 case 'base64': 1237 /* chunk_split is found in PHP >= 3.0.6 */1238 1495 $encoded = chunk_split(base64_encode($str), 76, $this->LE); 1239 1496 break; 1240 1497 case '7bit': 1241 1498 case '8bit': 1242 1499 $encoded = $this->FixEOL($str); 1500 //Make sure it ends with a line break 1243 1501 if (substr($encoded, -(strlen($this->LE))) != $this->LE) 1244 1502 $encoded .= $this->LE; 1245 1503 break; … … 1257 1515 } 1258 1516 1259 1517 /** 1260 * Encode a header string to best of Q, B, quoted or none.1261 * @access p rivate1518 * Encode a header string to best (shortest) of Q, B, quoted or none. 1519 * @access public 1262 1520 * @return string 1263 1521 */ 1264 function EncodeHeader($str, $position = 'text') {1522 public function EncodeHeader($str, $position = 'text') { 1265 1523 $x = 0; 1266 1524 1267 1525 switch (strtolower($position)) { 1268 1526 case 'phrase': 1269 1527 if (!preg_match('/[\200-\377]/', $str)) { 1270 / * Can't use addslashes as we don't know what value has magic_quotes_sybase. */1528 // Can't use addslashes as we don't know what value has magic_quotes_sybase 1271 1529 $encoded = addcslashes($str, "\0..\37\177\\\""); 1272 1530 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { 1273 1531 return ($encoded); … … 1279 1537 break; 1280 1538 case 'comment': 1281 1539 $x = preg_match_all('/[()"]/', $str, $matches); 1282 / * Fall-through */1540 // Fall-through 1283 1541 case 'text': 1284 1542 default: 1285 1543 $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); … … 1291 1549 } 1292 1550 1293 1551 $maxlen = 75 - 7 - strlen($this->CharSet); 1294 / * Try to select the encoding which should produce the shortest output */1552 // Try to select the encoding which should produce the shortest output 1295 1553 if (strlen($str)/3 < $x) { 1296 1554 $encoding = 'B'; 1297 1555 if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { 1298 // Use a custom function which correctly encodes and wraps long1299 // multibyte strings without breaking lines within a character1556 // Use a custom function which correctly encodes and wraps long 1557 // multibyte strings without breaking lines within a character 1300 1558 $encoded = $this->Base64EncodeWrapMB($str); 1301 1559 } else { 1302 1560 $encoded = base64_encode($str); … … 1318 1576 1319 1577 /** 1320 1578 * Checks if a string contains multibyte characters. 1321 * @access p rivate1579 * @access public 1322 1580 * @param string $str multi-byte text to wrap encode 1323 1581 * @return bool 1324 1582 */ 1325 function HasMultiBytes($str) {1583 public function HasMultiBytes($str) { 1326 1584 if (function_exists('mb_strlen')) { 1327 1585 return (strlen($str) > mb_strlen($str, $this->CharSet)); 1328 1586 } else { // Assume no multibytes (we can't handle without mbstring functions anyway) 1329 return False;1587 return false; 1330 1588 } 1331 1589 } 1332 1590 … … 1334 1592 * Correctly encodes and wraps long multibyte strings for mail headers 1335 1593 * without breaking lines within a character. 1336 1594 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php 1337 * @access p rivate1595 * @access public 1338 1596 * @param string $str multi-byte text to wrap encode 1339 1597 * @return string 1340 1598 */ 1341 function Base64EncodeWrapMB($str) {1599 public function Base64EncodeWrapMB($str) { 1342 1600 $start = "=?".$this->CharSet."?B?"; 1343 1601 $end = "?="; 1344 1602 $encoded = ""; … … 1371 1629 } 1372 1630 1373 1631 /** 1374 * Encode string to quoted-printable. 1375 * @access private 1376 * @return string 1377 */ 1378 function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) { 1632 * Encode string to quoted-printable. 1633 * Only uses standard PHP, slow, but will always work 1634 * @access public 1635 * @param string $string the text to encode 1636 * @param integer $line_max Number of chars allowed on a line before wrapping 1637 * @return string 1638 */ 1639 public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { 1379 1640 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 1380 1641 $lines = preg_split('/(?:\r\n|\r|\n)/', $input); 1381 1642 $eol = "\r\n"; … … 1417 1678 } 1418 1679 1419 1680 /** 1420 * Callback for converting to "=XX". 1421 * @access private 1422 * @return string 1423 */ 1424 function EncodeQ_callback ($matches) { 1425 return sprintf('=%02X', ord($matches[1])); 1681 * Encode string to RFC2045 (6.7) quoted-printable format 1682 * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version 1683 * Also results in same content as you started with after decoding 1684 * @see EncodeQPphp() 1685 * @access public 1686 * @param string $string the text to encode 1687 * @param integer $line_max Number of chars allowed on a line before wrapping 1688 * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function 1689 * @return string 1690 * @author Marcus Bointon 1691 */ 1692 public function EncodeQP($string, $line_max = 76, $space_conv = false) { 1693 if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) 1694 return quoted_printable_encode($string); 1695 } 1696 $filters = stream_get_filters(); 1697 if (!in_array('convert.*', $filters)) { //Got convert stream filter? 1698 return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation 1699 } 1700 $fp = fopen('php://temp/', 'r+'); 1701 $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks 1702 $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); 1703 $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); 1704 fputs($fp, $string); 1705 rewind($fp); 1706 $out = stream_get_contents($fp); 1707 stream_filter_remove($s); 1708 $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange 1709 fclose($fp); 1710 return $out; 1426 1711 } 1427 1712 1428 1713 /** 1429 1714 * Encode string to q encoding. 1430 * @access private 1715 * @link http://tools.ietf.org/html/rfc2047 1716 * @param string $str the text to encode 1717 * @param string $position Where the text is going to be used, see the RFC for what that means 1718 * @access public 1431 1719 * @return string 1432 1720 */ 1433 function EncodeQ ($str, $position = 'text') {1434 / * There should not be any EOL in the string */1435 $encoded = preg_replace( "/[\r\n]/", '', $str);1721 public function EncodeQ ($str, $position = 'text') { 1722 // There should not be any EOL in the string 1723 $encoded = preg_replace('/[\r\n]*/', '', $str); 1436 1724 1437 1725 switch (strtolower($position)) { 1438 1726 case 'phrase': 1439 $encoded = preg_replace_callback("/([^A-Za-z0-9!*+\/ -])/", 1440 array('PHPMailer', 'EncodeQ_callback'), $encoded); 1727 $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1441 1728 break; 1442 1729 case 'comment': 1443 $encoded = preg_replace_callback("/([\(\)\"])/", 1444 array('PHPMailer', 'EncodeQ_callback'), $encoded); 1445 break; 1730 $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1446 1731 case 'text': 1447 1732 default: 1448 /* Replace every high ascii, control =, ? and _ characters */ 1449 $encoded = preg_replace_callback('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/', 1450 array('PHPMailer', 'EncodeQ_callback'), $encoded); 1733 // Replace every high ascii, control =, ? and _ characters 1734 //TODO using /e (equivalent to eval()) is probably not a good idea 1735 $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', 1736 "'='.sprintf('%02X', ord('\\1'))", $encoded); 1451 1737 break; 1452 1738 } 1453 1739 1454 / * Replace every spaces to _ (more readable than =20) */1740 // Replace every spaces to _ (more readable than =20) 1455 1741 $encoded = str_replace(' ', '_', $encoded); 1456 1742 1457 1743 return $encoded; … … 1467 1753 * @param string $type File extension (MIME) type. 1468 1754 * @return void 1469 1755 */ 1470 function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { 1471 /* Append to $attachment array */ 1472 $cur = count($this->attachment); 1473 $this->attachment[$cur][0] = $string; 1474 $this->attachment[$cur][1] = $filename; 1475 $this->attachment[$cur][2] = $filename; 1476 $this->attachment[$cur][3] = $encoding; 1477 $this->attachment[$cur][4] = $type; 1478 $this->attachment[$cur][5] = true; // isString 1479 $this->attachment[$cur][6] = 'attachment'; 1480 $this->attachment[$cur][7] = 0; 1756 public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { 1757 // Append to $attachment array 1758 $this->attachment[] = array( 1759 0 => $string, 1760 1 => $filename, 1761 2 => basename($filename), 1762 3 => $encoding, 1763 4 => $type, 1764 5 => true, // isStringAttachment 1765 6 => 'attachment', 1766 7 => 0 1767 ); 1481 1768 } 1482 1769 1483 1770 /** … … 1493 1780 * @param string $type File extension (MIME) type. 1494 1781 * @return bool 1495 1782 */ 1496 function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {1783 public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 1497 1784 1498 if (!@is_file($path)) {1785 if ( !@is_file($path) ) { 1499 1786 $this->SetError($this->Lang('file_access') . $path); 1500 1787 return false; 1501 1788 } 1502 1789 1503 1790 $filename = basename($path); 1504 if ($name == '') {1791 if ( $name == '' ) { 1505 1792 $name = $filename; 1506 1793 } 1507 1794 1508 /* Append to $attachment array */ 1509 $cur = count($this->attachment); 1510 $this->attachment[$cur][0] = $path; 1511 $this->attachment[$cur][1] = $filename; 1512 $this->attachment[$cur][2] = $name; 1513 $this->attachment[$cur][3] = $encoding; 1514 $this->attachment[$cur][4] = $type; 1515 $this->attachment[$cur][5] = false; 1516 $this->attachment[$cur][6] = 'inline'; 1517 $this->attachment[$cur][7] = $cid; 1795 // Append to $attachment array 1796 $this->attachment[] = array( 1797 0 => $path, 1798 1 => $filename, 1799 2 => $name, 1800 3 => $encoding, 1801 4 => $type, 1802 5 => false, // isStringAttachment 1803 6 => 'inline', 1804 7 => $cid 1805 ); 1518 1806 1519 1807 return true; 1520 1808 } 1521 1809 1522 1810 /** 1523 1811 * Returns true if an inline attachment is present. 1524 * @access p rivate1812 * @access public 1525 1813 * @return bool 1526 1814 */ 1527 function InlineImageExists() { 1528 $result = false; 1529 for($i = 0; $i < count($this->attachment); $i++) { 1530 if($this->attachment[$i][6] == 'inline') { 1531 $result = true; 1532 break; 1815 public function InlineImageExists() { 1816 foreach($this->attachment as $attachment) { 1817 if ($attachment[6] == 'inline') { 1818 return true; 1533 1819 } 1534 1820 } 1535 1536 return $result; 1821 return false; 1537 1822 } 1538 1823 1539 1824 ///////////////////////////////////////////////// … … 1544 1829 * Clears all recipients assigned in the TO array. Returns void. 1545 1830 * @return void 1546 1831 */ 1547 function ClearAddresses() { 1832 public function ClearAddresses() { 1833 foreach($this->to as $to) { 1834 unset($this->all_recipients[strtolower($to[0])]); 1835 } 1548 1836 $this->to = array(); 1549 1837 } 1550 1838 … … 1552 1840 * Clears all recipients assigned in the CC array. Returns void. 1553 1841 * @return void 1554 1842 */ 1555 function ClearCCs() { 1843 public function ClearCCs() { 1844 foreach($this->cc as $cc) { 1845 unset($this->all_recipients[strtolower($cc[0])]); 1846 } 1556 1847 $this->cc = array(); 1557 1848 } 1558 1849 … … 1560 1851 * Clears all recipients assigned in the BCC array. Returns void. 1561 1852 * @return void 1562 1853 */ 1563 function ClearBCCs() { 1854 public function ClearBCCs() { 1855 foreach($this->bcc as $bcc) { 1856 unset($this->all_recipients[strtolower($bcc[0])]); 1857 } 1564 1858 $this->bcc = array(); 1565 1859 } 1566 1860 … … 1568 1862 * Clears all recipients assigned in the ReplyTo array. Returns void. 1569 1863 * @return void 1570 1864 */ 1571 function ClearReplyTos() {1865 public function ClearReplyTos() { 1572 1866 $this->ReplyTo = array(); 1573 1867 } 1574 1868 … … 1577 1871 * array. Returns void. 1578 1872 * @return void 1579 1873 */ 1580 function ClearAllRecipients() {1874 public function ClearAllRecipients() { 1581 1875 $this->to = array(); 1582 1876 $this->cc = array(); 1583 1877 $this->bcc = array(); 1878 $this->all_recipients = array(); 1584 1879 } 1585 1880 1586 1881 /** … … 1588 1883 * attachments. Returns void. 1589 1884 * @return void 1590 1885 */ 1591 function ClearAttachments() {1886 public function ClearAttachments() { 1592 1887 $this->attachment = array(); 1593 1888 } 1594 1889 … … 1596 1891 * Clears all custom headers. Returns void. 1597 1892 * @return void 1598 1893 */ 1599 function ClearCustomHeaders() {1894 public function ClearCustomHeaders() { 1600 1895 $this->CustomHeader = array(); 1601 1896 } 1602 1897 … … 1606 1901 1607 1902 /** 1608 1903 * Adds the error message to the error container. 1609 * Returns void. 1610 * @access private 1904 * @access protected 1611 1905 * @return void 1612 1906 */ 1613 function SetError($msg) {1907 protected function SetError($msg) { 1614 1908 $this->error_count++; 1909 if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { 1910 $lasterror = $this->smtp->getError(); 1911 if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) { 1912 $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n"; 1913 } 1914 } 1615 1915 $this->ErrorInfo = $msg; 1616 1916 } 1617 1917 1618 1918 /** 1619 1919 * Returns the proper RFC 822 formatted date. 1620 * @access p rivate1920 * @access public 1621 1921 * @return string 1922 * @static 1622 1923 */ 1623 function RFCDate() {1924 public static function RFCDate() { 1624 1925 $tz = date('Z'); 1625 1926 $tzs = ($tz < 0) ? '-' : '+'; 1626 1927 $tz = abs($tz); … … 1631 1932 } 1632 1933 1633 1934 /** 1634 * Returns the appropriate server variable. Should work with both1635 * PHP 4.1.0+ as well as older versions. Returns an empty string1636 * if nothing is found.1637 * @access private1638 * @return mixed1639 */1640 function ServerVar($varName) {1641 global $HTTP_SERVER_VARS;1642 global $HTTP_ENV_VARS;1643 1644 if(!isset($_SERVER)) {1645 $_SERVER = $HTTP_SERVER_VARS;1646 if(!isset($_SERVER['REMOTE_ADDR'])) {1647 $_SERVER = $HTTP_ENV_VARS; // must be Apache1648 }1649 }1650 1651 if(isset($_SERVER[$varName])) {1652 return $_SERVER[$varName];1653 } else {1654 return '';1655 }1656 }1657 1658 /**1659 1935 * Returns the server hostname or 'localhost.localdomain' if unknown. 1660 1936 * @access private 1661 1937 * @return string 1662 1938 */ 1663 function ServerHostname() {1664 if ( $this->Hostname != '') {1939 private function ServerHostname() { 1940 if (!empty($this->Hostname)) { 1665 1941 $result = $this->Hostname; 1666 } elseif ( $this->ServerVar('SERVER_NAME') != '') {1667 $result = $ this->ServerVar('SERVER_NAME');1942 } elseif (isset($_SERVER['SERVER_NAME'])) { 1943 $result = $_SERVER['SERVER_NAME']; 1668 1944 } else { 1669 1945 $result = 'localhost.localdomain'; 1670 1946 } … … 1677 1953 * @access private 1678 1954 * @return string 1679 1955 */ 1680 function Lang($key) {1956 private function Lang($key) { 1681 1957 if(count($this->language) < 1) { 1682 1958 $this->SetLanguage('en'); // set the default language 1683 1959 } … … 1691 1967 1692 1968 /** 1693 1969 * Returns true if an error occurred. 1970 * @access public 1694 1971 * @return bool 1695 1972 */ 1696 function IsError() {1973 public function IsError() { 1697 1974 return ($this->error_count > 0); 1698 1975 } 1699 1976 … … 1702 1979 * @access private 1703 1980 * @return string 1704 1981 */ 1705 function FixEOL($str) {1982 private function FixEOL($str) { 1706 1983 $str = str_replace("\r\n", "\n", $str); 1707 1984 $str = str_replace("\r", "\n", $str); 1708 1985 $str = str_replace("\n", $this->LE, $str); … … 1711 1988 1712 1989 /** 1713 1990 * Adds a custom header. 1991 * @access public 1714 1992 * @return void 1715 1993 */ 1716 function AddCustomHeader($custom_header) {1994 public function AddCustomHeader($custom_header) { 1717 1995 $this->CustomHeader[] = explode(':', $custom_header, 2); 1718 1996 } 1719 1997 … … 1722 2000 * @access public 1723 2001 * @return $message 1724 2002 */ 1725 function MsgHTML($message,$basedir='') {2003 public function MsgHTML($message, $basedir = '') { 1726 2004 preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); 1727 2005 if(isset($images[2])) { 1728 2006 foreach($images[2] as $i => $url) { 1729 2007 // do not change urls for absolute images (thanks to corvuscorax) 1730 if (!preg_match(' /^[A-z][A-z]*:\/\//',$url)) {2008 if (!preg_match('#^[A-z]+://#',$url)) { 1731 2009 $filename = basename($url); 1732 2010 $directory = dirname($url); 1733 2011 ($directory == '.')?$directory='':''; 1734 2012 $cid = 'cid:' . md5($filename); 1735 $fileParts = split("\.", $filename); 1736 $ext = $fileParts[1]; 1737 $mimeType = $this->_mime_types($ext); 2013 $ext = pathinfo($filename, PATHINFO_EXTENSION); 2014 $mimeType = self::_mime_types($ext); 1738 2015 if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } 1739 2016 if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; } 1740 2017 if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { … … 1746 2023 $this->IsHTML(true); 1747 2024 $this->Body = $message; 1748 2025 $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); 1749 if ( !empty($textMsg) && empty($this->AltBody)) {2026 if (!empty($textMsg) && empty($this->AltBody)) { 1750 2027 $this->AltBody = html_entity_decode($textMsg); 1751 2028 } 1752 if ( empty($this->AltBody)) {1753 $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";2029 if (empty($this->AltBody)) { 2030 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; 1754 2031 } 1755 2032 } 1756 2033 1757 2034 /** 1758 * Gets the mime type of the embedded or inline image 1759 * @access private 1760 * @return mime type of ext 2035 * Gets the MIME type of the embedded or inline image 2036 * @param string File extension 2037 * @access public 2038 * @return string MIME type of ext 2039 * @static 1761 2040 */ 1762 function _mime_types($ext = '') {2041 public static function _mime_types($ext = '') { 1763 2042 $mimes = array( 1764 'ai' => 'application/postscript', 1765 'aif' => 'audio/x-aiff', 1766 'aifc' => 'audio/x-aiff', 1767 'aiff' => 'audio/x-aiff', 1768 'avi' => 'video/x-msvideo', 2043 'hqx' => 'application/mac-binhex40', 2044 'cpt' => 'application/mac-compactpro', 2045 'doc' => 'application/msword', 1769 2046 'bin' => 'application/macbinary', 1770 'bmp' => 'image/bmp', 2047 'dms' => 'application/octet-stream', 2048 'lha' => 'application/octet-stream', 2049 'lzh' => 'application/octet-stream', 2050 'exe' => 'application/octet-stream', 1771 2051 'class' => 'application/octet-stream', 1772 'cpt' => 'application/mac-compactpro', 1773 'css' => 'text/css', 2052 'psd' => 'application/octet-stream', 2053 'so' => 'application/octet-stream', 2054 'sea' => 'application/octet-stream', 2055 'dll' => 'application/octet-stream', 2056 'oda' => 'application/oda', 2057 'pdf' => 'application/pdf', 2058 'ai' => 'application/postscript', 2059 'eps' => 'application/postscript', 2060 'ps' => 'application/postscript', 2061 'smi' => 'application/smil', 2062 'smil' => 'application/smil', 2063 'mif' => 'application/vnd.mif', 2064 'xls' => 'application/vnd.ms-excel', 2065 'ppt' => 'application/vnd.ms-powerpoint', 2066 'wbxml' => 'application/vnd.wap.wbxml', 2067 'wmlc' => 'application/vnd.wap.wmlc', 1774 2068 'dcr' => 'application/x-director', 1775 2069 'dir' => 'application/x-director', 1776 'dll' => 'application/octet-stream', 1777 'dms' => 'application/octet-stream', 1778 'doc' => 'application/msword', 2070 'dxr' => 'application/x-director', 1779 2071 'dvi' => 'application/x-dvi', 1780 'dxr' => 'application/x-director',1781 'eml' => 'message/rfc822',1782 'eps' => 'application/postscript',1783 'exe' => 'application/octet-stream',1784 'gif' => 'image/gif',1785 2072 'gtar' => 'application/x-gtar', 1786 'htm' => 'text/html', 1787 'html' => 'text/html', 1788 'jpe' => 'image/jpeg', 1789 'jpeg' => 'image/jpeg', 1790 'jpg' => 'image/jpeg', 1791 'hqx' => 'application/mac-binhex40', 2073 'php' => 'application/x-httpd-php', 2074 'php4' => 'application/x-httpd-php', 2075 'php3' => 'application/x-httpd-php', 2076 'phtml' => 'application/x-httpd-php', 2077 'phps' => 'application/x-httpd-php-source', 1792 2078 'js' => 'application/x-javascript', 1793 'lha' => 'application/octet-stream', 1794 'log' => 'text/plain', 1795 'lzh' => 'application/octet-stream', 2079 'swf' => 'application/x-shockwave-flash', 2080 'sit' => 'application/x-stuffit', 2081 'tar' => 'application/x-tar', 2082 'tgz' => 'application/x-tar', 2083 'xhtml' => 'application/xhtml+xml', 2084 'xht' => 'application/xhtml+xml', 2085 'zip' => 'application/zip', 1796 2086 'mid' => 'audio/midi', 1797 2087 'midi' => 'audio/midi', 1798 'mif' => 'application/vnd.mif', 1799 'mov' => 'video/quicktime', 1800 'movie' => 'video/x-sgi-movie', 2088 'mpga' => 'audio/mpeg', 1801 2089 'mp2' => 'audio/mpeg', 1802 2090 'mp3' => 'audio/mpeg', 1803 'mpe' => 'video/mpeg', 1804 'mpeg' => 'video/mpeg', 1805 'mpg' => 'video/mpeg', 1806 'mpga' => 'audio/mpeg', 1807 'oda' => 'application/oda', 1808 'pdf' => 'application/pdf', 1809 'php' => 'application/x-httpd-php', 1810 'php3' => 'application/x-httpd-php', 1811 'php4' => 'application/x-httpd-php', 1812 'phps' => 'application/x-httpd-php-source', 1813 'phtml' => 'application/x-httpd-php', 1814 'png' => 'image/png', 1815 'ppt' => 'application/vnd.ms-powerpoint', 1816 'ps' => 'application/postscript', 1817 'psd' => 'application/octet-stream', 1818 'qt' => 'video/quicktime', 1819 'ra' => 'audio/x-realaudio', 2091 'aif' => 'audio/x-aiff', 2092 'aiff' => 'audio/x-aiff', 2093 'aifc' => 'audio/x-aiff', 1820 2094 'ram' => 'audio/x-pn-realaudio', 1821 2095 'rm' => 'audio/x-pn-realaudio', 1822 2096 'rpm' => 'audio/x-pn-realaudio-plugin', 1823 'rtf' => 'text/rtf', 1824 'rtx' => 'text/richtext', 2097 'ra' => 'audio/x-realaudio', 1825 2098 'rv' => 'video/vnd.rn-realvideo', 1826 'sea' => 'application/octet-stream', 2099 'wav' => 'audio/x-wav', 2100 'bmp' => 'image/bmp', 2101 'gif' => 'image/gif', 2102 'jpeg' => 'image/jpeg', 2103 'jpg' => 'image/jpeg', 2104 'jpe' => 'image/jpeg', 2105 'png' => 'image/png', 2106 'tiff' => 'image/tiff', 2107 'tif' => 'image/tiff', 2108 'css' => 'text/css', 2109 'html' => 'text/html', 2110 'htm' => 'text/html', 1827 2111 'shtml' => 'text/html', 1828 'sit' => 'application/x-stuffit', 1829 'so' => 'application/octet-stream', 1830 'smi' => 'application/smil', 1831 'smil' => 'application/smil', 1832 'swf' => 'application/x-shockwave-flash', 1833 'tar' => 'application/x-tar', 2112 'txt' => 'text/plain', 1834 2113 'text' => 'text/plain', 1835 'txt' => 'text/plain', 1836 'tgz' => 'application/x-tar', 1837 'tif' => 'image/tiff', 1838 'tiff' => 'image/tiff', 1839 'wav' => 'audio/x-wav', 1840 'wbxml' => 'application/vnd.wap.wbxml', 1841 'wmlc' => 'application/vnd.wap.wmlc', 2114 'log' => 'text/plain', 2115 'rtx' => 'text/richtext', 2116 'rtf' => 'text/rtf', 2117 'xml' => 'text/xml', 2118 'xsl' => 'text/xml', 2119 'mpeg' => 'video/mpeg', 2120 'mpg' => 'video/mpeg', 2121 'mpe' => 'video/mpeg', 2122 'qt' => 'video/quicktime', 2123 'mov' => 'video/quicktime', 2124 'avi' => 'video/x-msvideo', 2125 'movie' => 'video/x-sgi-movie', 2126 'doc' => 'application/msword', 1842 2127 'word' => 'application/msword', 1843 'xht' => 'application/xhtml+xml',1844 'xhtml' => 'application/xhtml+xml',1845 2128 'xl' => 'application/excel', 1846 'xls' => 'application/vnd.ms-excel', 1847 'xml' => 'text/xml', 1848 'xsl' => 'text/xml', 1849 'zip' => 'application/zip' 2129 'eml' => 'message/rfc822' 1850 2130 ); 1851 return ( !isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];2131 return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; 1852 2132 } 1853 2133 1854 2134 /** 1855 * Set (or reset) Class Objects (variables) 2135 * Set (or reset) Class Objects (variables) 2136 * 2137 * Usage Example: 2138 * $page->set('X-Priority', '3'); 2139 * 2140 * @access public 2141 * @param string $name Parameter Name 2142 * @param mixed $value Parameter Value 2143 * NOTE: will not work with arrays, there are no arrays to set/reset 2144 * @todo Should this not be using __set() magic function? 2145 */ 2146 public function set($name, $value = '') { 2147 try { 2148 if (isset($this->$name) ) { 2149 $this->$name = $value; 2150 } else { 2151 throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL); 2152 } 2153 } catch (Exception $e) { 2154 $this->SetError($e->getMessage()); 2155 if ($e->getCode() == self::STOP_CRITICAL) { 2156 return false; 2157 } 2158 } 2159 return true; 2160 } 2161 2162 /** 2163 * Strips newlines to prevent header injection. 2164 * @access public 2165 * @param string $str String 2166 * @return string 2167 */ 2168 public function SecureHeader($str) { 2169 $str = str_replace("\r", '', $str); 2170 $str = str_replace("\n", '', $str); 2171 return trim($str); 2172 } 2173 2174 /** 2175 * Set the private key file and password to sign the message. 1856 2176 * 1857 * Usage Example: 1858 * $page->set('X-Priority', '3'); 2177 * @access public 2178 * @param string $key_filename Parameter File Name 2179 * @param string $key_pass Password for private key 2180 */ 2181 public function Sign($cert_filename, $key_filename, $key_pass) { 2182 $this->sign_cert_file = $cert_filename; 2183 $this->sign_key_file = $key_filename; 2184 $this->sign_key_pass = $key_pass; 2185 } 2186 2187 /** 2188 * Set the private key file and password to sign the message. 1859 2189 * 1860 2190 * @access public 1861 * @param string $name Parameter Name 1862 * @param mixed $value Parameter Value 1863 * NOTE: will not work with arrays, there are no arrays to set/reset 2191 * @param string $key_filename Parameter File Name 2192 * @param string $key_pass Password for private key 1864 2193 */ 1865 function set ( $name, $value = '' ) { 1866 if ( isset($this->$name) ) { 1867 $this->$name = $value; 1868 } else { 1869 $this->SetError('Cannot set or reset variable ' . $name); 1870 return false; 2194 public function DKIM_QP($txt) { 2195 $tmp=""; 2196 $line=""; 2197 for ($i=0;$i<strlen($txt);$i++) { 2198 $ord=ord($txt[$i]); 2199 if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) { 2200 $line.=$txt[$i]; 2201 } else { 2202 $line.="=".sprintf("%02X",$ord); 2203 } 1871 2204 } 2205 return $line; 1872 2206 } 1873 2207 1874 2208 /** 1875 * Read a file from a supplied filename and return it.2209 * Generate DKIM signature 1876 2210 * 1877 2211 * @access public 1878 * @param string $ filename Parameter File Name2212 * @param string $s Header 1879 2213 */ 1880 function getFile($filename) { 1881 $return = ''; 1882 if ($fp = fopen($filename, 'rb')) { 1883 while (!feof($fp)) { 1884 $return .= fread($fp, 1024); 1885 } 1886 fclose($fp); 1887 return $return; 2214 public function DKIM_Sign($s) { 2215 $privKeyStr = file_get_contents($this->DKIM_private); 2216 if ($this->DKIM_passphrase!='') { 2217 $privKey = openssl_pkey_get_private($privKeyStr,$this->DKIM_passphrase); 1888 2218 } else { 1889 return false;2219 $privKey = $privKeyStr; 1890 2220 } 2221 if (openssl_sign($s, $signature, $privKey)) { 2222 return base64_encode($signature); 2223 } 1891 2224 } 1892 2225 1893 2226 /** 1894 * Strips newlines to prevent header injection.1895 * @access private1896 * @ param string $str String1897 * @ return string2227 * Generate DKIM Canonicalization Header 2228 * 2229 * @access public 2230 * @param string $s Header 1898 2231 */ 1899 function SecureHeader($str) { 1900 $str = trim($str); 1901 $str = str_replace("\r", "", $str); 1902 $str = str_replace("\n", "", $str); 1903 return $str; 2232 public function DKIM_HeaderC($s) { 2233 $s=preg_replace("/\r\n\s+/"," ",$s); 2234 $lines=explode("\r\n",$s); 2235 foreach ($lines as $key=>$line) { 2236 list($heading,$value)=explode(":",$line,2); 2237 $heading=strtolower($heading); 2238 $value=preg_replace("/\s+/"," ",$value) ; // Compress useless spaces 2239 $lines[$key]=$heading.":".trim($value) ; // Don't forget to remove WSP around the value 2240 } 2241 $s=implode("\r\n",$lines); 2242 return $s; 1904 2243 } 1905 2244 1906 2245 /** 1907 * Set the private key file and password to sign the message.2246 * Generate DKIM Canonicalization Body 1908 2247 * 1909 2248 * @access public 1910 * @param string $key_filename Parameter File Name 1911 * @param string $key_pass Password for private key 2249 * @param string $body Message Body 1912 2250 */ 1913 function Sign($cert_filename, $key_filename, $key_pass) { 1914 $this->sign_cert_file = $cert_filename; 1915 $this->sign_key_file = $key_filename; 1916 $this->sign_key_pass = $key_pass; 2251 public function DKIM_BodyC($body) { 2252 if ($body == '') return "\r\n"; 2253 // stabilize line endings 2254 $body=str_replace("\r\n","\n",$body); 2255 $body=str_replace("\n","\r\n",$body); 2256 // END stabilize line endings 2257 while (substr($body,strlen($body)-4,4) == "\r\n\r\n") { 2258 $body=substr($body,0,strlen($body)-2); 2259 } 2260 return $body; 1917 2261 } 1918 2262 2263 /** 2264 * Create the DKIM header, body, as new header 2265 * 2266 * @access public 2267 * @param string $headers_line Header lines 2268 * @param string $subject Subject 2269 * @param string $body Body 2270 */ 2271 public function DKIM_Add($headers_line,$subject,$body) { 2272 $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms 2273 $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body 2274 $DKIMquery = 'dns/txt'; // Query method 2275 $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) 2276 $subject_header = "Subject: $subject"; 2277 $headers = explode("\r\n",$headers_line); 2278 foreach($headers as $header) { 2279 if (strpos($header,'From:') === 0) { 2280 $from_header=$header; 2281 } elseif (strpos($header,'To:') === 0) { 2282 $to_header=$header; 2283 } 2284 } 2285 $from = str_replace('|','=7C',$this->DKIM_QP($from_header)); 2286 $to = str_replace('|','=7C',$this->DKIM_QP($to_header)); 2287 $subject = str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable 2288 $body = $this->DKIM_BodyC($body); 2289 $DKIMlen = strlen($body) ; // Length of body 2290 $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body 2291 $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";"; 2292 $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n". 2293 "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n". 2294 "\th=From:To:Subject;\r\n". 2295 "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n". 2296 "\tz=$from\r\n". 2297 "\t|$to\r\n". 2298 "\t|$subject;\r\n". 2299 "\tbh=" . $DKIMb64 . ";\r\n". 2300 "\tb="; 2301 $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); 2302 $signed = $this->DKIM_Sign($toSign); 2303 return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n"; 2304 } 2305 2306 protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) { 2307 if (!empty($this->action_function) && function_exists($this->action_function)) { 2308 $params = array($isSent,$to,$cc,$bcc,$subject,$body); 2309 call_user_func_array($this->action_function,$params); 2310 } 2311 } 1919 2312 } 1920 2313 1921 ?> 2314 class phpmailerException extends Exception { 2315 public function errorMessage() { 2316 $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n"; 2317 return $errorMsg; 2318 } 2319 } 2320 ?> 2321 No newline at end of file -
wp-includes/class-pop3.php
1 1 <?php 2 /*~ class.pop3.php 3 .---------------------------------------------------------------------------. 4 | Software: PHPMailer - PHP email class | 5 | Version: 5.1 | 6 | Contact: via sourceforge.net support pages (also www.codeworxtech.com) | 7 | Info: http://phpmailer.sourceforge.net | 8 | Support: http://sourceforge.net/projects/phpmailer/ | 9 | ------------------------------------------------------------------------- | 10 | Admin: Andy Prevost (project admininistrator) | 11 | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 12 | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | 13 | Founder: Brent R. Matzelle (original founder) | 14 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | 15 | Copyright (c) 2001-2003, Brent R. Matzelle | 16 | ------------------------------------------------------------------------- | 17 | License: Distributed under the Lesser General Public License (LGPL) | 18 | http://www.gnu.org/copyleft/lesser.html | 19 | This program is distributed in the hope that it will be useful - WITHOUT | 20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 21 | FITNESS FOR A PARTICULAR PURPOSE. | 22 | ------------------------------------------------------------------------- | 23 | We offer a number of paid services (www.codeworxtech.com): | 24 | - Web Hosting on highly optimized fast and secure servers | 25 | - Technology Consulting | 26 | - Oursourcing (highly qualified programmers and graphic designers) | 27 '---------------------------------------------------------------------------' 28 */ 29 2 30 /** 3 * mail_fetch/setup.php 31 * PHPMailer - PHP POP Before SMTP Authentication Class 32 * NOTE: Designed for use with PHP version 5 and up 33 * @package PHPMailer 34 * @author Andy Prevost 35 * @author Marcus Bointon 36 * @copyright 2004 - 2009 Andy Prevost 37 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 38 * @version $Id$ 39 */ 40 41 /** 42 * POP Before SMTP Authentication Class 43 * Version 5.0.0 4 44 * 5 * @package SquirrelMail 45 * Author: Richard Davey (rich@corephp.co.uk) 46 * Modifications: Andy Prevost 47 * License: LGPL, see PHPMailer License 6 48 * 7 * @copyright (c) 1999-2006 The SquirrelMail Project Team 49 * Specifically for PHPMailer to allow POP before SMTP authentication. 50 * Does not yet work with APOP - if you have an APOP account, contact Richard Davey 51 * and we can test changes to this script. 8 52 * 9 * @copyright (c) 1999 CDI (cdi@thewebmasters.net) All Rights Reserved 10 * Modified by Philippe Mingo 2001 mingo@rotedic.com 11 * An RFC 1939 compliant wrapper class for the POP3 protocol. 53 * This class is based on the structure of the SMTP class originally authored by Chris Ryan 12 54 * 13 * Licensed under the GNU GPL. For full terms see the file COPYING.14 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License55 * This class is rfc 1939 compliant and implements all the commands 56 * required for POP3 connection, authentication and disconnection. 15 57 * 16 * pop3 class 17 * 18 * $Id$ 58 * @package PHPMailer 59 * @author Richard Davey 19 60 */ 20 61 21 62 class POP3 { 22 var $ERROR = ''; // Error string. 63 /** 64 * Default POP3 port 65 * @var int 66 */ 67 public $POP3_PORT = 110; 23 68 24 var $TIMEOUT = 60; // Default timeout before giving up on a 25 // network operation. 69 /** 70 * Default Timeout 71 * @var int 72 */ 73 public $POP3_TIMEOUT = 30; 26 74 27 var $COUNT = -1; // Mailbox msg count 75 /** 76 * POP3 Carriage Return + Line Feed 77 * @var string 78 */ 79 public $CRLF = "\r\n"; 28 80 29 var $BUFFER = 512; // Socket buffer for socket fgets() calls. 30 // Per RFC 1939 the returned line a POP3 31 // server can send is 512 bytes. 81 /** 82 * Displaying Debug warnings? (0 = now, 1+ = yes) 83 * @var int 84 */ 85 public $do_debug = 2; 32 86 33 var $FP = ''; // The connection to the server's 34 // file descriptor 87 /** 88 * POP3 Mail Server 89 * @var string 90 */ 91 public $host; 35 92 36 var $MAILSERVER = ''; // Set this to hard code the server name 93 /** 94 * POP3 Port 95 * @var int 96 */ 97 public $port; 37 98 38 var $DEBUG = FALSE; // set to true to echo pop3 39 // commands and responses to error_log 40 // this WILL log passwords! 99 /** 100 * POP3 Timeout Value 101 * @var int 102 */ 103 public $tval; 41 104 42 var $BANNER = ''; // Holds the banner returned by the 43 // pop server - used for apop() 105 /** 106 * POP3 Username 107 * @var string 108 */ 109 public $username; 44 110 45 var $ALLOWAPOP = FALSE; // Allow or disallow apop() 46 // This must be set to true 47 // manually 111 /** 112 * POP3 Password 113 * @var string 114 */ 115 public $password; 48 116 49 function POP3 ( $server = '', $timeout = '' ) { 50 settype($this->BUFFER,"integer"); 51 if( !empty($server) ) { 52 // Do not allow programs to alter MAILSERVER 53 // if it is already specified. They can get around 54 // this if they -really- want to, so don't count on it. 55 if(empty($this->MAILSERVER)) 56 $this->MAILSERVER = $server; 57 } 58 if(!empty($timeout)) { 59 settype($timeout,"integer"); 60 $this->TIMEOUT = $timeout; 61 if (!ini_get('safe_mode')) 62 set_time_limit($timeout); 63 } 64 return true; 65 } 117 ///////////////////////////////////////////////// 118 // PROPERTIES, PRIVATE AND PROTECTED 119 ///////////////////////////////////////////////// 66 120 67 function update_timer () { 68 if (!ini_get('safe_mode')) 69 set_time_limit($this->TIMEOUT); 70 return true; 71 } 121 private $pop_conn; 122 private $connected; 123 private $error; // Error log array 72 124 73 function connect ($server, $port = 110) { 74 // Opens a socket to the specified server. Unless overridden, 75 // port defaults to 110. Returns true on success, false on fail 125 /** 126 * Constructor, sets the initial values 127 * @access public 128 * @return POP3 129 */ 130 public function __construct() { 131 $this->pop_conn = 0; 132 $this->connected = false; 133 $this->error = null; 134 } 76 135 77 // If MAILSERVER is set, override $server with it's value 136 /** 137 * Combination of public events - connect, login, disconnect 138 * @access public 139 * @param string $host 140 * @param integer $port 141 * @param integer $tval 142 * @param string $username 143 * @param string $password 144 */ 145 public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) { 146 $this->host = $host; 78 147 79 if (!isset($port) || !$port) {$port = 110;} 80 if(!empty($this->MAILSERVER)) 81 $server = $this->MAILSERVER; 148 // If no port value is passed, retrieve it 149 if ($port == false) { 150 $this->port = $this->POP3_PORT; 151 } else { 152 $this->port = $port; 153 } 82 154 83 if(empty($server)){ 84 $this->ERROR = "POP3 connect: " . _("No server specified"); 85 unset($this->FP); 86 return false; 87 } 155 // If no port value is passed, retrieve it 156 if ($tval == false) { 157 $this->tval = $this->POP3_TIMEOUT; 158 } else { 159 $this->tval = $tval; 160 } 88 161 89 $fp = @fsockopen("$server", $port, $errno, $errstr); 162 $this->do_debug = $debug_level; 163 $this->username = $username; 164 $this->password = $password; 90 165 91 if(!$fp) { 92 $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]"; 93 unset($this->FP); 94 return false; 95 } 166 // Refresh the error log 167 $this->error = null; 96 168 97 socket_set_blocking($fp,-1); 98 $this->update_timer(); 99 $reply = fgets($fp,$this->BUFFER); 100 $reply = $this->strip_clf($reply); 101 if($this->DEBUG) 102 error_log("POP3 SEND [connect: $server] GOT [$reply]",0); 103 if(!$this->is_ok($reply)) { 104 $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]"; 105 unset($this->FP); 106 return false; 107 } 108 $this->FP = $fp; 109 $this->BANNER = $this->parse_banner($reply); 110 return true; 111 } 169 // Connect 170 $result = $this->Connect($this->host, $this->port, $this->tval); 112 171 113 function user ($user = "") {114 // Sends the USER command, returns true or false172 if ($result) { 173 $login_result = $this->Login($this->username, $this->password); 115 174 116 if( empty($user) ) { 117 $this->ERROR = "POP3 user: " . _("no login ID submitted"); 118 return false; 119 } elseif(!isset($this->FP)) { 120 $this->ERROR = "POP3 user: " . _("connection not established"); 121 return false; 122 } else { 123 $reply = $this->send_cmd("USER $user"); 124 if(!$this->is_ok($reply)) { 125 $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]"; 126 return false; 127 } else 128 return true; 129 } 130 } 175 if ($login_result) { 176 $this->Disconnect(); 131 177 132 function pass ($pass = "") { 133 // Sends the PASS command, returns # of msgs in mailbox, 134 // returns false (undef) on Auth failure 178 return true; 179 } 135 180 136 if(empty($pass)) {137 $this->ERROR = "POP3 pass: " . _("No password submitted");138 return false;139 } elseif(!isset($this->FP)) {140 $this->ERROR = "POP3 pass: " . _("connection not established");141 return false;142 } else {143 $reply = $this->send_cmd("PASS $pass");144 if(!$this->is_ok($reply)) {145 $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]";146 $this->quit();147 return false;148 } else {149 // Auth successful.150 $count = $this->last("count");151 $this->COUNT = $count;152 return $count;153 }154 }155 181 } 156 182 157 function apop ($login,$pass) { 158 // Attempts an APOP login. If this fails, it'll 159 // try a standard login. YOUR SERVER MUST SUPPORT 160 // THE USE OF THE APOP COMMAND! 161 // (apop is optional per rfc1939) 183 // We need to disconnect regardless if the login succeeded 184 $this->Disconnect(); 162 185 163 if(!isset($this->FP)) { 164 $this->ERROR = "POP3 apop: " . _("No connection to server"); 165 return false; 166 } elseif(!$this->ALLOWAPOP) { 167 $retVal = $this->login($login,$pass); 168 return $retVal; 169 } elseif(empty($login)) { 170 $this->ERROR = "POP3 apop: " . _("No login ID submitted"); 171 return false; 172 } elseif(empty($pass)) { 173 $this->ERROR = "POP3 apop: " . _("No password submitted"); 174 return false; 175 } else { 176 $banner = $this->BANNER; 177 if( (!$banner) or (empty($banner)) ) { 178 $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort"); 179 $retVal = $this->login($login,$pass); 180 return $retVal; 181 } else { 182 $AuthString = $banner; 183 $AuthString .= $pass; 184 $APOPString = md5($AuthString); 185 $cmd = "APOP $login $APOPString"; 186 $reply = $this->send_cmd($cmd); 187 if(!$this->is_ok($reply)) { 188 $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort"); 189 $retVal = $this->login($login,$pass); 190 return $retVal; 191 } else { 192 // Auth successful. 193 $count = $this->last("count"); 194 $this->COUNT = $count; 195 return $count; 196 } 197 } 198 } 199 } 186 return false; 187 } 200 188 201 function login ($login = "", $pass = "") { 202 // Sends both user and pass. Returns # of msgs in mailbox or 203 // false on failure (or -1, if the error occurs while getting 204 // the number of messages.) 205 206 if( !isset($this->FP) ) { 207 $this->ERROR = "POP3 login: " . _("No connection to server"); 208 return false; 209 } else { 210 $fp = $this->FP; 211 if( !$this->user( $login ) ) { 212 // Preserve the error generated by user() 213 return false; 214 } else { 215 $count = $this->pass($pass); 216 if( (!$count) || ($count == -1) ) { 217 // Preserve the error generated by last() and pass() 218 return false; 219 } else 220 return $count; 221 } 222 } 189 /** 190 * Connect to the POP3 server 191 * @access public 192 * @param string $host 193 * @param integer $port 194 * @param integer $tval 195 * @return boolean 196 */ 197 public function Connect ($host, $port = false, $tval = 30) { 198 // Are we already connected? 199 if ($this->connected) { 200 return true; 223 201 } 224 202 225 function top ($msgNum, $numLines = "0") { 226 // Gets the header and first $numLines of the msg body 227 // returns data in an array with each returned line being 228 // an array element. If $numLines is empty, returns 229 // only the header information, and none of the body. 203 /* 204 On Windows this will raise a PHP Warning error if the hostname doesn't exist. 205 Rather than supress it with @fsockopen, let's capture it cleanly instead 206 */ 230 207 231 if(!isset($this->FP)) { 232 $this->ERROR = "POP3 top: " . _("No connection to server"); 233 return false; 234 } 235 $this->update_timer(); 208 set_error_handler(array(&$this, 'catchWarning')); 236 209 237 $fp = $this->FP; 238 $buffer = $this->BUFFER; 239 $cmd = "TOP $msgNum $numLines"; 240 fwrite($fp, "TOP $msgNum $numLines\r\n"); 241 $reply = fgets($fp, $buffer); 242 $reply = $this->strip_clf($reply); 243 if($this->DEBUG) { 244 @error_log("POP3 SEND [$cmd] GOT [$reply]",0); 245 } 246 if(!$this->is_ok($reply)) 247 { 248 $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]"; 249 return false; 250 } 210 // Connect to the POP3 server 211 $this->pop_conn = fsockopen($host, // POP3 Host 212 $port, // Port # 213 $errno, // Error Number 214 $errstr, // Error Message 215 $tval); // Timeout (seconds) 251 216 252 $count = 0;253 $MsgArray = array();217 // Restore the error handler 218 restore_error_handler(); 254 219 255 $line = fgets($fp,$buffer); 256 while ( !ereg("^\.\r\n",$line)) 257 { 258 $MsgArray[$count] = $line; 259 $count++; 260 $line = fgets($fp,$buffer); 261 if(empty($line)) { break; } 262 } 263 264 return $MsgArray; 220 // Does the Error Log now contain anything? 221 if ($this->error && $this->do_debug >= 1) { 222 $this->displayErrors(); 265 223 } 266 224 267 function pop_list ($msgNum = "") { 268 // If called with an argument, returns that msgs' size in octets 269 // No argument returns an associative array of undeleted 270 // msg numbers and their sizes in octets 225 // Did we connect? 226 if ($this->pop_conn == false) { 227 // It would appear not... 228 $this->error = array( 229 'error' => "Failed to connect to server $host on port $port", 230 'errno' => $errno, 231 'errstr' => $errstr 232 ); 271 233 272 if(!isset($this->FP)) 273 { 274 $this->ERROR = "POP3 pop_list: " . _("No connection to server"); 275 return false; 276 } 277 $fp = $this->FP; 278 $Total = $this->COUNT; 279 if( (!$Total) or ($Total == -1) ) 280 { 281 return false; 282 } 283 if($Total == 0) 284 { 285 return array("0","0"); 286 // return -1; // mailbox empty 287 } 234 if ($this->do_debug >= 1) { 235 $this->displayErrors(); 236 } 288 237 289 $this->update_timer(); 290 291 if(!empty($msgNum)) 292 { 293 $cmd = "LIST $msgNum"; 294 fwrite($fp,"$cmd\r\n"); 295 $reply = fgets($fp,$this->BUFFER); 296 $reply = $this->strip_clf($reply); 297 if($this->DEBUG) { 298 @error_log("POP3 SEND [$cmd] GOT [$reply]",0); 299 } 300 if(!$this->is_ok($reply)) 301 { 302 $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; 303 return false; 304 } 305 list($junk,$num,$size) = preg_split('/\s+/',$reply); 306 return $size; 307 } 308 $cmd = "LIST"; 309 $reply = $this->send_cmd($cmd); 310 if(!$this->is_ok($reply)) 311 { 312 $reply = $this->strip_clf($reply); 313 $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; 314 return false; 315 } 316 $MsgArray = array(); 317 $MsgArray[0] = $Total; 318 for($msgC=1;$msgC <= $Total; $msgC++) 319 { 320 if($msgC > $Total) { break; } 321 $line = fgets($fp,$this->BUFFER); 322 $line = $this->strip_clf($line); 323 if(ereg("^\.",$line)) 324 { 325 $this->ERROR = "POP3 pop_list: " . _("Premature end of list"); 326 return false; 327 } 328 list($thisMsg,$msgSize) = preg_split('/\s+/',$line); 329 settype($thisMsg,"integer"); 330 if($thisMsg != $msgC) 331 { 332 $MsgArray[$msgC] = "deleted"; 333 } 334 else 335 { 336 $MsgArray[$msgC] = $msgSize; 337 } 338 } 339 return $MsgArray; 238 return false; 340 239 } 341 240 342 function get ($msgNum) { 343 // Retrieve the specified msg number. Returns an array 344 // where each line of the msg is an array element. 241 // Increase the stream time-out 345 242 346 if(!isset($this->FP)) 347 { 348 $this->ERROR = "POP3 get: " . _("No connection to server"); 349 return false; 350 } 243 // Check for PHP 4.3.0 or later 244 if (version_compare(phpversion(), '5.0.0', 'ge')) { 245 stream_set_timeout($this->pop_conn, $tval, 0); 246 } else { 247 // Does not work on Windows 248 if (substr(PHP_OS, 0, 3) !== 'WIN') { 249 socket_set_timeout($this->pop_conn, $tval, 0); 250 } 251 } 351 252 352 $this->update_timer(); 253 // Get the POP3 server response 254 $pop3_response = $this->getResponse(); 353 255 354 $fp = $this->FP; 355 $buffer = $this->BUFFER; 356 $cmd = "RETR $msgNum"; 357 $reply = $this->send_cmd($cmd); 256 // Check for the +OK 257 if ($this->checkResponse($pop3_response)) { 258 // The connection is established and the POP3 server is talking 259 $this->connected = true; 260 return true; 261 } 358 262 359 if(!$this->is_ok($reply)) 360 { 361 $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]"; 362 return false; 363 } 263 } 364 264 365 $count = 0; 366 $MsgArray = array(); 265 /** 266 * Login to the POP3 server (does not support APOP yet) 267 * @access public 268 * @param string $username 269 * @param string $password 270 * @return boolean 271 */ 272 public function Login ($username = '', $password = '') { 273 if ($this->connected == false) { 274 $this->error = 'Not connected to POP3 server'; 367 275 368 $line = fgets($fp,$buffer); 369 while ( !ereg("^\.\r\n",$line)) 370 { 371 if ( $line[0] == '.' ) { $line = substr($line,1); } 372 $MsgArray[$count] = $line; 373 $count++; 374 $line = fgets($fp,$buffer); 375 if(empty($line)) { break; } 376 } 377 return $MsgArray; 276 if ($this->do_debug >= 1) { 277 $this->displayErrors(); 278 } 378 279 } 379 280 380 function last ( $type = "count" ) { 381 // Returns the highest msg number in the mailbox. 382 // returns -1 on error, 0+ on success, if type != count 383 // results in a popstat() call (2 element array returned) 384 385 $last = -1; 386 if(!isset($this->FP)) 387 { 388 $this->ERROR = "POP3 last: " . _("No connection to server"); 389 return $last; 390 } 391 392 $reply = $this->send_cmd("STAT"); 393 if(!$this->is_ok($reply)) 394 { 395 $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]"; 396 return $last; 397 } 398 399 $Vars = preg_split('/\s+/',$reply); 400 $count = $Vars[1]; 401 $size = $Vars[2]; 402 settype($count,"integer"); 403 settype($size,"integer"); 404 if($type != "count") 405 { 406 return array($count,$size); 407 } 408 return $count; 281 if (empty($username)) { 282 $username = $this->username; 409 283 } 410 284 411 function reset () { 412 // Resets the status of the remote server. This includes 413 // resetting the status of ALL msgs to not be deleted. 414 // This method automatically closes the connection to the server. 415 416 if(!isset($this->FP)) 417 { 418 $this->ERROR = "POP3 reset: " . _("No connection to server"); 419 return false; 420 } 421 $reply = $this->send_cmd("RSET"); 422 if(!$this->is_ok($reply)) 423 { 424 // The POP3 RSET command -never- gives a -ERR 425 // response - if it ever does, something truely 426 // wild is going on. 427 428 $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]"; 429 @error_log("POP3 reset: ERROR [$reply]",0); 430 } 431 $this->quit(); 432 return true; 285 if (empty($password)) { 286 $password = $this->password; 433 287 } 434 288 435 function send_cmd ( $cmd = "" ) 436 { 437 // Sends a user defined command string to the 438 // POP server and returns the results. Useful for 439 // non-compliant or custom POP servers. 440 // Do NOT includ the \r\n as part of your command 441 // string - it will be appended automatically. 289 $pop_username = "USER $username" . $this->CRLF; 290 $pop_password = "PASS $password" . $this->CRLF; 442 291 443 // The return value is a standard fgets() call, which444 // will read up to $this->BUFFER bytes of data, until it445 // encounters a new line, or EOF, whichever happens first.292 // Send the Username 293 $this->sendString($pop_username); 294 $pop3_response = $this->getResponse(); 446 295 447 // This method works best if $cmd responds with only 448 // one line of data. 296 if ($this->checkResponse($pop3_response)) { 297 // Send the Password 298 $this->sendString($pop_password); 299 $pop3_response = $this->getResponse(); 449 300 450 if(!isset($this->FP)) 451 { 452 $this->ERROR = "POP3 send_cmd: " . _("No connection to server"); 453 return false; 454 } 455 456 if(empty($cmd)) 457 { 458 $this->ERROR = "POP3 send_cmd: " . _("Empty command string"); 459 return ""; 460 } 461 462 $fp = $this->FP; 463 $buffer = $this->BUFFER; 464 $this->update_timer(); 465 fwrite($fp,"$cmd\r\n"); 466 $reply = fgets($fp,$buffer); 467 $reply = $this->strip_clf($reply); 468 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 469 return $reply; 470 } 471 472 function quit() { 473 // Closes the connection to the POP3 server, deleting 474 // any msgs marked as deleted. 475 476 if(!isset($this->FP)) 477 { 478 $this->ERROR = "POP3 quit: " . _("connection does not exist"); 479 return false; 480 } 481 $fp = $this->FP; 482 $cmd = "QUIT"; 483 fwrite($fp,"$cmd\r\n"); 484 $reply = fgets($fp,$this->BUFFER); 485 $reply = $this->strip_clf($reply); 486 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 487 fclose($fp); 488 unset($this->FP); 301 if ($this->checkResponse($pop3_response)) { 489 302 return true; 303 } else { 304 return false; 305 } 306 } else { 307 return false; 490 308 } 309 } 491 310 492 function popstat () { 493 // Returns an array of 2 elements. The number of undeleted 494 // msgs in the mailbox, and the size of the mbox in octets. 311 /** 312 * Disconnect from the POP3 server 313 * @access public 314 */ 315 public function Disconnect () { 316 $this->sendString('QUIT'); 495 317 496 $PopArray = $this->last("array"); 318 fclose($this->pop_conn); 319 } 497 320 498 if($PopArray == -1) { return false; } 321 ///////////////////////////////////////////////// 322 // Private Methods 323 ///////////////////////////////////////////////// 499 324 500 if( (!$PopArray) or (empty($PopArray)) ) 501 { 502 return false; 503 } 504 return $PopArray; 505 } 325 /** 326 * Get the socket response back. 327 * $size is the maximum number of bytes to retrieve 328 * @access private 329 * @param integer $size 330 * @return string 331 */ 332 private function getResponse ($size = 128) { 333 $pop3_response = fgets($this->pop_conn, $size); 506 334 507 function uidl ($msgNum = "") 508 { 509 // Returns the UIDL of the msg specified. If called with 510 // no arguments, returns an associative array where each 511 // undeleted msg num is a key, and the msg's uidl is the element 512 // Array element 0 will contain the total number of msgs 335 return $pop3_response; 336 } 513 337 514 if(!isset($this->FP)) { 515 $this->ERROR = "POP3 uidl: " . _("No connection to server"); 516 return false; 517 } 338 /** 339 * Send a string down the open socket connection to the POP3 server 340 * @access private 341 * @param string $string 342 * @return integer 343 */ 344 private function sendString ($string) { 345 $bytes_sent = fwrite($this->pop_conn, $string, strlen($string)); 518 346 519 $fp = $this->FP;520 $buffer = $this->BUFFER;347 return $bytes_sent; 348 } 521 349 522 if(!empty($msgNum)) { 523 $cmd = "UIDL $msgNum"; 524 $reply = $this->send_cmd($cmd); 525 if(!$this->is_ok($reply)) 526 { 527 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; 528 return false; 529 } 530 list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply); 531 return $myUidl; 532 } else { 533 $this->update_timer(); 350 /** 351 * Checks the POP3 server response for +OK or -ERR 352 * @access private 353 * @param string $string 354 * @return boolean 355 */ 356 private function checkResponse ($string) { 357 if (substr($string, 0, 3) !== '+OK') { 358 $this->error = array( 359 'error' => "Server reported an error: $string", 360 'errno' => 0, 361 'errstr' => '' 362 ); 534 363 535 $UIDLArray = array();536 $Total = $this->COUNT;537 $UIDLArray[0] = $Total;364 if ($this->do_debug >= 1) { 365 $this->displayErrors(); 366 } 538 367 539 if ($Total < 1) 540 { 541 return $UIDLArray; 542 } 543 $cmd = "UIDL"; 544 fwrite($fp, "UIDL\r\n"); 545 $reply = fgets($fp, $buffer); 546 $reply = $this->strip_clf($reply); 547 if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } 548 if(!$this->is_ok($reply)) 549 { 550 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; 551 return false; 552 } 553 554 $line = ""; 555 $count = 1; 556 $line = fgets($fp,$buffer); 557 while ( !ereg("^\.\r\n",$line)) { 558 if(ereg("^\.\r\n",$line)) { 559 break; 560 } 561 list ($msg,$msgUidl) = preg_split('/\s+/',$line); 562 $msgUidl = $this->strip_clf($msgUidl); 563 if($count == $msg) { 564 $UIDLArray[$msg] = $msgUidl; 565 } 566 else 567 { 568 $UIDLArray[$count] = 'deleted'; 569 } 570 $count++; 571 $line = fgets($fp,$buffer); 572 } 573 } 574 return $UIDLArray; 368 return false; 369 } else { 370 return true; 575 371 } 576 372 577 function delete ($msgNum = "") { 578 // Flags a specified msg as deleted. The msg will not 579 // be deleted until a quit() method is called. 373 } 580 374 581 if(!isset($this->FP)) 582 { 583 $this->ERROR = "POP3 delete: " . _("No connection to server"); 584 return false; 585 } 586 if(empty($msgNum)) 587 { 588 $this->ERROR = "POP3 delete: " . _("No msg number submitted"); 589 return false; 590 } 591 $reply = $this->send_cmd("DELE $msgNum"); 592 if(!$this->is_ok($reply)) 593 { 594 $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]"; 595 return false; 596 } 597 return true; 598 } 375 /** 376 * If debug is enabled, display the error message array 377 * @access private 378 */ 379 private function displayErrors () { 380 echo '<pre>'; 599 381 600 // ********************************************************* 601 602 // The following methods are internal to the class. 603 604 function is_ok ($cmd = "") { 605 // Return true or false on +OK or -ERR 606 607 if( empty($cmd) ) 608 return false; 609 else 610 return( ereg ("^\+OK", $cmd ) ); 382 foreach ($this->error as $single_error) { 383 print_r($single_error); 611 384 } 612 385 613 function strip_clf ($text = "") {614 // Strips \r\n from server responses386 echo '</pre>'; 387 } 615 388 616 if(empty($text)) 617 return $text; 618 else { 619 $stripped = str_replace("\r",'',$text); 620 $stripped = str_replace("\n",'',$stripped); 621 return $stripped; 622 } 623 } 389 /** 390 * Takes over from PHP for the socket warning handler 391 * @access private 392 * @param integer $errno 393 * @param string $errstr 394 * @param string $errfile 395 * @param integer $errline 396 */ 397 private function catchWarning ($errno, $errstr, $errfile, $errline) { 398 $this->error[] = array( 399 'error' => "Connecting to the POP3 server raised a PHP warning: ", 400 'errno' => $errno, 401 'errstr' => $errstr 402 ); 403 } 624 404 625 function parse_banner ( $server_text ) { 626 $outside = true; 627 $banner = ""; 628 $length = strlen($server_text); 629 for($count =0; $count < $length; $count++) 630 { 631 $digit = substr($server_text,$count,1); 632 if(!empty($digit)) { 633 if( (!$outside) && ($digit != '<') && ($digit != '>') ) 634 { 635 $banner .= $digit; 636 } 637 if ($digit == '<') 638 { 639 $outside = false; 640 } 641 if($digit == '>') 642 { 643 $outside = true; 644 } 645 } 646 } 647 $banner = $this->strip_clf($banner); // Just in case 648 return "<$banner>"; 649 } 650 651 } // End class 652 ?> 405 // End of class 406 } 407 ?> 408 No newline at end of file -
wp-includes/class-smtp.php
2 2 /*~ class.smtp.php 3 3 .---------------------------------------------------------------------------. 4 4 | Software: PHPMailer - PHP email class | 5 | Version: 2.0.4|5 | Version: 5.1 | 6 6 | Contact: via sourceforge.net support pages (also www.codeworxtech.com) | 7 7 | Info: http://phpmailer.sourceforge.net | 8 8 | Support: http://sourceforge.net/projects/phpmailer/ | 9 9 | ------------------------------------------------------------------------- | 10 | Author: Andy Prevost (project admininistrator) | 11 | Author: Brent R. Matzelle (original founder) | 12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. | 10 | Admin: Andy Prevost (project admininistrator) | 11 | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 12 | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | 13 | Founder: Brent R. Matzelle (original founder) | 14 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | 13 15 | Copyright (c) 2001-2003, Brent R. Matzelle | 14 16 | ------------------------------------------------------------------------- | 15 17 | License: Distributed under the Lesser General Public License (LGPL) | … … 23 25 | - Technology Consulting | 24 26 | - Oursourcing (highly qualified programmers and graphic designers) | 25 27 '---------------------------------------------------------------------------' 28 */ 29 30 /** 31 * PHPMailer - PHP SMTP email transport class 32 * NOTE: Designed for use with PHP version 5 and up 33 * @package PHPMailer 34 * @author Andy Prevost 35 * @author Marcus Bointon 36 * @copyright 2004 - 2008 Andy Prevost 37 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 38 * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $ 26 39 */ 40 27 41 /** 28 42 * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP 29 43 * commands except TURN which will always return a not implemented 30 44 * error. SMTP also provides some utility methods for sending mail 31 45 * to an SMTP server. 32 * @package PHPMailer 33 * @author Chris Ryan 46 * original author: Chris Ryan 34 47 */ 35 48 36 class SMTP 37 { 49 class SMTP { 38 50 /** 39 51 * SMTP server port 40 52 * @var int 41 53 */ 42 var$SMTP_PORT = 25;54 public $SMTP_PORT = 25; 43 55 44 56 /** 45 57 * SMTP reply line ending 46 58 * @var string 47 59 */ 48 var$CRLF = "\r\n";60 public $CRLF = "\r\n"; 49 61 50 62 /** 51 63 * Sets whether debugging is turned on 52 64 * @var bool 53 65 */ 54 var $do_debug; #the level of debug to perform66 public $do_debug; // the level of debug to perform 55 67 56 68 /** 57 69 * Sets VERP use on/off (default is off) 58 70 * @var bool 59 71 */ 60 var$do_verp = false;72 public $do_verp = false; 61 73 62 /**#@+ 63 * @access private 64 */ 65 var $smtp_conn; # the socket to the server 66 var $error; # error if any on the last call 67 var $helo_rply; # the reply the server sent to us for HELO 68 /**#@-*/ 74 ///////////////////////////////////////////////// 75 // PROPERTIES, PRIVATE AND PROTECTED 76 ///////////////////////////////////////////////// 69 77 78 private $smtp_conn; // the socket to the server 79 private $error; // error if any on the last call 80 private $helo_rply; // the reply the server sent to us for HELO 81 70 82 /** 71 83 * Initialize the class so that the data is in a known state. 72 84 * @access public 73 85 * @return void 74 86 */ 75 function SMTP() {87 public function __construct() { 76 88 $this->smtp_conn = 0; 77 89 $this->error = null; 78 90 $this->helo_rply = null; … … 80 92 $this->do_debug = 0; 81 93 } 82 94 83 / *************************************************************84 * CONNECTION FUNCTIONS *85 ***********************************************************/95 ///////////////////////////////////////////////// 96 // CONNECTION FUNCTIONS 97 ///////////////////////////////////////////////// 86 98 87 99 /** 88 100 * Connect to the server specified on the port specified. … … 97 109 * @access public 98 110 * @return bool 99 111 */ 100 function Connect($host,$port=0,$tval=30) {101 #set the error val to null so there is no confusion112 public function Connect($host, $port = 0, $tval = 30) { 113 // set the error val to null so there is no confusion 102 114 $this->error = null; 103 115 104 #make sure we are __not__ connected116 // make sure we are __not__ connected 105 117 if($this->connected()) { 106 # ok we are connected! what should we do? 107 # for now we will just give an error saying we 108 # are already connected 118 // already connected, generate error 109 119 $this->error = array("error" => "Already connected to a server"); 110 120 return false; 111 121 } … … 114 124 $port = $this->SMTP_PORT; 115 125 } 116 126 117 #connect to the smtp server118 $this->smtp_conn = fsockopen($host, #the host of the server119 $port, #the port to use120 $errno, #error number if any121 $errstr, #error message if any122 $tval); #give up after ? secs123 #verify we connected properly127 // connect to the smtp server 128 $this->smtp_conn = @fsockopen($host, // the host of the server 129 $port, // the port to use 130 $errno, // error number if any 131 $errstr, // error message if any 132 $tval); // give up after ? secs 133 // verify we connected properly 124 134 if(empty($this->smtp_conn)) { 125 135 $this->error = array("error" => "Failed to connect to server", 126 136 "errno" => $errno, 127 137 "errstr" => $errstr); 128 138 if($this->do_debug >= 1) { 129 echo "SMTP -> ERROR: " . $this->error["error"] . 130 ": $errstr ($errno)" . $this->CRLF; 139 echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'; 131 140 } 132 141 return false; 133 142 } 134 143 135 # sometimes the SMTP server takes a little longer to respond 136 # so we will give it a longer timeout for the first read 137 // Windows still does not have support for this timeout function 144 // SMTP server can take longer to respond, give longer timeout for first read 145 // Windows does not have support for this timeout function 138 146 if(substr(PHP_OS, 0, 3) != "WIN") 139 147 socket_set_timeout($this->smtp_conn, $tval, 0); 140 148 141 # get any announcement stuff149 // get any announcement 142 150 $announce = $this->get_lines(); 143 151 144 # set the timeout of any socket functions at 1/10 of a second145 //if(function_exists("socket_set_timeout"))146 // socket_set_timeout($this->smtp_conn, 0, 100000);152 if($this->do_debug >= 2) { 153 echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'; 154 } 147 155 156 return true; 157 } 158 159 /** 160 * Initiate a TLS communication with the server. 161 * 162 * SMTP CODE 220 Ready to start TLS 163 * SMTP CODE 501 Syntax error (no parameters allowed) 164 * SMTP CODE 454 TLS not available due to temporary reason 165 * @access public 166 * @return bool success 167 */ 168 public function StartTLS() { 169 $this->error = null; # to avoid confusion 170 171 if(!$this->connected()) { 172 $this->error = array("error" => "Called StartTLS() without being connected"); 173 return false; 174 } 175 176 fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); 177 178 $rply = $this->get_lines(); 179 $code = substr($rply,0,3); 180 148 181 if($this->do_debug >= 2) { 149 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $announce;182 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 150 183 } 151 184 185 if($code != 220) { 186 $this->error = 187 array("error" => "STARTTLS not accepted from server", 188 "smtp_code" => $code, 189 "smtp_msg" => substr($rply,4)); 190 if($this->do_debug >= 1) { 191 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 192 } 193 return false; 194 } 195 196 // Begin encrypted connection 197 if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { 198 return false; 199 } 200 152 201 return true; 153 202 } 154 203 … … 158 207 * @access public 159 208 * @return bool 160 209 */ 161 function Authenticate($username, $password) {210 public function Authenticate($username, $password) { 162 211 // Start authentication 163 212 fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); 164 213 … … 171 220 "smtp_code" => $code, 172 221 "smtp_msg" => substr($rply,4)); 173 222 if($this->do_debug >= 1) { 174 echo "SMTP -> ERROR: " . $this->error["error"] . 175 ": " . $rply . $this->CRLF; 223 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 176 224 } 177 225 return false; 178 226 } … … 189 237 "smtp_code" => $code, 190 238 "smtp_msg" => substr($rply,4)); 191 239 if($this->do_debug >= 1) { 192 echo "SMTP -> ERROR: " . $this->error["error"] . 193 ": " . $rply . $this->CRLF; 240 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 194 241 } 195 242 return false; 196 243 } … … 207 254 "smtp_code" => $code, 208 255 "smtp_msg" => substr($rply,4)); 209 256 if($this->do_debug >= 1) { 210 echo "SMTP -> ERROR: " . $this->error["error"] . 211 ": " . $rply . $this->CRLF; 257 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 212 258 } 213 259 return false; 214 260 } … … 218 264 219 265 /** 220 266 * Returns true if connected to a server otherwise false 221 * @access p rivate267 * @access public 222 268 * @return bool 223 269 */ 224 function Connected() {270 public function Connected() { 225 271 if(!empty($this->smtp_conn)) { 226 272 $sock_status = socket_get_status($this->smtp_conn); 227 273 if($sock_status["eof"]) { 228 # hmm this is an odd situation... the socket is 229 # valid but we are not connected anymore 274 // the socket is valid but we are not connected 230 275 if($this->do_debug >= 1) { 231 echo "SMTP -> NOTICE:" . $this->CRLF . 232 "EOF caught while checking if connected"; 276 echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; 233 277 } 234 278 $this->Close(); 235 279 return false; 236 280 } 237 return true; #everything looks good281 return true; // everything looks good 238 282 } 239 283 return false; 240 284 } … … 246 290 * @access public 247 291 * @return void 248 292 */ 249 function Close() {250 $this->error = null; #so there is no confusion293 public function Close() { 294 $this->error = null; // so there is no confusion 251 295 $this->helo_rply = null; 252 296 if(!empty($this->smtp_conn)) { 253 #close the connection and cleanup297 // close the connection and cleanup 254 298 fclose($this->smtp_conn); 255 299 $this->smtp_conn = 0; 256 300 } 257 301 } 258 302 259 / ***************************************************************260 * SMTP COMMANDS *261 *************************************************************/303 ///////////////////////////////////////////////// 304 // SMTP COMMANDS 305 ///////////////////////////////////////////////// 262 306 263 307 /** 264 308 * Issues a data command and sends the msg_data to the server 265 309 * finializing the mail transaction. $msg_data is the message 266 310 * that is to be send with the headers. Each header needs to be 267 311 * on a single line followed by a <CRLF> with the message headers 268 * and the message body being sep arated by and additional <CRLF>.312 * and the message body being seperated by and additional <CRLF>. 269 313 * 270 314 * Implements rfc 821: DATA <CRLF> 271 315 * … … 279 323 * @access public 280 324 * @return bool 281 325 */ 282 function Data($msg_data) {283 $this->error = null; #so no confusion is caused326 public function Data($msg_data) { 327 $this->error = null; // so no confusion is caused 284 328 285 329 if(!$this->connected()) { 286 330 $this->error = array( … … 294 338 $code = substr($rply,0,3); 295 339 296 340 if($this->do_debug >= 2) { 297 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;341 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 298 342 } 299 343 300 344 if($code != 354) { … … 303 347 "smtp_code" => $code, 304 348 "smtp_msg" => substr($rply,4)); 305 349 if($this->do_debug >= 1) { 306 echo "SMTP -> ERROR: " . $this->error["error"] . 307 ": " . $rply . $this->CRLF; 350 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 308 351 } 309 352 return false; 310 353 } 311 354 312 # the server is ready to accept data! 313 # according to rfc 821 we should not send more than 1000 314 # including the CRLF 315 # characters on a single line so we will break the data up 316 # into lines by \r and/or \n then if needed we will break 317 # each of those into smaller lines to fit within the limit. 318 # in addition we will be looking for lines that start with 319 # a period '.' and append and additional period '.' to that 320 # line. NOTE: this does not count towards are limit. 355 /* the server is ready to accept data! 356 * according to rfc 821 we should not send more than 1000 357 * including the CRLF 358 * characters on a single line so we will break the data up 359 * into lines by \r and/or \n then if needed we will break 360 * each of those into smaller lines to fit within the limit. 361 * in addition we will be looking for lines that start with 362 * a period '.' and append and additional period '.' to that 363 * line. NOTE: this does not count towards limit. 364 */ 321 365 322 #normalize the line breaks so we know the explode works366 // normalize the line breaks so we know the explode works 323 367 $msg_data = str_replace("\r\n","\n",$msg_data); 324 368 $msg_data = str_replace("\r","\n",$msg_data); 325 369 $lines = explode("\n",$msg_data); 326 370 327 # we need to find a good way to determine is headers are 328 # in the msg_data or if it is a straight msg body 329 # currently I am assuming rfc 822 definitions of msg headers 330 # and if the first field of the first line (':' sperated) 331 # does not contain a space then it _should_ be a header 332 # and we can process all lines before a blank "" line as 333 # headers. 371 /* we need to find a good way to determine is headers are 372 * in the msg_data or if it is a straight msg body 373 * currently I am assuming rfc 822 definitions of msg headers 374 * and if the first field of the first line (':' sperated) 375 * does not contain a space then it _should_ be a header 376 * and we can process all lines before a blank "" line as 377 * headers. 378 */ 379 334 380 $field = substr($lines[0],0,strpos($lines[0],":")); 335 381 $in_headers = false; 336 382 if(!empty($field) && !strstr($field," ")) { 337 383 $in_headers = true; 338 384 } 339 385 340 $max_line_length = 998; #used below; set here for ease in change386 $max_line_length = 998; // used below; set here for ease in change 341 387 342 388 while(list(,$line) = @each($lines)) { 343 389 $lines_out = null; 344 390 if($line == "" && $in_headers) { 345 391 $in_headers = false; 346 392 } 347 # ok we need to break this line up into several 348 # smaller lines 393 // ok we need to break this line up into several smaller lines 349 394 while(strlen($line) > $max_line_length) { 350 395 $pos = strrpos(substr($line,0,$max_line_length)," "); 351 396 352 #Patch to fix DOS attack397 // Patch to fix DOS attack 353 398 if(!$pos) { 354 399 $pos = $max_line_length - 1; 400 $lines_out[] = substr($line,0,$pos); 401 $line = substr($line,$pos); 402 } else { 403 $lines_out[] = substr($line,0,$pos); 404 $line = substr($line,$pos + 1); 355 405 } 356 406 357 $lines_out[] = substr($line,0,$pos); 358 $line = substr($line,$pos + 1); 359 # if we are processing headers we need to 360 # add a LWSP-char to the front of the new line 361 # rfc 822 on long msg headers 407 /* if processing headers add a LWSP-char to the front of new line 408 * rfc 822 on long msg headers 409 */ 362 410 if($in_headers) { 363 411 $line = "\t" . $line; 364 412 } 365 413 } 366 414 $lines_out[] = $line; 367 415 368 # nowsend the lines to the server416 // send the lines to the server 369 417 while(list(,$line_out) = @each($lines_out)) { 370 418 if(strlen($line_out) > 0) 371 419 { … … 377 425 } 378 426 } 379 427 380 # ok all the message data has been sent so lets get this 381 # over with aleady 428 // message data has been sent 382 429 fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); 383 430 384 431 $rply = $this->get_lines(); 385 432 $code = substr($rply,0,3); 386 433 387 434 if($this->do_debug >= 2) { 388 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;435 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 389 436 } 390 437 391 438 if($code != 250) { … … 394 441 "smtp_code" => $code, 395 442 "smtp_msg" => substr($rply,4)); 396 443 if($this->do_debug >= 1) { 397 echo "SMTP -> ERROR: " . $this->error["error"] . 398 ": " . $rply . $this->CRLF; 444 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 399 445 } 400 446 return false; 401 447 } … … 403 449 } 404 450 405 451 /** 406 * Expand takes the name and asks the server to list all the407 * people who are members of the _list_. Expand will return408 * back and array of the result or false if an error occurs.409 * Each value in the array returned has the format of:410 * [ <full-name> <sp> ] <path>411 * The definition of <path> is defined in rfc 821412 *413 * Implements rfc 821: EXPN <SP> <string> <CRLF>414 *415 * SMTP CODE SUCCESS: 250416 * SMTP CODE FAILURE: 550417 * SMTP CODE ERROR : 500,501,502,504,421418 * @access public419 * @return string array420 */421 function Expand($name) {422 $this->error = null; # so no confusion is caused423 424 if(!$this->connected()) {425 $this->error = array(426 "error" => "Called Expand() without being connected");427 return false;428 }429 430 fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);431 432 $rply = $this->get_lines();433 $code = substr($rply,0,3);434 435 if($this->do_debug >= 2) {436 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;437 }438 439 if($code != 250) {440 $this->error =441 array("error" => "EXPN not accepted from server",442 "smtp_code" => $code,443 "smtp_msg" => substr($rply,4));444 if($this->do_debug >= 1) {445 echo "SMTP -> ERROR: " . $this->error["error"] .446 ": " . $rply . $this->CRLF;447 }448 return false;449 }450 451 # parse the reply and place in our array to return to user452 $entries = explode($this->CRLF,$rply);453 while(list(,$l) = @each($entries)) {454 $list[] = substr($l,4);455 }456 457 return $list;458 }459 460 /**461 452 * Sends the HELO command to the smtp server. 462 453 * This makes sure that we and the server are in 463 454 * the same known state. … … 469 460 * @access public 470 461 * @return bool 471 462 */ 472 function Hello($host="") {473 $this->error = null; #so no confusion is caused463 public function Hello($host = '') { 464 $this->error = null; // so no confusion is caused 474 465 475 466 if(!$this->connected()) { 476 467 $this->error = array( … … 478 469 return false; 479 470 } 480 471 481 # if a hostname for the HELO was not specified determine 482 # a suitable one to send 472 // if hostname for HELO was not specified send default 483 473 if(empty($host)) { 484 # we need to determine some sort of appopiate default 485 # to send to the server 474 // determine appropriate default to send to server 486 475 $host = "localhost"; 487 476 } 488 477 489 478 // Send extended hello first (RFC 2821) 490 if(!$this->SendHello("EHLO", $host)) 491 {492 if(!$this->SendHello("HELO", $host))493 return false;479 if(!$this->SendHello("EHLO", $host)) { 480 if(!$this->SendHello("HELO", $host)) { 481 return false; 482 } 494 483 } 495 484 496 485 return true; … … 501 490 * @access private 502 491 * @return bool 503 492 */ 504 function SendHello($hello, $host) {493 private function SendHello($hello, $host) { 505 494 fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); 506 495 507 496 $rply = $this->get_lines(); 508 497 $code = substr($rply,0,3); 509 498 510 499 if($this->do_debug >= 2) { 511 echo "SMTP -> FROM SERVER: " . $ this->CRLF . $rply;500 echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />'; 512 501 } 513 502 514 503 if($code != 250) { … … 517 506 "smtp_code" => $code, 518 507 "smtp_msg" => substr($rply,4)); 519 508 if($this->do_debug >= 1) { 520 echo "SMTP -> ERROR: " . $this->error["error"] . 521 ": " . $rply . $this->CRLF; 509 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 522 510 } 523 511 return false; 524 512 } … … 529 517 } 530 518 531 519 /** 532 * Gets help information on the keyword specified. If the keyword533 * is not specified then returns generic help, ussually contianing534 * A list of keywords that help is available on. This function535 * returns the results back to the user. It is up to the user to536 * handle the returned data. If an error occurs then false is537 * returned with $this->error set appropiately.538 *539 * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>540 *541 * SMTP CODE SUCCESS: 211,214542 * SMTP CODE ERROR : 500,501,502,504,421543 * @access public544 * @return string545 */546 function Help($keyword="") {547 $this->error = null; # to avoid confusion548 549 if(!$this->connected()) {550 $this->error = array(551 "error" => "Called Help() without being connected");552 return false;553 }554 555 $extra = "";556 if(!empty($keyword)) {557 $extra = " " . $keyword;558 }559 560 fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);561 562 $rply = $this->get_lines();563 $code = substr($rply,0,3);564 565 if($this->do_debug >= 2) {566 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;567 }568 569 if($code != 211 && $code != 214) {570 $this->error =571 array("error" => "HELP not accepted from server",572 "smtp_code" => $code,573 "smtp_msg" => substr($rply,4));574 if($this->do_debug >= 1) {575 echo "SMTP -> ERROR: " . $this->error["error"] .576 ": " . $rply . $this->CRLF;577 }578 return false;579 }580 581 return $rply;582 }583 584 /**585 520 * Starts a mail transaction from the email address specified in 586 521 * $from. Returns true if successful or false otherwise. If True 587 522 * the mail transaction is started and then one or more Recipient … … 595 530 * @access public 596 531 * @return bool 597 532 */ 598 function Mail($from) {599 $this->error = null; #so no confusion is caused533 public function Mail($from) { 534 $this->error = null; // so no confusion is caused 600 535 601 536 if(!$this->connected()) { 602 537 $this->error = array( … … 611 546 $code = substr($rply,0,3); 612 547 613 548 if($this->do_debug >= 2) { 614 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;549 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 615 550 } 616 551 617 552 if($code != 250) { … … 620 555 "smtp_code" => $code, 621 556 "smtp_msg" => substr($rply,4)); 622 557 if($this->do_debug >= 1) { 623 echo "SMTP -> ERROR: " . $this->error["error"] . 624 ": " . $rply . $this->CRLF; 558 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 625 559 } 626 560 return false; 627 561 } … … 629 563 } 630 564 631 565 /** 632 * Sends the command NOOP to the SMTP server.633 *634 * Implements from rfc 821: NOOP <CRLF>635 *636 * SMTP CODE SUCCESS: 250637 * SMTP CODE ERROR : 500, 421638 * @access public639 * @return bool640 */641 function Noop() {642 $this->error = null; # so no confusion is caused643 644 if(!$this->connected()) {645 $this->error = array(646 "error" => "Called Noop() without being connected");647 return false;648 }649 650 fputs($this->smtp_conn,"NOOP" . $this->CRLF);651 652 $rply = $this->get_lines();653 $code = substr($rply,0,3);654 655 if($this->do_debug >= 2) {656 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;657 }658 659 if($code != 250) {660 $this->error =661 array("error" => "NOOP not accepted from server",662 "smtp_code" => $code,663 "smtp_msg" => substr($rply,4));664 if($this->do_debug >= 1) {665 echo "SMTP -> ERROR: " . $this->error["error"] .666 ": " . $rply . $this->CRLF;667 }668 return false;669 }670 return true;671 }672 673 /**674 566 * Sends the quit command to the server and then closes the socket 675 567 * if there is no error or the $close_on_error argument is true. 676 568 * … … 681 573 * @access public 682 574 * @return bool 683 575 */ 684 function Quit($close_on_error=true) {685 $this->error = null; #so there is no confusion576 public function Quit($close_on_error = true) { 577 $this->error = null; // so there is no confusion 686 578 687 579 if(!$this->connected()) { 688 580 $this->error = array( … … 690 582 return false; 691 583 } 692 584 693 #send the quit command to the server585 // send the quit command to the server 694 586 fputs($this->smtp_conn,"quit" . $this->CRLF); 695 587 696 #get any good-bye messages588 // get any good-bye messages 697 589 $byemsg = $this->get_lines(); 698 590 699 591 if($this->do_debug >= 2) { 700 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $byemsg;592 echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />'; 701 593 } 702 594 703 595 $rval = true; … … 705 597 706 598 $code = substr($byemsg,0,3); 707 599 if($code != 221) { 708 #use e as a tmp var cause Close will overwrite $this->error600 // use e as a tmp var cause Close will overwrite $this->error 709 601 $e = array("error" => "SMTP server rejected quit command", 710 602 "smtp_code" => $code, 711 603 "smtp_rply" => substr($byemsg,4)); 712 604 $rval = false; 713 605 if($this->do_debug >= 1) { 714 echo "SMTP -> ERROR: " . $e["error"] . ": " . 715 $byemsg . $this->CRLF; 606 echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />'; 716 607 } 717 608 } 718 609 … … 735 626 * @access public 736 627 * @return bool 737 628 */ 738 function Recipient($to) {739 $this->error = null; #so no confusion is caused629 public function Recipient($to) { 630 $this->error = null; // so no confusion is caused 740 631 741 632 if(!$this->connected()) { 742 633 $this->error = array( … … 750 641 $code = substr($rply,0,3); 751 642 752 643 if($this->do_debug >= 2) { 753 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;644 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 754 645 } 755 646 756 647 if($code != 250 && $code != 251) { … … 759 650 "smtp_code" => $code, 760 651 "smtp_msg" => substr($rply,4)); 761 652 if($this->do_debug >= 1) { 762 echo "SMTP -> ERROR: " . $this->error["error"] . 763 ": " . $rply . $this->CRLF; 653 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 764 654 } 765 655 return false; 766 656 } … … 779 669 * @access public 780 670 * @return bool 781 671 */ 782 function Reset() {783 $this->error = null; #so no confusion is caused672 public function Reset() { 673 $this->error = null; // so no confusion is caused 784 674 785 675 if(!$this->connected()) { 786 676 $this->error = array( … … 794 684 $code = substr($rply,0,3); 795 685 796 686 if($this->do_debug >= 2) { 797 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;687 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 798 688 } 799 689 800 690 if($code != 250) { … … 803 693 "smtp_code" => $code, 804 694 "smtp_msg" => substr($rply,4)); 805 695 if($this->do_debug >= 1) { 806 echo "SMTP -> ERROR: " . $this->error["error"] . 807 ": " . $rply . $this->CRLF; 696 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 808 697 } 809 698 return false; 810 699 } … … 818 707 * the mail transaction is started and then one or more Recipient 819 708 * commands may be called followed by a Data command. This command 820 709 * will send the message to the users terminal if they are logged 821 * in.822 *823 * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>824 *825 * SMTP CODE SUCCESS: 250826 * SMTP CODE SUCCESS: 552,451,452827 * SMTP CODE SUCCESS: 500,501,502,421828 * @access public829 * @return bool830 */831 function Send($from) {832 $this->error = null; # so no confusion is caused833 834 if(!$this->connected()) {835 $this->error = array(836 "error" => "Called Send() without being connected");837 return false;838 }839 840 fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);841 842 $rply = $this->get_lines();843 $code = substr($rply,0,3);844 845 if($this->do_debug >= 2) {846 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;847 }848 849 if($code != 250) {850 $this->error =851 array("error" => "SEND not accepted from server",852 "smtp_code" => $code,853 "smtp_msg" => substr($rply,4));854 if($this->do_debug >= 1) {855 echo "SMTP -> ERROR: " . $this->error["error"] .856 ": " . $rply . $this->CRLF;857 }858 return false;859 }860 return true;861 }862 863 /**864 * Starts a mail transaction from the email address specified in865 * $from. Returns true if successful or false otherwise. If True866 * the mail transaction is started and then one or more Recipient867 * commands may be called followed by a Data command. This command868 * will send the message to the users terminal if they are logged869 710 * in and send them an email. 870 711 * 871 712 * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> … … 876 717 * @access public 877 718 * @return bool 878 719 */ 879 function SendAndMail($from) {880 $this->error = null; #so no confusion is caused720 public function SendAndMail($from) { 721 $this->error = null; // so no confusion is caused 881 722 882 723 if(!$this->connected()) { 883 724 $this->error = array( … … 891 732 $code = substr($rply,0,3); 892 733 893 734 if($this->do_debug >= 2) { 894 echo "SMTP -> FROM SERVER:" . $ this->CRLF . $rply;735 echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 895 736 } 896 737 897 738 if($code != 250) { … … 900 741 "smtp_code" => $code, 901 742 "smtp_msg" => substr($rply,4)); 902 743 if($this->do_debug >= 1) { 903 echo "SMTP -> ERROR: " . $this->error["error"] . 904 ": " . $rply . $this->CRLF; 744 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 905 745 } 906 746 return false; 907 747 } … … 909 749 } 910 750 911 751 /** 912 * Starts a mail transaction from the email address specified in913 * $from. Returns true if successful or false otherwise. If True914 * the mail transaction is started and then one or more Recipient915 * commands may be called followed by a Data command. This command916 * will send the message to the users terminal if they are logged917 * in or mail it to them if they are not.918 *919 * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>920 *921 * SMTP CODE SUCCESS: 250922 * SMTP CODE SUCCESS: 552,451,452923 * SMTP CODE SUCCESS: 500,501,502,421924 * @access public925 * @return bool926 */927 function SendOrMail($from) {928 $this->error = null; # so no confusion is caused929 930 if(!$this->connected()) {931 $this->error = array(932 "error" => "Called SendOrMail() without being connected");933 return false;934 }935 936 fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);937 938 $rply = $this->get_lines();939 $code = substr($rply,0,3);940 941 if($this->do_debug >= 2) {942 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;943 }944 945 if($code != 250) {946 $this->error =947 array("error" => "SOML not accepted from server",948 "smtp_code" => $code,949 "smtp_msg" => substr($rply,4));950 if($this->do_debug >= 1) {951 echo "SMTP -> ERROR: " . $this->error["error"] .952 ": " . $rply . $this->CRLF;953 }954 return false;955 }956 return true;957 }958 959 /**960 752 * This is an optional command for SMTP that this class does not 961 753 * support. This method is here to make the RFC821 Definition 962 754 * complete for this class and __may__ be implimented in the future … … 969 761 * @access public 970 762 * @return bool 971 763 */ 972 function Turn() {764 public function Turn() { 973 765 $this->error = array("error" => "This method, TURN, of the SMTP ". 974 766 "is not implemented"); 975 767 if($this->do_debug >= 1) { 976 echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF ;768 echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />'; 977 769 } 978 770 return false; 979 771 } 980 772 981 773 /** 982 * Verifies that the name is recognized by the server. 983 * Returns false if the name could not be verified otherwise 984 * the response from the server is returned. 985 * 986 * Implements rfc 821: VRFY <SP> <string> <CRLF> 987 * 988 * SMTP CODE SUCCESS: 250,251 989 * SMTP CODE FAILURE: 550,551,553 990 * SMTP CODE ERROR : 500,501,502,421 991 * @access public 992 * @return int 993 */ 994 function Verify($name) { 995 $this->error = null; # so no confusion is caused 996 997 if(!$this->connected()) { 998 $this->error = array( 999 "error" => "Called Verify() without being connected"); 1000 return false; 1001 } 1002 1003 fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF); 1004 1005 $rply = $this->get_lines(); 1006 $code = substr($rply,0,3); 1007 1008 if($this->do_debug >= 2) { 1009 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; 1010 } 1011 1012 if($code != 250 && $code != 251) { 1013 $this->error = 1014 array("error" => "VRFY failed on name '$name'", 1015 "smtp_code" => $code, 1016 "smtp_msg" => substr($rply,4)); 1017 if($this->do_debug >= 1) { 1018 echo "SMTP -> ERROR: " . $this->error["error"] . 1019 ": " . $rply . $this->CRLF; 1020 } 1021 return false; 1022 } 1023 return $rply; 774 * Get the current error 775 * @access public 776 * @return array 777 */ 778 public function getError() { 779 return $this->error; 1024 780 } 1025 781 1026 / *******************************************************************1027 * INTERNAL FUNCTIONS *1028 ******************************************************************/782 ///////////////////////////////////////////////// 783 // INTERNAL FUNCTIONS 784 ///////////////////////////////////////////////// 1029 785 1030 786 /** 1031 787 * Read in as many lines as possible … … 1036 792 * @access private 1037 793 * @return string 1038 794 */ 1039 function get_lines() {795 private function get_lines() { 1040 796 $data = ""; 1041 797 while($str = @fgets($this->smtp_conn,515)) { 1042 798 if($this->do_debug >= 4) { 1043 echo "SMTP -> get_lines(): \$data was \"$data\"" . 1044 $this->CRLF; 1045 echo "SMTP -> get_lines(): \$str is \"$str\"" . 1046 $this->CRLF; 799 echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />'; 800 echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />'; 1047 801 } 1048 802 $data .= $str; 1049 803 if($this->do_debug >= 4) { 1050 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF ;804 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />'; 1051 805 } 1052 # if the 4th character is a space then we are done reading 1053 # so just break the loop 806 // if 4th character is a space, we are done reading, break the loop 1054 807 if(substr($str,3,1) == " ") { break; } 1055 808 } 1056 809 return $data; … … 1058 811 1059 812 } 1060 813 1061 1062 ?>814 ?> 815 No newline at end of file
