| [ Index ] |
PHP Cross Reference of Wordpress MU 2.7 |
[Summary view] [Print] [Text view]
1 <?php 2 /*~ class.phpmailer.php 3 .---------------------------------------------------------------------------. 4 | Software: PHPMailer - PHP email class | 5 | Version: 2.0.2 | 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 | Author: Andy Prevost (project admininistrator) | 11 | Author: Brent R. Matzelle (original founder) | 12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. | 13 | Copyright (c) 2001-2003, Brent R. Matzelle | 14 | ------------------------------------------------------------------------- | 15 | License: Distributed under the Lesser General Public License (LGPL) | 16 | http://www.gnu.org/copyleft/lesser.html | 17 | This program is distributed in the hope that it will be useful - WITHOUT | 18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 19 | FITNESS FOR A PARTICULAR PURPOSE. | 20 | ------------------------------------------------------------------------- | 21 | We offer a number of paid services (www.codeworxtech.com): | 22 | - Web Hosting on highly optimized fast and secure servers | 23 | - Technology Consulting | 24 | - Oursourcing (highly qualified programmers and graphic designers) | 25 '---------------------------------------------------------------------------' 26 */ 27 /** 28 * PHPMailer - PHP email transport class 29 * @package PHPMailer 30 * @author Andy Prevost 31 * @copyright 2004 - 2008 Andy Prevost 32 */ 33 34 class PHPMailer { 35 36 ///////////////////////////////////////////////// 37 // PROPERTIES, PUBLIC 38 ///////////////////////////////////////////////// 39 40 /** 41 * Email priority (1 = High, 3 = Normal, 5 = low). 42 * @var int 43 */ 44 var $Priority = 3; 45 46 /** 47 * Sets the CharSet of the message. 48 * @var string 49 */ 50 var $CharSet = 'iso-8859-1'; 51 52 /** 53 * Sets the Content-type of the message. 54 * @var string 55 */ 56 var $ContentType = 'text/plain'; 57 58 /** 59 * Sets the Encoding of the message. Options for this are "8bit", 60 * "7bit", "binary", "base64", and "quoted-printable". 61 * @var string 62 */ 63 var $Encoding = '8bit'; 64 65 /** 66 * Holds the most recent mailer error message. 67 * @var string 68 */ 69 var $ErrorInfo = ''; 70 71 /** 72 * Sets the From email address for the message. 73 * @var string 74 */ 75 var $From = 'root@localhost'; 76 77 /** 78 * Sets the From name of the message. 79 * @var string 80 */ 81 var $FromName = 'Root User'; 82 83 /** 84 * Sets the Sender email (Return-Path) of the message. If not empty, 85 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. 86 * @var string 87 */ 88 var $Sender = ''; 89 90 /** 91 * Sets the Subject of the message. 92 * @var string 93 */ 94 var $Subject = ''; 95 96 /** 97 * Sets the Body of the message. This can be either an HTML or text body. 98 * If HTML then run IsHTML(true). 99 * @var string 100 */ 101 var $Body = ''; 102 103 /** 104 * Sets the text-only body of the message. This automatically sets the 105 * email to multipart/alternative. This body can be read by mail 106 * clients that do not have HTML email capability such as mutt. Clients 107 * that can read HTML will view the normal Body. 108 * @var string 109 */ 110 var $AltBody = ''; 111 112 /** 113 * Sets word wrapping on the body of the message to a given number of 114 * characters. 115 * @var int 116 */ 117 var $WordWrap = 0; 118 119 /** 120 * Method to send mail: ("mail", "sendmail", or "smtp"). 121 * @var string 122 */ 123 var $Mailer = 'mail'; 124 125 /** 126 * Sets the path of the sendmail program. 127 * @var string 128 */ 129 var $Sendmail = '/usr/sbin/sendmail'; 130 131 /** 132 * Path to PHPMailer plugins. This is now only useful if the SMTP class 133 * is in a different directory than the PHP include path. 134 * @var string 135 */ 136 var $PluginDir = ''; 137 138 /** 139 * Holds PHPMailer version. 140 * @var string 141 */ 142 var $Version = "2.0.2"; 143 144 /** 145 * Sets the email address that a reading confirmation will be sent. 146 * @var string 147 */ 148 var $ConfirmReadingTo = ''; 149 150 /** 151 * Sets the hostname to use in Message-Id and Received headers 152 * and as default HELO string. If empty, the value returned 153 * by SERVER_NAME is used or 'localhost.localdomain'. 154 * @var string 155 */ 156 var $Hostname = ''; 157 158 /** 159 * Sets the message ID to be used in the Message-Id header. 160 * If empty, a unique id will be generated. 161 * @var string 162 */ 163 var $MessageID = ''; 164 165 ///////////////////////////////////////////////// 166 // PROPERTIES FOR SMTP 167 ///////////////////////////////////////////////// 168 169 /** 170 * Sets the SMTP hosts. All hosts must be separated by a 171 * semicolon. You can also specify a different port 172 * for each host by using this format: [hostname:port] 173 * (e.g. "smtp1.example.com:25;smtp2.example.com"). 174 * Hosts will be tried in order. 175 * @var string 176 */ 177 var $Host = 'localhost'; 178 179 /** 180 * Sets the default SMTP server port. 181 * @var int 182 */ 183 var $Port = 25; 184 185 /** 186 * Sets the SMTP HELO of the message (Default is $Hostname). 187 * @var string 188 */ 189 var $Helo = ''; 190 191 /** 192 * Sets connection prefix. 193 * Options are "", "ssl" or "tls" 194 * @var string 195 */ 196 var $SMTPSecure = ""; 197 198 /** 199 * Sets SMTP authentication. Utilizes the Username and Password variables. 200 * @var bool 201 */ 202 var $SMTPAuth = false; 203 204 /** 205 * Sets SMTP username. 206 * @var string 207 */ 208 var $Username = ''; 209 210 /** 211 * Sets SMTP password. 212 * @var string 213 */ 214 var $Password = ''; 215 216 /** 217 * Sets the SMTP server timeout in seconds. This function will not 218 * work with the win32 version. 219 * @var int 220 */ 221 var $Timeout = 10; 222 223 /** 224 * Sets SMTP class debugging on or off. 225 * @var bool 226 */ 227 var $SMTPDebug = false; 228 229 /** 230 * Prevents the SMTP connection from being closed after each mail 231 * sending. If this is set to true then to close the connection 232 * requires an explicit call to SmtpClose(). 233 * @var bool 234 */ 235 var $SMTPKeepAlive = false; 236 237 /** 238 * Provides the ability to have the TO field process individual 239 * emails, instead of sending to entire TO addresses 240 * @var bool 241 */ 242 var $SingleTo = false; 243 244 ///////////////////////////////////////////////// 245 // PROPERTIES, PRIVATE 246 ///////////////////////////////////////////////// 247 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_key_file = ""; 261 var $sign_key_pass = ""; 262 263 ///////////////////////////////////////////////// 264 // METHODS, VARIABLES 265 ///////////////////////////////////////////////// 266 267 /** 268 * Sets message type to HTML. 269 * @param bool $bool 270 * @return void 271 */ 272 function IsHTML($bool) { 273 if($bool == true) { 274 $this->ContentType = 'text/html'; 275 } else { 276 $this->ContentType = 'text/plain'; 277 } 278 } 279 280 /** 281 * Sets Mailer to send message using SMTP. 282 * @return void 283 */ 284 function IsSMTP() { 285 $this->Mailer = 'smtp'; 286 } 287 288 /** 289 * Sets Mailer to send message using PHP mail() function. 290 * @return void 291 */ 292 function IsMail() { 293 $this->Mailer = 'mail'; 294 } 295 296 /** 297 * Sets Mailer to send message using the $Sendmail program. 298 * @return void 299 */ 300 function IsSendmail() { 301 $this->Mailer = 'sendmail'; 302 } 303 304 /** 305 * Sets Mailer to send message using the qmail MTA. 306 * @return void 307 */ 308 function IsQmail() { 309 $this->Sendmail = '/var/qmail/bin/sendmail'; 310 $this->Mailer = 'sendmail'; 311 } 312 313 ///////////////////////////////////////////////// 314 // METHODS, RECIPIENTS 315 ///////////////////////////////////////////////// 316 317 /** 318 * Adds a "To" address. 319 * @param string $address 320 * @param string $name 321 * @return void 322 */ 323 function AddAddress($address, $name = '') { 324 $cur = count($this->to); 325 $this->to[$cur][0] = trim($address); 326 $this->to[$cur][1] = $name; 327 } 328 329 /** 330 * Adds a "Cc" address. Note: this function works 331 * with the SMTP mailer on win32, not with the "mail" 332 * mailer. 333 * @param string $address 334 * @param string $name 335 * @return void 336 */ 337 function AddCC($address, $name = '') { 338 $cur = count($this->cc); 339 $this->cc[$cur][0] = trim($address); 340 $this->cc[$cur][1] = $name; 341 } 342 343 /** 344 * Adds a "Bcc" address. Note: this function works 345 * with the SMTP mailer on win32, not with the "mail" 346 * mailer. 347 * @param string $address 348 * @param string $name 349 * @return void 350 */ 351 function AddBCC($address, $name = '') { 352 $cur = count($this->bcc); 353 $this->bcc[$cur][0] = trim($address); 354 $this->bcc[$cur][1] = $name; 355 } 356 357 /** 358 * Adds a "Reply-To" address. 359 * @param string $address 360 * @param string $name 361 * @return void 362 */ 363 function AddReplyTo($address, $name = '') { 364 $cur = count($this->ReplyTo); 365 $this->ReplyTo[$cur][0] = trim($address); 366 $this->ReplyTo[$cur][1] = $name; 367 } 368 369 ///////////////////////////////////////////////// 370 // METHODS, MAIL SENDING 371 ///////////////////////////////////////////////// 372 373 /** 374 * Creates message and assigns Mailer. If the message is 375 * not sent successfully then it returns false. Use the ErrorInfo 376 * variable to view description of the error. 377 * @return bool 378 */ 379 function Send() { 380 $header = ''; 381 $body = ''; 382 $result = true; 383 384 if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { 385 $this->SetError($this->Lang('provide_address')); 386 return false; 387 } 388 389 /* Set whether the message is multipart/alternative */ 390 if(!empty($this->AltBody)) { 391 $this->ContentType = 'multipart/alternative'; 392 } 393 394 $this->error_count = 0; // reset errors 395 $this->SetMessageType(); 396 $header .= $this->CreateHeader(); 397 $body = $this->CreateBody(); 398 399 if($body == '') { 400 return false; 401 } 402 403 /* Choose the mailer */ 404 switch($this->Mailer) { 405 case 'sendmail': 406 $result = $this->SendmailSend($header, $body); 407 break; 408 case 'smtp': 409 $result = $this->SmtpSend($header, $body); 410 break; 411 case 'mail': 412 $result = $this->MailSend($header, $body); 413 break; 414 default: 415 $result = $this->MailSend($header, $body); 416 break; 417 //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported')); 418 //$result = false; 419 //break; 420 } 421 422 return $result; 423 } 424 425 /** 426 * Sends mail using the $Sendmail program. 427 * @access private 428 * @return bool 429 */ 430 function SendmailSend($header, $body) { 431 if ($this->Sender != '') { 432 $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); 433 } else { 434 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); 435 } 436 437 if(!@$mail = popen($sendmail, 'w')) { 438 $this->SetError($this->Lang('execute') . $this->Sendmail); 439 return false; 440 } 441 442 fputs($mail, $header); 443 fputs($mail, $body); 444 445 $result = pclose($mail); 446 if (version_compare(phpversion(), '4.2.3') == -1) { 447 $result = $result >> 8 & 0xFF; 448 } 449 if($result != 0) { 450 $this->SetError($this->Lang('execute') . $this->Sendmail); 451 return false; 452 } 453 return true; 454 } 455 456 /** 457 * Sends mail using the PHP mail() function. 458 * @access private 459 * @return bool 460 */ 461 function MailSend($header, $body) { 462 463 $to = ''; 464 for($i = 0; $i < count($this->to); $i++) { 465 if($i != 0) { $to .= ', '; } 466 $to .= $this->AddrFormat($this->to[$i]); 467 } 468 469 $toArr = split(',', $to); 470 471 $params = sprintf("-oi -f %s", $this->Sender); 472 if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) { 473 $old_from = ini_get('sendmail_from'); 474 ini_set('sendmail_from', $this->Sender); 475 if ($this->SingleTo === true && count($toArr) > 1) { 476 foreach ($toArr as $key => $val) { 477 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 478 } 479 } else { 480 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 481 } 482 } else { 483 if ($this->SingleTo === true && count($toArr) > 1) { 484 foreach ($toArr as $key => $val) { 485 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); 486 } 487 } else { 488 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); 489 } 490 } 491 492 if (isset($old_from)) { 493 ini_set('sendmail_from', $old_from); 494 } 495 496 if(!$rt) { 497 $this->SetError($this->Lang('instantiate')); 498 return false; 499 } 500 501 return true; 502 } 503 504 /** 505 * Sends mail via SMTP using PhpSMTP (Author: 506 * Chris Ryan). Returns bool. Returns false if there is a 507 * bad MAIL FROM, RCPT, or DATA input. 508 * @access private 509 * @return bool 510 */ 511 function SmtpSend($header, $body) { 512 include_once($this->PluginDir . 'class-smtp.php'); 513 $error = ''; 514 $bad_rcpt = array(); 515 516 if(!$this->SmtpConnect()) { 517 return false; 518 } 519 520 $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; 521 if(!$this->smtp->Mail($smtp_from)) { 522 $error = $this->Lang('from_failed') . $smtp_from; 523 $this->SetError($error); 524 $this->smtp->Reset(); 525 return false; 526 } 527 528 /* Attempt to send attach all recipients */ 529 for($i = 0; $i < count($this->to); $i++) { 530 if(!$this->smtp->Recipient($this->to[$i][0])) { 531 $bad_rcpt[] = $this->to[$i][0]; 532 } 533 } 534 for($i = 0; $i < count($this->cc); $i++) { 535 if(!$this->smtp->Recipient($this->cc[$i][0])) { 536 $bad_rcpt[] = $this->cc[$i][0]; 537 } 538 } 539 for($i = 0; $i < count($this->bcc); $i++) { 540 if(!$this->smtp->Recipient($this->bcc[$i][0])) { 541 $bad_rcpt[] = $this->bcc[$i][0]; 542 } 543 } 544 545 if(count($bad_rcpt) > 0) { // Create error message 546 for($i = 0; $i < count($bad_rcpt); $i++) { 547 if($i != 0) { 548 $error .= ', '; 549 } 550 $error .= $bad_rcpt[$i]; 551 } 552 $error = $this->Lang('recipients_failed') . $error; 553 $this->SetError($error); 554 $this->smtp->Reset(); 555 return false; 556 } 557 558 if(!$this->smtp->Data($header . $body)) { 559 $this->SetError($this->Lang('data_not_accepted')); 560 $this->smtp->Reset(); 561 return false; 562 } 563 if($this->SMTPKeepAlive == true) { 564 $this->smtp->Reset(); 565 } else { 566 $this->SmtpClose(); 567 } 568 569 return true; 570 } 571 572 /** 573 * Initiates a connection to an SMTP server. Returns false if the 574 * operation failed. 575 * @access private 576 * @return bool 577 */ 578 function SmtpConnect() { 579 if($this->smtp == NULL) { 580 $this->smtp = new SMTP(); 581 } 582 583 $this->smtp->do_debug = $this->SMTPDebug; 584 $hosts = explode(';', $this->Host); 585 $index = 0; 586 $connection = ($this->smtp->Connected()); 587 588 /* Retry while there is no connection */ 589 while($index < count($hosts) && $connection == false) { 590 $hostinfo = array(); 591 if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) { 592 $host = $hostinfo[1]; 593 $port = $hostinfo[2]; 594 } else { 595 $host = $hosts[$index]; 596 $port = $this->Port; 597 } 598 599 if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) { 600 if ($this->Helo != '') { 601 $this->smtp->Hello($this->Helo); 602 } else { 603 $this->smtp->Hello($this->ServerHostname()); 604 } 605 606 $connection = true; 607 if($this->SMTPAuth) { 608 if(!$this->smtp->Authenticate($this->Username, $this->Password)) { 609 $this->SetError($this->Lang('authenticate')); 610 $this->smtp->Reset(); 611 $connection = false; 612 } 613 } 614 } 615 $index++; 616 } 617 if(!$connection) { 618 $this->SetError($this->Lang('connect_host')); 619 } 620 621 return $connection; 622 } 623 624 /** 625 * Closes the active SMTP session if one exists. 626 * @return void 627 */ 628 function SmtpClose() { 629 if($this->smtp != NULL) { 630 if($this->smtp->Connected()) { 631 $this->smtp->Quit(); 632 $this->smtp->Close(); 633 } 634 } 635 } 636 637 /** 638 * Sets the language for all class error messages. Returns false 639 * if it cannot load the language file. The default language type 640 * is English. 641 * @param string $lang_type Type of language (e.g. Portuguese: "br") 642 * @param string $lang_path Path to the language file directory 643 * @access public 644 * @return bool 645 */ 646 function SetLanguage($lang_type, $lang_path = 'language/') { 647 if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) { 648 include($lang_path.'phpmailer.lang-'.$lang_type.'.php'); 649 } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) { 650 include($lang_path.'phpmailer.lang-en.php'); 651 } else { 652 $this->SetError('Could not load language file'); 653 return false; 654 } 655 $this->language = $PHPMAILER_LANG; 656 657 return true; 658 } 659 660 ///////////////////////////////////////////////// 661 // METHODS, MESSAGE CREATION 662 ///////////////////////////////////////////////// 663 664 /** 665 * Creates recipient headers. 666 * @access private 667 * @return string 668 */ 669 function AddrAppend($type, $addr) { 670 $addr_str = $type . ': '; 671 $addr_str .= $this->AddrFormat($addr[0]); 672 if(count($addr) > 1) { 673 for($i = 1; $i < count($addr); $i++) { 674 $addr_str .= ', ' . $this->AddrFormat($addr[$i]); 675 } 676 } 677 $addr_str .= $this->LE; 678 679 return $addr_str; 680 } 681 682 /** 683 * Formats an address correctly. 684 * @access private 685 * @return string 686 */ 687 function AddrFormat($addr) { 688 if(empty($addr[1])) { 689 $formatted = $this->SecureHeader($addr[0]); 690 } else { 691 $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; 692 } 693 694 return $formatted; 695 } 696 697 /** 698 * Wraps message for use with mailers that do not 699 * automatically perform wrapping and for quoted-printable. 700 * Original written by philippe. 701 * @access private 702 * @return string 703 */ 704 function WrapText($message, $length, $qp_mode = false) { 705 $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; 706 // If utf-8 encoding is used, we will need to make sure we don't 707 // split multibyte characters when we wrap 708 $is_utf8 = (strtolower($this->CharSet) == "utf-8"); 709 710 $message = $this->FixEOL($message); 711 if (substr($message, -1) == $this->LE) { 712 $message = substr($message, 0, -1); 713 } 714 715 $line = explode($this->LE, $message); 716 $message = ''; 717 for ($i=0 ;$i < count($line); $i++) { 718 $line_part = explode(' ', $line[$i]); 719 $buf = ''; 720 for ($e = 0; $e<count($line_part); $e++) { 721 $word = $line_part[$e]; 722 if ($qp_mode and (strlen($word) > $length)) { 723 $space_left = $length - strlen($buf) - 1; 724 if ($e != 0) { 725 if ($space_left > 20) { 726 $len = $space_left; 727 if ($is_utf8) { 728 $len = $this->UTF8CharBoundary($word, $len); 729 } elseif (substr($word, $len - 1, 1) == "=") { 730 $len--; 731 } elseif (substr($word, $len - 2, 1) == "=") { 732 $len -= 2; 733 } 734 $part = substr($word, 0, $len); 735 $word = substr($word, $len); 736 $buf .= ' ' . $part; 737 $message .= $buf . sprintf("=%s", $this->LE); 738 } else { 739 $message .= $buf . $soft_break; 740 } 741 $buf = ''; 742 } 743 while (strlen($word) > 0) { 744 $len = $length; 745 if ($is_utf8) { 746 $len = $this->UTF8CharBoundary($word, $len); 747 } elseif (substr($word, $len - 1, 1) == "=") { 748 $len--; 749 } elseif (substr($word, $len - 2, 1) == "=") { 750 $len -= 2; 751 } 752 $part = substr($word, 0, $len); 753 $word = substr($word, $len); 754 755 if (strlen($word) > 0) { 756 $message .= $part . sprintf("=%s", $this->LE); 757 } else { 758 $buf = $part; 759 } 760 } 761 } else { 762 $buf_o = $buf; 763 $buf .= ($e == 0) ? $word : (' ' . $word); 764 765 if (strlen($buf) > $length and $buf_o != '') { 766 $message .= $buf_o . $soft_break; 767 $buf = $word; 768 } 769 } 770 } 771 $message .= $buf . $this->LE; 772 } 773 774 return $message; 775 } 776 777 /** 778 * Finds last character boundary prior to maxLength in a utf-8 779 * quoted (printable) encoded string. 780 * Original written by Colin Brown. 781 * @access private 782 * @param string $encodedText utf-8 QP text 783 * @param int $maxLength find last character boundary prior to this length 784 * @return int 785 */ 786 function UTF8CharBoundary($encodedText, $maxLength) { 787 $foundSplitPos = false; 788 $lookBack = 3; 789 while (!$foundSplitPos) { 790 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); 791 $encodedCharPos = strpos($lastChunk, "="); 792 if ($encodedCharPos !== false) { 793 // Found start of encoded character byte within $lookBack block. 794 // Check the encoded byte value (the 2 chars after the '=') 795 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); 796 $dec = hexdec($hex); 797 if ($dec < 128) { // Single byte character. 798 // If the encoded char was found at pos 0, it will fit 799 // otherwise reduce maxLength to start of the encoded char 800 $maxLength = ($encodedCharPos == 0) ? $maxLength : 801 $maxLength - ($lookBack - $encodedCharPos); 802 $foundSplitPos = true; 803 } elseif ($dec >= 192) { // First byte of a multi byte character 804 // Reduce maxLength to split at start of character 805 $maxLength = $maxLength - ($lookBack - $encodedCharPos); 806 $foundSplitPos = true; 807 } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back 808 $lookBack += 3; 809 } 810 } else { 811 // No encoded character found 812 $foundSplitPos = true; 813 } 814 } 815 return $maxLength; 816 } 817 818 /** 819 * Set the body wrapping. 820 * @access private 821 * @return void 822 */ 823 function SetWordWrap() { 824 if($this->WordWrap < 1) { 825 return; 826 } 827 828 switch($this->message_type) { 829 case 'alt': 830 /* fall through */ 831 case 'alt_attachments': 832 $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); 833 break; 834 default: 835 $this->Body = $this->WrapText($this->Body, $this->WordWrap); 836 break; 837 } 838 } 839 840 /** 841 * Assembles message header. 842 * @access private 843 * @return string 844 */ 845 function CreateHeader() { 846 $result = ''; 847 848 /* Set the boundaries */ 849 $uniq_id = md5(uniqid(time())); 850 $this->boundary[1] = 'b1_' . $uniq_id; 851 $this->boundary[2] = 'b2_' . $uniq_id; 852 853 $result .= $this->HeaderLine('Date', $this->RFCDate()); 854 if($this->Sender == '') { 855 $result .= $this->HeaderLine('Return-Path', trim($this->From)); 856 } else { 857 $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); 858 } 859 860 /* To be created automatically by mail() */ 861 if($this->Mailer != 'mail') { 862 if(count($this->to) > 0) { 863 $result .= $this->AddrAppend('To', $this->to); 864 } elseif (count($this->cc) == 0) { 865 $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); 866 } 867 if(count($this->cc) > 0) { 868 $result .= $this->AddrAppend('Cc', $this->cc); 869 } 870 } 871 872 $from = array(); 873 $from[0][0] = trim($this->From); 874 $from[0][1] = $this->FromName; 875 $result .= $this->AddrAppend('From', $from); 876 877 /* sendmail and mail() extract Cc from the header before sending */ 878 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) { 879 $result .= $this->AddrAppend('Cc', $this->cc); 880 } 881 882 /* sendmail and mail() extract Bcc from the header before sending */ 883 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { 884 $result .= $this->AddrAppend('Bcc', $this->bcc); 885 } 886 887 if(count($this->ReplyTo) > 0) { 888 $result .= $this->AddrAppend('Reply-To', $this->ReplyTo); 889 } 890 891 /* mail() sets the subject itself */ 892 if($this->Mailer != 'mail') { 893 $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); 894 } 895 896 if($this->MessageID != '') { 897 $result .= $this->HeaderLine('Message-ID',$this->MessageID); 898 } else { 899 $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); 900 } 901 $result .= $this->HeaderLine('X-Priority', $this->Priority); 902 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']'); 903 904 if($this->ConfirmReadingTo != '') { 905 $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); 906 } 907 908 // Add custom headers 909 for($index = 0; $index < count($this->CustomHeader); $index++) { 910 $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); 911 } 912 if (!$this->sign_key_file) { 913 $result .= $this->HeaderLine('MIME-Version', '1.0'); 914 $result .= $this->GetMailMIME(); 915 } 916 917 return $result; 918 } 919 920 /** 921 * Returns the message MIME. 922 * @access private 923 * @return string 924 */ 925 function GetMailMIME() { 926 $result = ''; 927 switch($this->message_type) { 928 case 'plain': 929 $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); 930 $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet); 931 break; 932 case 'attachments': 933 /* fall through */ 934 case 'alt_attachments': 935 if($this->InlineImageExists()){ 936 $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); 937 } else { 938 $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); 939 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); 940 } 941 break; 942 case 'alt': 943 $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); 944 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); 945 break; 946 } 947 948 if($this->Mailer != 'mail') { 949 $result .= $this->LE.$this->LE; 950 } 951 952 return $result; 953 } 954 955 /** 956 * Assembles the message body. Returns an empty string on failure. 957 * @access private 958 * @return string 959 */ 960 function CreateBody() { 961 $result = ''; 962 if ($this->sign_key_file) { 963 $result .= $this->GetMailMIME(); 964 } 965 966 $this->SetWordWrap(); 967 968 switch($this->message_type) { 969 case 'alt': 970 $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); 971 $result .= $this->EncodeString($this->AltBody, $this->Encoding); 972 $result .= $this->LE.$this->LE; 973 $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); 974 $result .= $this->EncodeString($this->Body, $this->Encoding); 975 $result .= $this->LE.$this->LE; 976 $result .= $this->EndBoundary($this->boundary[1]); 977 break; 978 case 'plain': 979 $result .= $this->EncodeString($this->Body, $this->Encoding); 980 break; 981 case 'attachments': 982 $result .= $this->GetBoundary($this->boundary[1], '', '', ''); 983 $result .= $this->EncodeString($this->Body, $this->Encoding); 984 $result .= $this->LE; 985 $result .= $this->AttachAll(); 986 break; 987 case 'alt_attachments': 988 $result .= sprintf("--%s%s", $this->boundary[1], $this->LE); 989 $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); 990 $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body 991 $result .= $this->EncodeString($this->AltBody, $this->Encoding); 992 $result .= $this->LE.$this->LE; 993 $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body 994 $result .= $this->EncodeString($this->Body, $this->Encoding); 995 $result .= $this->LE.$this->LE; 996 $result .= $this->EndBoundary($this->boundary[2]); 997 $result .= $this->AttachAll(); 998 break; 999 } 1000 1001 if($this->IsError()) { 1002 $result = ''; 1003 } else if ($this->sign_key_file) { 1004 $file = tempnam("", "mail"); 1005 $fp = fopen($file, "w"); 1006 fwrite($fp, $result); 1007 fclose($fp); 1008 $signed = tempnam("", "signed"); 1009 1010 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_key_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) { 1011 $fp = fopen($signed, "r"); 1012 $result = fread($fp, filesize($this->sign_key_file)); 1013 fclose($fp); 1014 } else { 1015 $this->SetError($this->Lang("signing").openssl_error_string()); 1016 $result = ''; 1017 } 1018 1019 unlink($file); 1020 unlink($signed); 1021 } 1022 1023 return $result; 1024 } 1025 1026 /** 1027 * Returns the start of a message boundary. 1028 * @access private 1029 */ 1030 function GetBoundary($boundary, $charSet, $contentType, $encoding) { 1031 $result = ''; 1032 if($charSet == '') { 1033 $charSet = $this->CharSet; 1034 } 1035 if($contentType == '') { 1036 $contentType = $this->ContentType; 1037 } 1038 if($encoding == '') { 1039 $encoding = $this->Encoding; 1040 } 1041 $result .= $this->TextLine('--' . $boundary); 1042 $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet); 1043 $result .= $this->LE; 1044 $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); 1045 $result .= $this->LE; 1046 1047 return $result; 1048 } 1049 1050 /** 1051 * Returns the end of a message boundary. 1052 * @access private 1053 */ 1054 function EndBoundary($boundary) { 1055 return $this->LE . '--' . $boundary . '--' . $this->LE; 1056 } 1057 1058 /** 1059 * Sets the message type. 1060 * @access private 1061 * @return void 1062 */ 1063 function SetMessageType() { 1064 if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { 1065 $this->message_type = 'plain'; 1066 } else { 1067 if(count($this->attachment) > 0) { 1068 $this->message_type = 'attachments'; 1069 } 1070 if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) { 1071 $this->message_type = 'alt'; 1072 } 1073 if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { 1074 $this->message_type = 'alt_attachments'; 1075 } 1076 } 1077 } 1078 1079 /* Returns a formatted header line. 1080 * @access private 1081 * @return string 1082 */ 1083 function HeaderLine($name, $value) { 1084 return $name . ': ' . $value . $this->LE; 1085 } 1086 1087 /** 1088 * Returns a formatted mail line. 1089 * @access private 1090 * @return string 1091 */ 1092 function TextLine($value) { 1093 return $value . $this->LE; 1094 } 1095 1096 ///////////////////////////////////////////////// 1097 // CLASS METHODS, ATTACHMENTS 1098 ///////////////////////////////////////////////// 1099 1100 /** 1101 * Adds an attachment from a path on the filesystem. 1102 * Returns false if the file could not be found 1103 * or accessed. 1104 * @param string $path Path to the attachment. 1105 * @param string $name Overrides the attachment name. 1106 * @param string $encoding File encoding (see $Encoding). 1107 * @param string $type File extension (MIME) type. 1108 * @return bool 1109 */ 1110 function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 1111 if(!@is_file($path)) { 1112 $this->SetError($this->Lang('file_access') . $path); 1113 return false; 1114 } 1115 1116 $filename = basename($path); 1117 if($name == '') { 1118 $name = $filename; 1119 } 1120 1121 $cur = count($this->attachment); 1122 $this->attachment[$cur][0] = $path; 1123 $this->attachment[$cur][1] = $filename; 1124 $this->attachment[$cur][2] = $name; 1125 $this->attachment[$cur][3] = $encoding; 1126 $this->attachment[$cur][4] = $type; 1127 $this->attachment[$cur][5] = false; // isStringAttachment 1128 $this->attachment[$cur][6] = 'attachment'; 1129 $this->attachment[$cur][7] = 0; 1130 1131 return true; 1132 } 1133 1134 /** 1135 * Attaches all fs, string, and binary attachments to the message. 1136 * Returns an empty string on failure. 1137 * @access private 1138 * @return string 1139 */ 1140 function AttachAll() { 1141 /* Return text of body */ 1142 $mime = array(); 1143 1144 /* Add all attachments */ 1145 for($i = 0; $i < count($this->attachment); $i++) { 1146 /* Check for string attachment */ 1147 $bString = $this->attachment[$i][5]; 1148 if ($bString) { 1149 $string = $this->attachment[$i][0]; 1150 } else { 1151 $path = $this->attachment[$i][0]; 1152 } 1153 1154 $filename = $this->attachment[$i][1]; 1155 $name = $this->attachment[$i][2]; 1156 $encoding = $this->attachment[$i][3]; 1157 $type = $this->attachment[$i][4]; 1158 $disposition = $this->attachment[$i][6]; 1159 $cid = $this->attachment[$i][7]; 1160 1161 $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); 1162 $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE); 1163 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); 1164 1165 if($disposition == 'inline') { 1166 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); 1167 } 1168 1169 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE); 1170 1171 /* Encode as string attachment */ 1172 if($bString) { 1173 $mime[] = $this->EncodeString($string, $encoding); 1174 if($this->IsError()) { 1175 return ''; 1176 } 1177 $mime[] = $this->LE.$this->LE; 1178 } else { 1179 $mime[] = $this->EncodeFile($path, $encoding); 1180 if($this->IsError()) { 1181 return ''; 1182 } 1183 $mime[] = $this->LE.$this->LE; 1184 } 1185 } 1186 1187 $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); 1188 1189 return join('', $mime); 1190 } 1191 1192 /** 1193 * Encodes attachment in requested format. Returns an 1194 * empty string on failure. 1195 * @access private 1196 * @return string 1197 */ 1198 function EncodeFile ($path, $encoding = 'base64') { 1199 if(!@$fd = fopen($path, 'rb')) { 1200 $this->SetError($this->Lang('file_open') . $path); 1201 return ''; 1202 } 1203 $magic_quotes = get_magic_quotes_runtime(); 1204 set_magic_quotes_runtime(0); 1205 $file_buffer = fread($fd, filesize($path)); 1206 $file_buffer = $this->EncodeString($file_buffer, $encoding); 1207 fclose($fd); 1208 set_magic_quotes_runtime($magic_quotes); 1209 1210 return $file_buffer; 1211 } 1212 1213 /** 1214 * Encodes string to requested format. Returns an 1215 * empty string on failure. 1216 * @access private 1217 * @return string 1218 */ 1219 function EncodeString ($str, $encoding = 'base64') { 1220 $encoded = ''; 1221 switch(strtolower($encoding)) { 1222 case 'base64': 1223 /* chunk_split is found in PHP >= 3.0.6 */ 1224 $encoded = chunk_split(base64_encode($str), 76, $this->LE); 1225 break; 1226 case '7bit': 1227 case '8bit': 1228 $encoded = $this->FixEOL($str); 1229 if (substr($encoded, -(strlen($this->LE))) != $this->LE) 1230 $encoded .= $this->LE; 1231 break; 1232 case 'binary': 1233 $encoded = $str; 1234 break; 1235 case 'quoted-printable': 1236 $encoded = $this->EncodeQP($str); 1237 break; 1238 default: 1239 $this->SetError($this->Lang('encoding') . $encoding); 1240 break; 1241 } 1242 return $encoded; 1243 } 1244 1245 /** 1246 * Encode a header string to best of Q, B, quoted or none. 1247 * @access private 1248 * @return string 1249 */ 1250 function EncodeHeader ($str, $position = 'text') { 1251 $x = 0; 1252 1253 switch (strtolower($position)) { 1254 case 'phrase': 1255 if (!preg_match('/[\200-\377]/', $str)) { 1256 /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */ 1257 $encoded = addcslashes($str, "\0..\37\177\\\""); 1258 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { 1259 return ($encoded); 1260 } else { 1261 return ("\"$encoded\""); 1262 } 1263 } 1264 $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); 1265 break; 1266 case 'comment': 1267 $x = preg_match_all('/[()"]/', $str, $matches); 1268 /* Fall-through */ 1269 case 'text': 1270 default: 1271 $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); 1272 break; 1273 } 1274 1275 if ($x == 0) { 1276 return ($str); 1277 } 1278 1279 $maxlen = 75 - 7 - strlen($this->CharSet); 1280 /* Try to select the encoding which should produce the shortest output */ 1281 if (strlen($str)/3 < $x) { 1282 $encoding = 'B'; 1283 if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { 1284 // Use a custom function which correctly encodes and wraps long 1285 // multibyte strings without breaking lines within a character 1286 $encoded = $this->Base64EncodeWrapMB($str); 1287 } else { 1288 $encoded = base64_encode($str); 1289 $maxlen -= $maxlen % 4; 1290 $encoded = trim(chunk_split($encoded, $maxlen, "\n")); 1291 } 1292 } else { 1293 $encoding = 'Q'; 1294 $encoded = $this->EncodeQ($str, $position); 1295 $encoded = $this->WrapText($encoded, $maxlen, true); 1296 $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); 1297 } 1298 1299 $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); 1300 $encoded = trim(str_replace("\n", $this->LE, $encoded)); 1301 1302 return $encoded; 1303 } 1304 1305 /** 1306 * Checks if a string contains multibyte characters. 1307 * @access private 1308 * @param string $str multi-byte text to wrap encode 1309 * @return bool 1310 */ 1311 function HasMultiBytes($str) { 1312 if (function_exists('mb_strlen')) { 1313 return (strlen($str) > mb_strlen($str, $this->CharSet)); 1314 } else { // Assume no multibytes (we can't handle without mbstring functions anyway) 1315 return False; 1316 } 1317 } 1318 1319 /** 1320 * Correctly encodes and wraps long multibyte strings for mail headers 1321 * without breaking lines within a character. 1322 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php 1323 * @access private 1324 * @param string $str multi-byte text to wrap encode 1325 * @return string 1326 */ 1327 function Base64EncodeWrapMB($str) { 1328 $start = "=?".$this->CharSet."?B?"; 1329 $end = "?="; 1330 $encoded = ""; 1331 1332 $mb_length = mb_strlen($str, $this->CharSet); 1333 // Each line must have length <= 75, including $start and $end 1334 $length = 75 - strlen($start) - strlen($end); 1335 // Average multi-byte ratio 1336 $ratio = $mb_length / strlen($str); 1337 // Base64 has a 4:3 ratio 1338 $offset = $avgLength = floor($length * $ratio * .75); 1339 1340 for ($i = 0; $i < $mb_length; $i += $offset) { 1341 $lookBack = 0; 1342 1343 do { 1344 $offset = $avgLength - $lookBack; 1345 $chunk = mb_substr($str, $i, $offset, $this->CharSet); 1346 $chunk = base64_encode($chunk); 1347 $lookBack++; 1348 } 1349 while (strlen($chunk) > $length); 1350 1351 $encoded .= $chunk . $this->LE; 1352 } 1353 1354 // Chomp the last linefeed 1355 $encoded = substr($encoded, 0, -strlen($this->LE)); 1356 return $encoded; 1357 } 1358 1359 /** 1360 * Encode string to quoted-printable. 1361 * @access private 1362 * @return string 1363 */ 1364 function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) { 1365 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 1366 $lines = preg_split('/(?:\r\n|\r|\n)/', $input); 1367 $eol = "\r\n"; 1368 $escape = '='; 1369 $output = ''; 1370 while( list(, $line) = each($lines) ) { 1371 $linlen = strlen($line); 1372 $newline = ''; 1373 for($i = 0; $i < $linlen; $i++) { 1374 $c = substr( $line, $i, 1 ); 1375 $dec = ord( $c ); 1376 if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E 1377 $c = '=2E'; 1378 } 1379 if ( $dec == 32 ) { 1380 if ( $i == ( $linlen - 1 ) ) { // convert space at eol only 1381 $c = '=20'; 1382 } else if ( $space_conv ) { 1383 $c = '=20'; 1384 } 1385 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required 1386 $h2 = floor($dec/16); 1387 $h1 = floor($dec%16); 1388 $c = $escape.$hex[$h2].$hex[$h1]; 1389 } 1390 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted 1391 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 1392 $newline = ''; 1393 // check if newline first character will be point or not 1394 if ( $dec == 46 ) { 1395 $c = '=2E'; 1396 } 1397 } 1398 $newline .= $c; 1399 } // end of for 1400 $output .= $newline.$eol; 1401 } // end of while 1402 return trim($output); 1403 } 1404 1405 /** 1406 * Encode string to q encoding. 1407 * @access private 1408 * @return string 1409 */ 1410 function EncodeQ ($str, $position = 'text') { 1411 /* There should not be any EOL in the string */ 1412 $encoded = preg_replace("[\r\n]", '', $str); 1413 1414 switch (strtolower($position)) { 1415 case 'phrase': 1416 $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1417 break; 1418 case 'comment': 1419 $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1420 case 'text': 1421 default: 1422 /* Replace every high ascii, control =, ? and _ characters */ 1423 $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', 1424 "'='.sprintf('%02X', ord('\\1'))", $encoded); 1425 break; 1426 } 1427 1428 /* Replace every spaces to _ (more readable than =20) */ 1429 $encoded = str_replace(' ', '_', $encoded); 1430 1431 return $encoded; 1432 } 1433 1434 /** 1435 * Adds a string or binary attachment (non-filesystem) to the list. 1436 * This method can be used to attach ascii or binary data, 1437 * such as a BLOB record from a database. 1438 * @param string $string String attachment data. 1439 * @param string $filename Name of the attachment. 1440 * @param string $encoding File encoding (see $Encoding). 1441 * @param string $type File extension (MIME) type. 1442 * @return void 1443 */ 1444 function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { 1445 /* Append to $attachment array */ 1446 $cur = count($this->attachment); 1447 $this->attachment[$cur][0] = $string; 1448 $this->attachment[$cur][1] = $filename; 1449 $this->attachment[$cur][2] = $filename; 1450 $this->attachment[$cur][3] = $encoding; 1451 $this->attachment[$cur][4] = $type; 1452 $this->attachment[$cur][5] = true; // isString 1453 $this->attachment[$cur][6] = 'attachment'; 1454 $this->attachment[$cur][7] = 0; 1455 } 1456 1457 /** 1458 * Adds an embedded attachment. This can include images, sounds, and 1459 * just about any other document. Make sure to set the $type to an 1460 * image type. For JPEG images use "image/jpeg" and for GIF images 1461 * use "image/gif". 1462 * @param string $path Path to the attachment. 1463 * @param string $cid Content ID of the attachment. Use this to identify 1464 * the Id for accessing the image in an HTML form. 1465 * @param string $name Overrides the attachment name. 1466 * @param string $encoding File encoding (see $Encoding). 1467 * @param string $type File extension (MIME) type. 1468 * @return bool 1469 */ 1470 function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { 1471 1472 if(!@is_file($path)) { 1473 $this->SetError($this->Lang('file_access') . $path); 1474 return false; 1475 } 1476 1477 $filename = basename($path); 1478 if($name == '') { 1479 $name = $filename; 1480 } 1481 1482 /* Append to $attachment array */ 1483 $cur = count($this->attachment); 1484 $this->attachment[$cur][0] = $path; 1485 $this->attachment[$cur][1] = $filename; 1486 $this->attachment[$cur][2] = $name; 1487 $this->attachment[$cur][3] = $encoding; 1488 $this->attachment[$cur][4] = $type; 1489 $this->attachment[$cur][5] = false; 1490 $this->attachment[$cur][6] = 'inline'; 1491 $this->attachment[$cur][7] = $cid; 1492 1493 return true; 1494 } 1495 1496 /** 1497 * Returns true if an inline attachment is present. 1498 * @access private 1499 * @return bool 1500 */ 1501 function InlineImageExists() { 1502 $result = false; 1503 for($i = 0; $i < count($this->attachment); $i++) { 1504 if($this->attachment[$i][6] == 'inline') { 1505 $result = true; 1506 break; 1507 } 1508 } 1509 1510 return $result; 1511 } 1512 1513 ///////////////////////////////////////////////// 1514 // CLASS METHODS, MESSAGE RESET 1515 ///////////////////////////////////////////////// 1516 1517 /** 1518 * Clears all recipients assigned in the TO array. Returns void. 1519 * @return void 1520 */ 1521 function ClearAddresses() { 1522 $this->to = array(); 1523 } 1524 1525 /** 1526 * Clears all recipients assigned in the CC array. Returns void. 1527 * @return void 1528 */ 1529 function ClearCCs() { 1530 $this->cc = array(); 1531 } 1532 1533 /** 1534 * Clears all recipients assigned in the BCC array. Returns void. 1535 * @return void 1536 */ 1537 function ClearBCCs() { 1538 $this->bcc = array(); 1539 } 1540 1541 /** 1542 * Clears all recipients assigned in the ReplyTo array. Returns void. 1543 * @return void 1544 */ 1545 function ClearReplyTos() { 1546 $this->ReplyTo = array(); 1547 } 1548 1549 /** 1550 * Clears all recipients assigned in the TO, CC and BCC 1551 * array. Returns void. 1552 * @return void 1553 */ 1554 function ClearAllRecipients() { 1555 $this->to = array(); 1556 $this->cc = array(); 1557 $this->bcc = array(); 1558 } 1559 1560 /** 1561 * Clears all previously set filesystem, string, and binary 1562 * attachments. Returns void. 1563 * @return void 1564 */ 1565 function ClearAttachments() { 1566 $this->attachment = array(); 1567 } 1568 1569 /** 1570 * Clears all custom headers. Returns void. 1571 * @return void 1572 */ 1573 function ClearCustomHeaders() { 1574 $this->CustomHeader = array(); 1575 } 1576 1577 ///////////////////////////////////////////////// 1578 // CLASS METHODS, MISCELLANEOUS 1579 ///////////////////////////////////////////////// 1580 1581 /** 1582 * Adds the error message to the error container. 1583 * Returns void. 1584 * @access private 1585 * @return void 1586 */ 1587 function SetError($msg) { 1588 $this->error_count++; 1589 $this->ErrorInfo = $msg; 1590 } 1591 1592 /** 1593 * Returns the proper RFC 822 formatted date. 1594 * @access private 1595 * @return string 1596 */ 1597 function RFCDate() { 1598 $tz = date('Z'); 1599 $tzs = ($tz < 0) ? '-' : '+'; 1600 $tz = abs($tz); 1601 $tz = (int)($tz/3600)*100 + ($tz%3600)/60; 1602 $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); 1603 1604 return $result; 1605 } 1606 1607 /** 1608 * Returns the appropriate server variable. Should work with both 1609 * PHP 4.1.0+ as well as older versions. Returns an empty string 1610 * if nothing is found. 1611 * @access private 1612 * @return mixed 1613 */ 1614 function ServerVar($varName) { 1615 global $HTTP_SERVER_VARS; 1616 global $HTTP_ENV_VARS; 1617 1618 if(!isset($_SERVER)) { 1619 $_SERVER = $HTTP_SERVER_VARS; 1620 if(!isset($_SERVER['REMOTE_ADDR'])) { 1621 $_SERVER = $HTTP_ENV_VARS; // must be Apache 1622 } 1623 } 1624 1625 if(isset($_SERVER[$varName])) { 1626 return $_SERVER[$varName]; 1627 } else { 1628 return ''; 1629 } 1630 } 1631 1632 /** 1633 * Returns the server hostname or 'localhost.localdomain' if unknown. 1634 * @access private 1635 * @return string 1636 */ 1637 function ServerHostname() { 1638 if ($this->Hostname != '') { 1639 $result = $this->Hostname; 1640 } elseif ($this->ServerVar('SERVER_NAME') != '') { 1641 $result = $this->ServerVar('SERVER_NAME'); 1642 } else { 1643 $result = 'localhost.localdomain'; 1644 } 1645 1646 return $result; 1647 } 1648 1649 /** 1650 * Returns a message in the appropriate language. 1651 * @access private 1652 * @return string 1653 */ 1654 function Lang($key) { 1655 if(count($this->language) < 1) { 1656 $this->SetLanguage('en'); // set the default language 1657 } 1658 1659 if(isset($this->language[$key])) { 1660 return $this->language[$key]; 1661 } else { 1662 return 'Language string failed to load: ' . $key; 1663 } 1664 } 1665 1666 /** 1667 * Returns true if an error occurred. 1668 * @return bool 1669 */ 1670 function IsError() { 1671 return ($this->error_count > 0); 1672 } 1673 1674 /** 1675 * Changes every end of line from CR or LF to CRLF. 1676 * @access private 1677 * @return string 1678 */ 1679 function FixEOL($str) { 1680 $str = str_replace("\r\n", "\n", $str); 1681 $str = str_replace("\r", "\n", $str); 1682 $str = str_replace("\n", $this->LE, $str); 1683 return $str; 1684 } 1685 1686 /** 1687 * Adds a custom header. 1688 * @return void 1689 */ 1690 function AddCustomHeader($custom_header) { 1691 $this->CustomHeader[] = explode(':', $custom_header, 2); 1692 } 1693 1694 /** 1695 * Evaluates the message and returns modifications for inline images and backgrounds 1696 * @access public 1697 * @return $message 1698 */ 1699 function MsgHTML($message,$basedir='') { 1700 preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); 1701 if(isset($images[2])) { 1702 foreach($images[2] as $i => $url) { 1703 // do not change urls for absolute images (thanks to corvuscorax) 1704 if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) { 1705 $filename = basename($url); 1706 $directory = dirname($url); 1707 ($directory == '.')?$directory='':''; 1708 $cid = 'cid:' . md5($filename); 1709 $fileParts = split("\.", $filename); 1710 $ext = $fileParts[1]; 1711 $mimeType = $this->_mime_types($ext); 1712 if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } 1713 if ( strlen($directory) > 1 && substr($basedir,-1) != '/') { $directory .= '/'; } 1714 $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType); 1715 if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { 1716 $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); 1717 } 1718 } 1719 } 1720 } 1721 $this->IsHTML(true); 1722 $this->Body = $message; 1723 $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); 1724 if ( !empty($textMsg) && empty($this->AltBody) ) { 1725 $this->AltBody = $textMsg; 1726 } 1727 if ( empty($this->AltBody) ) { 1728 $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n"; 1729 } 1730 } 1731 1732 /** 1733 * Gets the mime type of the embedded or inline image 1734 * @access private 1735 * @return mime type of ext 1736 */ 1737 function _mime_types($ext = '') { 1738 $mimes = array( 1739 'hqx' => 'application/mac-binhex40', 1740 'cpt' => 'application/mac-compactpro', 1741 'doc' => 'application/msword', 1742 'bin' => 'application/macbinary', 1743 'dms' => 'application/octet-stream', 1744 'lha' => 'application/octet-stream', 1745 'lzh' => 'application/octet-stream', 1746 'exe' => 'application/octet-stream', 1747 'class' => 'application/octet-stream', 1748 'psd' => 'application/octet-stream', 1749 'so' => 'application/octet-stream', 1750 'sea' => 'application/octet-stream', 1751 'dll' => 'application/octet-stream', 1752 'oda' => 'application/oda', 1753 'pdf' => 'application/pdf', 1754 'ai' => 'application/postscript', 1755 'eps' => 'application/postscript', 1756 'ps' => 'application/postscript', 1757 'smi' => 'application/smil', 1758 'smil' => 'application/smil', 1759 'mif' => 'application/vnd.mif', 1760 'xls' => 'application/vnd.ms-excel', 1761 'ppt' => 'application/vnd.ms-powerpoint', 1762 'wbxml' => 'application/vnd.wap.wbxml', 1763 'wmlc' => 'application/vnd.wap.wmlc', 1764 'dcr' => 'application/x-director', 1765 'dir' => 'application/x-director', 1766 'dxr' => 'application/x-director', 1767 'dvi' => 'application/x-dvi', 1768 'gtar' => 'application/x-gtar', 1769 'php' => 'application/x-httpd-php', 1770 'php4' => 'application/x-httpd-php', 1771 'php3' => 'application/x-httpd-php', 1772 'phtml' => 'application/x-httpd-php', 1773 'phps' => 'application/x-httpd-php-source', 1774 'js' => 'application/x-javascript', 1775 'swf' => 'application/x-shockwave-flash', 1776 'sit' => 'application/x-stuffit', 1777 'tar' => 'application/x-tar', 1778 'tgz' => 'application/x-tar', 1779 'xhtml' => 'application/xhtml+xml', 1780 'xht' => 'application/xhtml+xml', 1781 'zip' => 'application/zip', 1782 'mid' => 'audio/midi', 1783 'midi' => 'audio/midi', 1784 'mpga' => 'audio/mpeg', 1785 'mp2' => 'audio/mpeg', 1786 'mp3' => 'audio/mpeg', 1787 'aif' => 'audio/x-aiff', 1788 'aiff' => 'audio/x-aiff', 1789 'aifc' => 'audio/x-aiff', 1790 'ram' => 'audio/x-pn-realaudio', 1791 'rm' => 'audio/x-pn-realaudio', 1792 'rpm' => 'audio/x-pn-realaudio-plugin', 1793 'ra' => 'audio/x-realaudio', 1794 'rv' => 'video/vnd.rn-realvideo', 1795 'wav' => 'audio/x-wav', 1796 'bmp' => 'image/bmp', 1797 'gif' => 'image/gif', 1798 'jpeg' => 'image/jpeg', 1799 'jpg' => 'image/jpeg', 1800 'jpe' => 'image/jpeg', 1801 'png' => 'image/png', 1802 'tiff' => 'image/tiff', 1803 'tif' => 'image/tiff', 1804 'css' => 'text/css', 1805 'html' => 'text/html', 1806 'htm' => 'text/html', 1807 'shtml' => 'text/html', 1808 'txt' => 'text/plain', 1809 'text' => 'text/plain', 1810 'log' => 'text/plain', 1811 'rtx' => 'text/richtext', 1812 'rtf' => 'text/rtf', 1813 'xml' => 'text/xml', 1814 'xsl' => 'text/xml', 1815 'mpeg' => 'video/mpeg', 1816 'mpg' => 'video/mpeg', 1817 'mpe' => 'video/mpeg', 1818 'qt' => 'video/quicktime', 1819 'mov' => 'video/quicktime', 1820 'avi' => 'video/x-msvideo', 1821 'movie' => 'video/x-sgi-movie', 1822 'doc' => 'application/msword', 1823 'word' => 'application/msword', 1824 'xl' => 'application/excel', 1825 'eml' => 'message/rfc822' 1826 ); 1827 return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; 1828 } 1829 1830 /** 1831 * Set (or reset) Class Objects (variables) 1832 * 1833 * Usage Example: 1834 * $page->set('X-Priority', '3'); 1835 * 1836 * @access public 1837 * @param string $name Parameter Name 1838 * @param mixed $value Parameter Value 1839 * NOTE: will not work with arrays, there are no arrays to set/reset 1840 */ 1841 function set ( $name, $value = '' ) { 1842 if ( isset($this->$name) ) { 1843 $this->$name = $value; 1844 } else { 1845 $this->SetError('Cannot set or reset variable ' . $name); 1846 return false; 1847 } 1848 } 1849 1850 /** 1851 * Read a file from a supplied filename and return it. 1852 * 1853 * @access public 1854 * @param string $filename Parameter File Name 1855 */ 1856 function getFile($filename) { 1857 $return = ''; 1858 if ($fp = fopen($filename, 'rb')) { 1859 while (!feof($fp)) { 1860 $return .= fread($fp, 1024); 1861 } 1862 fclose($fp); 1863 return $return; 1864 } else { 1865 return false; 1866 } 1867 } 1868 1869 /** 1870 * Strips newlines to prevent header injection. 1871 * @access private 1872 * @param string $str String 1873 * @return string 1874 */ 1875 function SecureHeader($str) { 1876 $str = trim($str); 1877 $str = str_replace("\r", "", $str); 1878 $str = str_replace("\n", "", $str); 1879 return $str; 1880 } 1881 1882 /** 1883 * Set the private key file and password to sign the message. 1884 * 1885 * @access public 1886 * @param string $key_filename Parameter File Name 1887 * @param string $key_pass Password for private key 1888 */ 1889 function Sign($key_filename, $key_pass) { 1890 $this->sign_key_file = $key_filename; 1891 $this->sign_key_pass = $key_pass; 1892 } 1893 1894 } 1895 1896 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 5 12:05:07 2009 | Cross-referenced by PHPXref 0.7 |