[ Index ]

PHP Cross Reference of Wordpress 2.9.1

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


Generated: Fri Jan 8 00:19:48 2010 Cross-referenced by PHPXref 0.7