[ Index ]

PHP Cross Reference of Wordpress MU 2.7

title

Body

[close]

/wp-includes/ -> class-phpmailer.php (source)

   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  ?>


Generated: Thu Mar 5 12:05:07 2009 Cross-referenced by PHPXref 0.7