[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 //////////////////////////////////////////////////// 3 // PHPMailer - PHP email class 4 // 5 // Class for sending email using either 6 // sendmail, PHP mail(), or SMTP. Methods are 7 // based upon the standard AspEmail(tm) classes. 8 // 9 // Copyright (C) 2001 - 2003 Brent R. Matzelle 10 // 11 // License: LGPL, see LICENSE 12 //////////////////////////////////////////////////// 13 14 /** 15 * PHPMailer - PHP email transport class 16 * @package PHPMailer 17 * @author Brent R. Matzelle 18 * @copyright 2001 - 2003 Brent R. Matzelle 19 */ 20 class PHPMailer 21 { 22 ///////////////////////////////////////////////// 23 // PUBLIC VARIABLES 24 ///////////////////////////////////////////////// 25 26 /** 27 * Email priority (1 = High, 3 = Normal, 5 = low). 28 * @var int 29 */ 30 var $Priority = 3; 31 32 /** 33 * Sets the CharSet of the message. 34 * @var string 35 */ 36 var $CharSet = "UTF-8"; 37 38 /** 39 * Sets the Content-type of the message. 40 * @var string 41 */ 42 var $ContentType = "text/plain"; 43 44 /** 45 * Sets the Encoding of the message. Options for this are "8bit", 46 * "7bit", "binary", "base64", and "quoted-printable". 47 * @var string 48 */ 49 var $Encoding = "8bit"; 50 51 /** 52 * Holds the most recent mailer error message. 53 * @var string 54 */ 55 var $ErrorInfo = ""; 56 57 /** 58 * Sets the From email address for the message. 59 * @var string 60 */ 61 var $From = "root@localhost"; 62 63 /** 64 * Sets the From name of the message. 65 * @var string 66 */ 67 var $FromName = "Root User"; 68 69 /** 70 * Sets the Sender email (Return-Path) of the message. If not empty, 71 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. 72 * @var string 73 */ 74 var $Sender = ""; 75 76 /** 77 * Sets the Subject of the message. 78 * @var string 79 */ 80 var $Subject = ""; 81 82 /** 83 * Sets the Body of the message. This can be either an HTML or text body. 84 * If HTML then run IsHTML(true). 85 * @var string 86 */ 87 var $Body = ""; 88 89 /** 90 * Sets the text-only body of the message. This automatically sets the 91 * email to multipart/alternative. This body can be read by mail 92 * clients that do not have HTML email capability such as mutt. Clients 93 * that can read HTML will view the normal Body. 94 * @var string 95 */ 96 var $AltBody = ""; 97 98 /** 99 * Sets word wrapping on the body of the message to a given number of 100 * characters. 101 * @var int 102 */ 103 var $WordWrap = 0; 104 105 /** 106 * Method to send mail: ("mail", "sendmail", or "smtp"). 107 * @var string 108 */ 109 var $Mailer = "mail"; 110 111 /** 112 * Sets the path of the sendmail program. 113 * @var string 114 */ 115 var $Sendmail = "/usr/sbin/sendmail"; 116 117 /** 118 * Path to PHPMailer plugins. This is now only useful if the SMTP class 119 * is in a different directory than the PHP include path. 120 * @var string 121 */ 122 var $PluginDir = ""; 123 124 /** 125 * Holds PHPMailer version. 126 * @var string 127 */ 128 var $Version = "1.72"; 129 130 /** 131 * Sets the email address that a reading confirmation will be sent. 132 * @var string 133 */ 134 var $ConfirmReadingTo = ""; 135 136 /** 137 * Sets the hostname to use in Message-Id and Received headers 138 * and as default HELO string. If empty, the value returned 139 * by SERVER_NAME is used or 'localhost.localdomain'. 140 * @var string 141 */ 142 var $Hostname = ""; 143 144 ///////////////////////////////////////////////// 145 // SMTP VARIABLES 146 ///////////////////////////////////////////////// 147 148 /** 149 * Sets the SMTP hosts. All hosts must be separated by a 150 * semicolon. You can also specify a different port 151 * for each host by using this format: [hostname:port] 152 * (e.g. "smtp1.example.com:25;smtp2.example.com"). 153 * Hosts will be tried in order. 154 * @var string 155 */ 156 var $Host = "localhost"; 157 158 /** 159 * Sets the default SMTP server port. 160 * @var int 161 */ 162 var $Port = 25; 163 164 /** 165 * Sets the SMTP HELO of the message (Default is $Hostname). 166 * @var string 167 */ 168 var $Helo = ""; 169 170 /** 171 * Sets SMTP authentication. Utilizes the Username and Password variables. 172 * @var bool 173 */ 174 var $SMTPAuth = false; 175 176 /** 177 * Sets SMTP username. 178 * @var string 179 */ 180 var $Username = ""; 181 182 /** 183 * Sets SMTP password. 184 * @var string 185 */ 186 var $Password = ""; 187 188 /** 189 * Sets the SMTP server timeout in seconds. This function will not 190 * work with the win32 version. 191 * @var int 192 */ 193 var $Timeout = 60; // Fix for http://trac.vtiger.com/cgi-bin/trac.cgi/ticket/5389 194 195 /** 196 * Sets SMTP class debugging on or off. 197 * @var bool 198 */ 199 var $SMTPDebug = false; 200 201 /** 202 * Prevents the SMTP connection from being closed after each mail 203 * sending. If this is set to true then to close the connection 204 * requires an explicit call to SmtpClose(). 205 * @var bool 206 */ 207 var $SMTPKeepAlive = false; 208 209 /**#@+ 210 * @access private 211 */ 212 var $smtp = NULL; 213 var $to = array(); 214 var $cc = array(); 215 var $bcc = array(); 216 var $ReplyTo = array(); 217 var $attachment = array(); 218 var $CustomHeader = array(); 219 var $message_type = ""; 220 var $boundary = array(); 221 var $language = array(); 222 var $error_count = 0; 223 var $LE = "\n"; 224 /**#@-*/ 225 226 ///////////////////////////////////////////////// 227 // VARIABLE METHODS 228 ///////////////////////////////////////////////// 229 230 /** 231 * Sets message type to HTML. 232 * @param bool $bool 233 * @return void 234 */ 235 function IsHTML($bool) { 236 if($bool == true) 237 $this->ContentType = "text/html"; 238 else 239 $this->ContentType = "text/plain"; 240 } 241 242 /** 243 * Sets Mailer to send message using SMTP. 244 * @return void 245 */ 246 function IsSMTP() { 247 $this->Mailer = "smtp"; 248 } 249 250 /** 251 * Sets Mailer to send message using PHP mail() function. 252 * @return void 253 */ 254 function IsMail() { 255 $this->Mailer = "mail"; 256 } 257 258 /** 259 * Sets Mailer to send message using the $Sendmail program. 260 * @return void 261 */ 262 function IsSendmail() { 263 $this->Mailer = "sendmail"; 264 } 265 266 /** 267 * Sets Mailer to send message using the qmail MTA. 268 * @return void 269 */ 270 function IsQmail() { 271 $this->Sendmail = "/var/qmail/bin/sendmail"; 272 $this->Mailer = "sendmail"; 273 } 274 275 276 ///////////////////////////////////////////////// 277 // RECIPIENT METHODS 278 ///////////////////////////////////////////////// 279 280 /** 281 * Adds a "To" address. 282 * @param string $address 283 * @param string $name 284 * @return void 285 */ 286 function AddAddress($address, $name = "") { 287 $cur = count($this->to); 288 $this->to[$cur][0] = trim($address); 289 $this->to[$cur][1] = $name; 290 } 291 292 /** 293 * Adds a "Cc" address. Note: this function works 294 * with the SMTP mailer on win32, not with the "mail" 295 * mailer. 296 * @param string $address 297 * @param string $name 298 * @return void 299 */ 300 function AddCC($address, $name = "") { 301 $cur = count($this->cc); 302 $this->cc[$cur][0] = trim($address); 303 $this->cc[$cur][1] = $name; 304 } 305 306 /** 307 * Adds a "Bcc" address. Note: this function works 308 * with the SMTP mailer on win32, not with the "mail" 309 * mailer. 310 * @param string $address 311 * @param string $name 312 * @return void 313 */ 314 function AddBCC($address, $name = "") { 315 $cur = count($this->bcc); 316 $this->bcc[$cur][0] = trim($address); 317 $this->bcc[$cur][1] = $name; 318 } 319 320 /** 321 * Adds a "Reply-to" address. 322 * @param string $address 323 * @param string $name 324 * @return void 325 */ 326 function AddReplyTo($address, $name = "") { 327 $cur = count($this->ReplyTo); 328 $this->ReplyTo[$cur][0] = trim($address); 329 $this->ReplyTo[$cur][1] = $name; 330 } 331 332 333 ///////////////////////////////////////////////// 334 // MAIL SENDING METHODS 335 ///////////////////////////////////////////////// 336 337 /** 338 * Creates message and assigns Mailer. If the message is 339 * not sent successfully then it returns false. Use the ErrorInfo 340 * variable to view description of the error. 341 * @return bool 342 */ 343 function Send() { 344 $header = ""; 345 $body = ""; 346 $result = true; 347 348 if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) 349 { 350 $this->SetError($this->Lang("provide_address")); 351 return false; 352 } 353 354 // Set whether the message is multipart/alternative 355 if(!empty($this->AltBody)) 356 $this->ContentType = "multipart/alternative"; 357 358 $this->error_count = 0; // reset errors 359 $this->SetMessageType(); 360 $header .= $this->CreateHeader(); 361 $body = $this->CreateBody(); 362 363 if($body == "") { return false; } 364 365 // Choose the mailer 366 switch($this->Mailer) 367 { 368 case "sendmail": 369 $result = $this->SendmailSend($header, $body); 370 break; 371 case "mail": 372 $result = $this->MailSend($header, $body); 373 break; 374 case "smtp": 375 $result = $this->SmtpSend($header, $body); 376 break; 377 default: 378 $this->SetError($this->Mailer . $this->Lang("mailer_not_supported")); 379 $result = false; 380 break; 381 } 382 383 return $result; 384 } 385 386 /** 387 * Sends mail using the $Sendmail program. 388 * @access private 389 * @return bool 390 */ 391 function SendmailSend($header, $body) { 392 if ($this->Sender != "") 393 $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellcmd($this->Sender)); 394 else 395 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); 396 397 if(!@$mail = popen($sendmail, "w")) 398 { 399 $this->SetError($this->Lang("execute") . $this->Sendmail); 400 return false; 401 } 402 403 fputs($mail, $header); 404 fputs($mail, $body); 405 406 $result = pclose($mail) >> 8 & 0xFF; 407 if($result != 0) 408 { 409 $this->SetError($this->Lang("execute") . $this->Sendmail); 410 return false; 411 } 412 413 return true; 414 } 415 416 /** 417 * Sends mail using the PHP mail() function. 418 * @access private 419 * @return bool 420 */ 421 function MailSend($header, $body) { 422 $to = ""; 423 for($i = 0; $i < count($this->to); $i++) 424 { 425 if($i != 0) { $to .= ", "; } 426 $to .= $this->to[$i][0]; 427 } 428 429 if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1) 430 { 431 $old_from = ini_get("sendmail_from"); 432 ini_set("sendmail_from", $this->Sender); 433 $params = sprintf("-oi -f %s", $this->Sender); 434 $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, 435 $header, $params); 436 } 437 else 438 $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header); 439 440 if (isset($old_from)) 441 ini_set("sendmail_from", $old_from); 442 443 if(!$rt) 444 { 445 $this->SetError($this->Lang("instantiate")); 446 return false; 447 } 448 449 return true; 450 } 451 452 /** 453 * Sends mail via SMTP using PhpSMTP (Author: 454 * Chris Ryan). Returns bool. Returns false if there is a 455 * bad MAIL FROM, RCPT, or DATA input. 456 * @access private 457 * @return bool 458 */ 459 function SmtpSend($header, $body) { 460 include_once($this->PluginDir . "class.smtp.php"); 461 $error = ""; 462 $bad_rcpt = array(); 463 464 if(!$this->SmtpConnect()) 465 return false; 466 467 $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender; 468 if(!$this->smtp->Mail($smtp_from)) 469 { 470 $error = $this->Lang("from_failed") . $smtp_from; 471 $this->SetError($error); 472 $this->smtp->Reset(); 473 return false; 474 } 475 476 // Attempt to send attach all recipients 477 for($i = 0; $i < count($this->to); $i++) 478 { 479 if(!$this->smtp->Recipient($this->to[$i][0])) 480 $bad_rcpt[] = $this->to[$i][0]; 481 } 482 for($i = 0; $i < count($this->cc); $i++) 483 { 484 if(!$this->smtp->Recipient($this->cc[$i][0])) 485 $bad_rcpt[] = $this->cc[$i][0]; 486 } 487 for($i = 0; $i < count($this->bcc); $i++) 488 { 489 if(!$this->smtp->Recipient($this->bcc[$i][0])) 490 $bad_rcpt[] = $this->bcc[$i][0]; 491 } 492 493 if(count($bad_rcpt) > 0) // Create error message 494 { 495 for($i = 0; $i < count($bad_rcpt); $i++) 496 { 497 if($i != 0) { $error .= ", "; } 498 $error .= $bad_rcpt[$i]; 499 } 500 $error = $this->Lang("recipients_failed") . $error; 501 $this->SetError($error); 502 $this->smtp->Reset(); 503 return false; 504 } 505 506 if(!$this->smtp->Data($header . $body)) 507 { 508 $this->SetError($this->Lang("data_not_accepted")); 509 $this->smtp->Reset(); 510 return false; 511 } 512 if($this->SMTPKeepAlive == true) 513 $this->smtp->Reset(); 514 else 515 $this->SmtpClose(); 516 517 return true; 518 } 519 520 /** 521 * Initiates a connection to an SMTP server. Returns false if the 522 * operation failed. 523 * @access private 524 * @return bool 525 */ 526 function SmtpConnect() { 527 if($this->smtp == NULL) { $this->smtp = new SMTP(); } 528 529 $this->smtp->do_debug = $this->SMTPDebug; 530 $hosts = explode(";", $this->Host); 531 $index = 0; 532 $connection = ($this->smtp->Connected()); 533 534 // Retry while there is no connection 535 while($index < count($hosts) && $connection == false) 536 { 537 if(strstr($hosts[$index], ":")) 538 { 539 #list($host, $port) = explode(":", $hosts[$index]); 540 // Prasad: support for host's like ssl://smtp.gmail.com:465 541 $hostA = explode(':', $hosts[$index]); 542 if (is_numeric(end($hostA))) 543 $port = array_pop($hostA); 544 else 545 $port = $this->Port; 546 $host = implode(':', $hostA); 547 } 548 else 549 { 550 $host = $hosts[$index]; 551 $port = $this->Port; 552 } 553 554 if($this->smtp->Connect($host, $port, $this->Timeout)) 555 { 556 if ($this->Helo != '') 557 $this->smtp->Hello($this->Helo); 558 else 559 $this->smtp->Hello($this->ServerHostname()); 560 561 if($this->SMTPAuth) 562 { 563 if(!$this->smtp->Authenticate($this->Username, 564 $this->Password)) 565 { 566 $this->SetError($this->Lang("authenticate")); 567 $this->smtp->Reset(); 568 $connection = false; 569 } 570 } 571 $connection = true; 572 } 573 $index++; 574 } 575 if(!$connection) 576 $this->SetError($this->Lang("connect_host")); 577 578 return $connection; 579 } 580 581 /** 582 * Closes the active SMTP session if one exists. 583 * @return void 584 */ 585 function SmtpClose() { 586 if($this->smtp != NULL) 587 { 588 if($this->smtp->Connected()) 589 { 590 $this->smtp->Quit(); 591 $this->smtp->Close(); 592 } 593 } 594 } 595 596 /** 597 * Sets the language for all class error messages. Returns false 598 * if it cannot load the language file. The default language type 599 * is English. 600 * @param string $lang_type Type of language (e.g. Portuguese: "br") 601 * @param string $lang_path Path to the language file directory 602 * @access public 603 * @return bool 604 */ 605 function SetLanguage($lang_type, $lang_path = "language/") { 606 global $root_directory; 607 if(file_exists($root_directory.'/cron/'.$lang_path.'phpmailer.lang-'.$lang_type.'.php')) 608 include($root_directory.'/cron/'.$lang_path.'phpmailer.lang-'.$lang_type.'.php'); 609 else if($root_directory.'/cron/'.file_exists($lang_path.'phpmailer.lang-en.php')) 610 include($root_directory.'/cron/'.$lang_path.'phpmailer.lang-en.php'); 611 else 612 { 613 $this->SetError("Could not load language file"); 614 return false; 615 } 616 $this->language = $PHPMAILER_LANG; 617 618 return true; 619 } 620 621 ///////////////////////////////////////////////// 622 // MESSAGE CREATION METHODS 623 ///////////////////////////////////////////////// 624 625 /** 626 * Creates recipient headers. 627 * @access private 628 * @return string 629 */ 630 function AddrAppend($type, $addr) { 631 $addr_str = $type . ": "; 632 $addr_str .= $this->AddrFormat($addr[0]); 633 if(count($addr) > 1) 634 { 635 for($i = 1; $i < count($addr); $i++) 636 $addr_str .= ", " . $this->AddrFormat($addr[$i]); 637 } 638 $addr_str .= $this->LE; 639 640 return $addr_str; 641 } 642 643 /** 644 * Formats an address correctly. 645 * @access private 646 * @return string 647 */ 648 function AddrFormat($addr) { 649 if(empty($addr[1])) 650 $formatted = $addr[0]; 651 else 652 { 653 $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" . 654 $addr[0] . ">"; 655 } 656 657 return $formatted; 658 } 659 660 /** 661 * Wraps message for use with mailers that do not 662 * automatically perform wrapping and for quoted-printable. 663 * Original written by philippe. 664 * @access private 665 * @return string 666 */ 667 function WrapText($message, $length, $qp_mode = false) { 668 $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; 669 670 $message = $this->FixEOL($message); 671 if (substr($message, -1) == $this->LE) 672 $message = substr($message, 0, -1); 673 674 $line = explode($this->LE, $message); 675 $message = ""; 676 for ($i=0 ;$i < count($line); $i++) 677 { 678 $line_part = explode(" ", $line[$i]); 679 $buf = ""; 680 for ($e = 0; $e<count($line_part); $e++) 681 { 682 $word = $line_part[$e]; 683 if ($qp_mode and (strlen($word) > $length)) 684 { 685 $space_left = $length - strlen($buf) - 1; 686 if ($e != 0) 687 { 688 if ($space_left > 20) 689 { 690 $len = $space_left; 691 if (substr($word, $len - 1, 1) == "=") 692 $len--; 693 elseif (substr($word, $len - 2, 1) == "=") 694 $len -= 2; 695 $part = substr($word, 0, $len); 696 $word = substr($word, $len); 697 $buf .= " " . $part; 698 $message .= $buf . sprintf("=%s", $this->LE); 699 } 700 else 701 { 702 $message .= $buf . $soft_break; 703 } 704 $buf = ""; 705 } 706 while (strlen($word) > 0) 707 { 708 $len = $length; 709 if (substr($word, $len - 1, 1) == "=") 710 $len--; 711 elseif (substr($word, $len - 2, 1) == "=") 712 $len -= 2; 713 $part = substr($word, 0, $len); 714 $word = substr($word, $len); 715 716 if (strlen($word) > 0) 717 $message .= $part . sprintf("=%s", $this->LE); 718 else 719 $buf = $part; 720 } 721 } 722 else 723 { 724 $buf_o = $buf; 725 $buf .= ($e == 0) ? $word : (" " . $word); 726 727 if (strlen($buf) > $length and $buf_o != "") 728 { 729 $message .= $buf_o . $soft_break; 730 $buf = $word; 731 } 732 } 733 } 734 $message .= $buf . $this->LE; 735 } 736 737 return $message; 738 } 739 740 /** 741 * Set the body wrapping. 742 * @access private 743 * @return void 744 */ 745 function SetWordWrap() { 746 if($this->WordWrap < 1) 747 return; 748 749 switch($this->message_type) 750 { 751 case "alt": 752 // fall through 753 case "alt_attachment": 754 $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); 755 break; 756 default: 757 $this->Body = $this->WrapText($this->Body, $this->WordWrap); 758 break; 759 } 760 } 761 762 /** 763 * Assembles message header. 764 * @access private 765 * @return string 766 */ 767 function CreateHeader() { 768 $result = ""; 769 770 // Set the boundaries 771 $uniq_id = md5(uniqid(time())); 772 $this->boundary[1] = "b1_" . $uniq_id; 773 $this->boundary[2] = "b2_" . $uniq_id; 774 775 $result .= $this->HeaderLine("Date", $this->RFCDate()); 776 if($this->Sender == "") 777 $result .= $this->HeaderLine("Return-Path", trim($this->From)); 778 else 779 $result .= $this->HeaderLine("Return-Path", trim($this->Sender)); 780 781 // To be created automatically by mail() 782 if($this->Mailer != "mail") 783 { 784 if(count($this->to) > 0) 785 $result .= $this->AddrAppend("To", $this->to); 786 else if (count($this->cc) == 0) 787 $result .= $this->HeaderLine("To", "undisclosed-recipients:;"); 788 if(count($this->cc) > 0) 789 $result .= $this->AddrAppend("Cc", $this->cc); 790 } 791 792 $from = array(); 793 $from[0][0] = trim($this->From); 794 $from[0][1] = $this->FromName; 795 $result .= $this->AddrAppend("From", $from); 796 797 // sendmail and mail() extract Bcc from the header before sending 798 if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0)) 799 $result .= $this->AddrAppend("Bcc", $this->bcc); 800 801 if(count($this->ReplyTo) > 0) 802 $result .= $this->AddrAppend("Reply-to", $this->ReplyTo); 803 804 // mail() sets the subject itself 805 if($this->Mailer != "mail") 806 $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject))); 807 808 $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); 809 $result .= $this->HeaderLine("X-Priority", $this->Priority); 810 $result .= $this->HeaderLine("X-Mailer", "PHPMailer [version " . $this->Version . "]"); 811 812 if($this->ConfirmReadingTo != "") 813 { 814 $result .= $this->HeaderLine("Disposition-Notification-To", 815 "<" . trim($this->ConfirmReadingTo) . ">"); 816 } 817 818 // Add custom headers 819 for($index = 0; $index < count($this->CustomHeader); $index++) 820 { 821 $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), 822 $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); 823 } 824 $result .= $this->HeaderLine("MIME-Version", "1.0"); 825 826 switch($this->message_type) 827 { 828 case "plain": 829 $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding); 830 $result .= sprintf("Content-Type: %s; charset=\"%s\"", 831 $this->ContentType, $this->CharSet); 832 break; 833 case "attachments": 834 // fall through 835 case "alt_attachments": 836 if($this->InlineImageExists()) 837 { 838 $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 839 "multipart/related", $this->LE, $this->LE, 840 $this->boundary[1], $this->LE); 841 } 842 else 843 { 844 $result .= $this->HeaderLine("Content-Type", "multipart/mixed;"); 845 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); 846 } 847 break; 848 case "alt": 849 $result .= $this->HeaderLine("Content-Type", "multipart/alternative;"); 850 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); 851 break; 852 } 853 854 if($this->Mailer != "mail") 855 $result .= $this->LE.$this->LE; 856 857 return $result; 858 } 859 860 /** 861 * Assembles the message body. Returns an empty string on failure. 862 * @access private 863 * @return string 864 */ 865 function CreateBody() { 866 $result = ""; 867 868 $this->SetWordWrap(); 869 870 switch($this->message_type) 871 { 872 case "alt": 873 $result .= $this->GetBoundary($this->boundary[1], "", 874 "text/plain", ""); 875 $result .= $this->EncodeString($this->AltBody, $this->Encoding); 876 $result .= $this->LE.$this->LE; 877 $result .= $this->GetBoundary($this->boundary[1], "", 878 "text/html", ""); 879 880 $result .= $this->EncodeString($this->Body, $this->Encoding); 881 $result .= $this->LE.$this->LE; 882 883 $result .= $this->EndBoundary($this->boundary[1]); 884 break; 885 case "plain": 886 $result .= $this->EncodeString($this->Body, $this->Encoding); 887 break; 888 case "attachments": 889 $result .= $this->GetBoundary($this->boundary[1], "", "", ""); 890 $result .= $this->EncodeString($this->Body, $this->Encoding); 891 $result .= $this->LE; 892 893 $result .= $this->AttachAll(); 894 break; 895 case "alt_attachments": 896 $result .= sprintf("--%s%s", $this->boundary[1], $this->LE); 897 $result .= sprintf("Content-Type: %s;%s" . 898 "\tboundary=\"%s\"%s", 899 "multipart/alternative", $this->LE, 900 $this->boundary[2], $this->LE.$this->LE); 901 902 // Create text body 903 $result .= $this->GetBoundary($this->boundary[2], "", 904 "text/plain", "") . $this->LE; 905 906 $result .= $this->EncodeString($this->AltBody, $this->Encoding); 907 $result .= $this->LE.$this->LE; 908 909 // Create the HTML body 910 $result .= $this->GetBoundary($this->boundary[2], "", 911 "text/html", "") . $this->LE; 912 913 $result .= $this->EncodeString($this->Body, $this->Encoding); 914 $result .= $this->LE.$this->LE; 915 916 $result .= $this->EndBoundary($this->boundary[2]); 917 918 $result .= $this->AttachAll(); 919 break; 920 } 921 if($this->IsError()) 922 $result = ""; 923 924 return $result; 925 } 926 927 /** 928 * Returns the start of a message boundary. 929 * @access private 930 */ 931 function GetBoundary($boundary, $charSet, $contentType, $encoding) { 932 $result = ""; 933 if($charSet == "") { $charSet = $this->CharSet; } 934 if($contentType == "") { $contentType = $this->ContentType; } 935 if($encoding == "") { $encoding = $this->Encoding; } 936 937 $result .= $this->TextLine("--" . $boundary); 938 $result .= sprintf("Content-Type: %s; charset = \"%s\"", 939 $contentType, $charSet); 940 $result .= $this->LE; 941 $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding); 942 $result .= $this->LE; 943 944 return $result; 945 } 946 947 /** 948 * Returns the end of a message boundary. 949 * @access private 950 */ 951 function EndBoundary($boundary) { 952 return $this->LE . "--" . $boundary . "--" . $this->LE; 953 } 954 955 /** 956 * Sets the message type. 957 * @access private 958 * @return void 959 */ 960 function SetMessageType() { 961 if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) 962 $this->message_type = "plain"; 963 else 964 { 965 if(count($this->attachment) > 0) 966 $this->message_type = "attachments"; 967 if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) 968 $this->message_type = "alt"; 969 if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) 970 $this->message_type = "alt_attachments"; 971 } 972 } 973 974 /** 975 * Returns a formatted header line. 976 * @access private 977 * @return string 978 */ 979 function HeaderLine($name, $value) { 980 return $name . ": " . $value . $this->LE; 981 } 982 983 /** 984 * Returns a formatted mail line. 985 * @access private 986 * @return string 987 */ 988 function TextLine($value) { 989 return $value . $this->LE; 990 } 991 992 ///////////////////////////////////////////////// 993 // ATTACHMENT METHODS 994 ///////////////////////////////////////////////// 995 996 /** 997 * Adds an attachment from a path on the filesystem. 998 * Returns false if the file could not be found 999 * or accessed. 1000 * @param string $path Path to the attachment. 1001 * @param string $name Overrides the attachment name. 1002 * @param string $encoding File encoding (see $Encoding). 1003 * @param string $type File extension (MIME) type. 1004 * @return bool 1005 */ 1006 function AddAttachment($path, $name = "", $encoding = "base64", 1007 $type = "application/octet-stream") { 1008 if(!@is_file($path)) 1009 { 1010 $this->SetError($this->Lang("file_access") . $path); 1011 return false; 1012 } 1013 1014 $filename = basename($path); 1015 if($name == "") 1016 $name = $filename; 1017 1018 $cur = count($this->attachment); 1019 $this->attachment[$cur][0] = $path; 1020 $this->attachment[$cur][1] = $filename; 1021 $this->attachment[$cur][2] = $name; 1022 $this->attachment[$cur][3] = $encoding; 1023 $this->attachment[$cur][4] = $type; 1024 $this->attachment[$cur][5] = false; // isStringAttachment 1025 $this->attachment[$cur][6] = "attachment"; 1026 $this->attachment[$cur][7] = 0; 1027 1028 return true; 1029 } 1030 1031 /** 1032 * Attaches all fs, string, and binary attachments to the message. 1033 * Returns an empty string on failure. 1034 * @access private 1035 * @return string 1036 */ 1037 function AttachAll() { 1038 // Return text of body 1039 $mime = array(); 1040 1041 // Add all attachments 1042 for($i = 0; $i < count($this->attachment); $i++) 1043 { 1044 // Check for string attachment 1045 $bString = $this->attachment[$i][5]; 1046 if ($bString) 1047 $string = $this->attachment[$i][0]; 1048 else 1049 $path = $this->attachment[$i][0]; 1050 1051 $filename = $this->attachment[$i][1]; 1052 $name = $this->attachment[$i][2]; 1053 $encoding = $this->attachment[$i][3]; 1054 $type = $this->attachment[$i][4]; 1055 $disposition = $this->attachment[$i][6]; 1056 $cid = $this->attachment[$i][7]; 1057 1058 $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); 1059 $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE); 1060 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); 1061 1062 if($disposition == "inline") 1063 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); 1064 1065 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", 1066 $disposition, $name, $this->LE.$this->LE); 1067 1068 // Encode as string attachment 1069 if($bString) 1070 { 1071 $mime[] = $this->EncodeString($string, $encoding); 1072 if($this->IsError()) { return ""; } 1073 $mime[] = $this->LE.$this->LE; 1074 } 1075 else 1076 { 1077 $mime[] = $this->EncodeFile($path, $encoding); 1078 if($this->IsError()) { return ""; } 1079 $mime[] = $this->LE.$this->LE; 1080 } 1081 } 1082 1083 $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); 1084 1085 return join("", $mime); 1086 } 1087 1088 /** 1089 * Encodes attachment in requested format. Returns an 1090 * empty string on failure. 1091 * @access private 1092 * @return string 1093 */ 1094 function EncodeFile ($path, $encoding = "base64") { 1095 if(!@$fd = fopen($path, "rb")) 1096 { 1097 $this->SetError($this->Lang("file_open") . $path); 1098 return ""; 1099 } 1100 if(!@$file_buffer = fread($fd, filesize($path))) 1101 { 1102 // $this->SetError($this->Lang("file_open") . $path); 1103 // return ""; 1104 } 1105 $file_buffer = $this->EncodeString($file_buffer, $encoding); 1106 fclose($fd); 1107 1108 return $file_buffer; 1109 } 1110 1111 /** 1112 * Encodes string to requested format. Returns an 1113 * empty string on failure. 1114 * @access private 1115 * @return string 1116 */ 1117 function EncodeString ($str, $encoding = "base64") { 1118 $encoded = ""; 1119 switch(strtolower($encoding)) { 1120 case "base64": 1121 // chunk_split is found in PHP >= 3.0.6 1122 $encoded = chunk_split(base64_encode($str), 76, $this->LE); 1123 break; 1124 case "7bit": 1125 case "8bit": 1126 $encoded = $this->FixEOL($str); 1127 if (substr($encoded, -(strlen($this->LE))) != $this->LE) 1128 $encoded .= $this->LE; 1129 break; 1130 case "binary": 1131 $encoded = $str; 1132 break; 1133 case "quoted-printable": 1134 $encoded = $this->EncodeQP($str); 1135 break; 1136 default: 1137 $this->SetError($this->Lang("encoding") . $encoding); 1138 break; 1139 } 1140 return $encoded; 1141 } 1142 1143 /** 1144 * Encode a header string to best of Q, B, quoted or none. 1145 * @access private 1146 * @return string 1147 */ 1148 function EncodeHeader ($str, $position = 'text') { 1149 $x = 0; 1150 1151 switch (strtolower($position)) { 1152 case 'phrase': 1153 if (!preg_match('/[\200-\377]/', $str)) { 1154 // Can't use addslashes as we don't know what value has magic_quotes_sybase. 1155 $encoded = addcslashes($str, "\0..\37\177\\\""); 1156 1157 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) 1158 return ($encoded); 1159 else 1160 return ("\"$encoded\""); 1161 } 1162 $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); 1163 break; 1164 case 'comment': 1165 $x = preg_match_all('/[()"]/', $str, $matches); 1166 // Fall-through 1167 case 'text': 1168 default: 1169 $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); 1170 break; 1171 } 1172 1173 if ($x == 0) 1174 return ($str); 1175 1176 $maxlen = 75 - 7 - strlen($this->CharSet); 1177 // Try to select the encoding which should produce the shortest output 1178 if (strlen($str)/3 < $x) { 1179 $encoding = 'B'; 1180 $encoded = base64_encode($str); 1181 $maxlen -= $maxlen % 4; 1182 $encoded = trim(chunk_split($encoded, $maxlen, "\n")); 1183 } else { 1184 $encoding = 'Q'; 1185 $encoded = $this->EncodeQ($str, $position); 1186 $encoded = $this->WrapText($encoded, $maxlen, true); 1187 $encoded = str_replace("=".$this->LE, "\n", trim($encoded)); 1188 } 1189 1190 $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); 1191 $encoded = trim(str_replace("\n", $this->LE, $encoded)); 1192 1193 return $encoded; 1194 } 1195 1196 /** 1197 * Encode string to quoted-printable. 1198 * @access private 1199 * @return string 1200 */ 1201 function EncodeQP ($str) { 1202 $encoded = $this->FixEOL($str); 1203 if (substr($encoded, -(strlen($this->LE))) != $this->LE) 1204 $encoded .= $this->LE; 1205 1206 // Replace every high ascii, control and = characters 1207 $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e', 1208 "'='.sprintf('%02X', ord('\\1'))", $encoded); 1209 // Replace every spaces and tabs when it's the last character on a line 1210 $encoded = preg_replace("/([\011\040])".$this->LE."/e", 1211 "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded); 1212 1213 // Maximum line length of 76 characters before CRLF (74 + space + '=') 1214 $encoded = $this->WrapText($encoded, 74, true); 1215 1216 return $encoded; 1217 } 1218 1219 /** 1220 * Encode string to q encoding. 1221 * @access private 1222 * @return string 1223 */ 1224 function EncodeQ ($str, $position = "text") { 1225 // There should not be any EOL in the string 1226 $encoded = preg_replace("[\r\n]", "", $str); 1227 1228 switch (strtolower($position)) { 1229 case "phrase": 1230 $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1231 break; 1232 case "comment": 1233 $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); 1234 case "text": 1235 default: 1236 // Replace every high ascii, control =, ? and _ characters 1237 $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', 1238 "'='.sprintf('%02X', ord('\\1'))", $encoded); 1239 break; 1240 } 1241 1242 // Replace every spaces to _ (more readable than =20) 1243 $encoded = str_replace(" ", "_", $encoded); 1244 1245 return $encoded; 1246 } 1247 1248 /** 1249 * Adds a string or binary attachment (non-filesystem) to the list. 1250 * This method can be used to attach ascii or binary data, 1251 * such as a BLOB record from a database. 1252 * @param string $string String attachment data. 1253 * @param string $filename Name of the attachment. 1254 * @param string $encoding File encoding (see $Encoding). 1255 * @param string $type File extension (MIME) type. 1256 * @return void 1257 */ 1258 function AddStringAttachment($string, $filename, $encoding = "base64", 1259 $type = "application/octet-stream") { 1260 // Append to $attachment array 1261 $cur = count($this->attachment); 1262 $this->attachment[$cur][0] = $string; 1263 $this->attachment[$cur][1] = $filename; 1264 $this->attachment[$cur][2] = $filename; 1265 $this->attachment[$cur][3] = $encoding; 1266 $this->attachment[$cur][4] = $type; 1267 $this->attachment[$cur][5] = true; // isString 1268 $this->attachment[$cur][6] = "attachment"; 1269 $this->attachment[$cur][7] = 0; 1270 } 1271 1272 /** 1273 * Adds an embedded attachment. This can include images, sounds, and 1274 * just about any other document. Make sure to set the $type to an 1275 * image type. For JPEG images use "image/jpeg" and for GIF images 1276 * use "image/gif". 1277 * @param string $path Path to the attachment. 1278 * @param string $cid Content ID of the attachment. Use this to identify 1279 * the Id for accessing the image in an HTML form. 1280 * @param string $name Overrides the attachment name. 1281 * @param string $encoding File encoding (see $Encoding). 1282 * @param string $type File extension (MIME) type. 1283 * @return bool 1284 */ 1285 function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64", 1286 $type = "application/octet-stream") { 1287 1288 if(!@is_file($path)) 1289 { 1290 $this->SetError($this->Lang("file_access") . $path); 1291 return false; 1292 } 1293 1294 $filename = basename($path); 1295 if($name == "") 1296 $name = $filename; 1297 1298 // Append to $attachment array 1299 $cur = count($this->attachment); 1300 $this->attachment[$cur][0] = $path; 1301 $this->attachment[$cur][1] = $filename; 1302 $this->attachment[$cur][2] = $name; 1303 $this->attachment[$cur][3] = $encoding; 1304 $this->attachment[$cur][4] = $type; 1305 $this->attachment[$cur][5] = false; // isStringAttachment 1306 $this->attachment[$cur][6] = "inline"; 1307 $this->attachment[$cur][7] = $cid; 1308 1309 return true; 1310 } 1311 1312 /** 1313 * Returns true if an inline attachment is present. 1314 * @access private 1315 * @return bool 1316 */ 1317 function InlineImageExists() { 1318 $result = false; 1319 for($i = 0; $i < count($this->attachment); $i++) 1320 { 1321 if($this->attachment[$i][6] == "inline") 1322 { 1323 $result = true; 1324 break; 1325 } 1326 } 1327 1328 return $result; 1329 } 1330 1331 ///////////////////////////////////////////////// 1332 // MESSAGE RESET METHODS 1333 ///////////////////////////////////////////////// 1334 1335 /** 1336 * Clears all recipients assigned in the TO array. Returns void. 1337 * @return void 1338 */ 1339 function ClearAddresses() { 1340 $this->to = array(); 1341 } 1342 1343 /** 1344 * Clears all recipients assigned in the CC array. Returns void. 1345 * @return void 1346 */ 1347 function ClearCCs() { 1348 $this->cc = array(); 1349 } 1350 1351 /** 1352 * Clears all recipients assigned in the BCC array. Returns void. 1353 * @return void 1354 */ 1355 function ClearBCCs() { 1356 $this->bcc = array(); 1357 } 1358 1359 /** 1360 * Clears all recipients assigned in the ReplyTo array. Returns void. 1361 * @return void 1362 */ 1363 function ClearReplyTos() { 1364 $this->ReplyTo = array(); 1365 } 1366 1367 /** 1368 * Clears all recipients assigned in the TO, CC and BCC 1369 * array. Returns void. 1370 * @return void 1371 */ 1372 function ClearAllRecipients() { 1373 $this->to = array(); 1374 $this->cc = array(); 1375 $this->bcc = array(); 1376 } 1377 1378 /** 1379 * Clears all previously set filesystem, string, and binary 1380 * attachments. Returns void. 1381 * @return void 1382 */ 1383 function ClearAttachments() { 1384 $this->attachment = array(); 1385 } 1386 1387 /** 1388 * Clears all custom headers. Returns void. 1389 * @return void 1390 */ 1391 function ClearCustomHeaders() { 1392 $this->CustomHeader = array(); 1393 } 1394 1395 1396 ///////////////////////////////////////////////// 1397 // MISCELLANEOUS METHODS 1398 ///////////////////////////////////////////////// 1399 1400 /** 1401 * Adds the error message to the error container. 1402 * Returns void. 1403 * @access private 1404 * @return void 1405 */ 1406 function SetError($msg) { 1407 $this->error_count++; 1408 $this->ErrorInfo = $msg; 1409 } 1410 1411 /** 1412 * Returns the proper RFC 822 formatted date. 1413 * @access private 1414 * @return string 1415 */ 1416 function RFCDate() { 1417 $tz = date("Z"); 1418 $tzs = ($tz < 0) ? "-" : "+"; 1419 $tz = abs($tz); 1420 $tz = ($tz/3600)*100 + ($tz%3600)/60; 1421 $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz); 1422 1423 return $result; 1424 } 1425 1426 /** 1427 * Returns the appropriate server variable. Should work with both 1428 * PHP 4.1.0+ as well as older versions. Returns an empty string 1429 * if nothing is found. 1430 * @access private 1431 * @return mixed 1432 */ 1433 function ServerVar($varName) { 1434 global $HTTP_SERVER_VARS; 1435 global $HTTP_ENV_VARS; 1436 1437 if(!isset($_SERVER)) 1438 { 1439 $_SERVER = $HTTP_SERVER_VARS; 1440 if(!isset($_SERVER["REMOTE_ADDR"])) 1441 $_SERVER = $HTTP_ENV_VARS; // must be Apache 1442 } 1443 1444 if(isset($_SERVER[$varName])) 1445 return $_SERVER[$varName]; 1446 else 1447 return ""; 1448 } 1449 1450 /** 1451 * Returns the server hostname or 'localhost.localdomain' if unknown. 1452 * @access private 1453 * @return string 1454 */ 1455 function ServerHostname() { 1456 if ($this->Hostname != "") 1457 $result = $this->Hostname; 1458 elseif ($this->ServerVar('SERVER_NAME') != "") 1459 $result = $this->ServerVar('SERVER_NAME'); 1460 else 1461 $result = "localhost.localdomain"; 1462 1463 return $result; 1464 } 1465 1466 /** 1467 * Returns a message in the appropriate language. 1468 * @access private 1469 * @return string 1470 */ 1471 function Lang($key) { 1472 if(count($this->language) < 1) 1473 $this->SetLanguage("en"); // set the default language 1474 1475 if(isset($this->language[$key])) 1476 return $this->language[$key]; 1477 else 1478 return "Language string failed to load: " . $key; 1479 } 1480 1481 /** 1482 * Returns true if an error occurred. 1483 * @return bool 1484 */ 1485 function IsError() { 1486 return ($this->error_count > 0); 1487 } 1488 1489 /** 1490 * Changes every end of line from CR or LF to CRLF. 1491 * @access private 1492 * @return string 1493 */ 1494 function FixEOL($str) { 1495 $str = str_replace("\r\n", "\n", $str); 1496 $str = str_replace("\r", "\n", $str); 1497 $str = str_replace("\n", $this->LE, $str); 1498 return $str; 1499 } 1500 1501 /** 1502 * Adds a custom header. 1503 * @return void 1504 */ 1505 function AddCustomHeader($custom_header) { 1506 $this->CustomHeader[] = explode(":", $custom_header, 2); 1507 } 1508 } 1509 1510 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |