PageRenderTime 89ms CodeModel.GetById 20ms app.highlight 56ms RepoModel.GetById 1ms app.codeStats 1ms

/libraries/phpmailer/phpmailer.php

https://bitbucket.org/asosso/joomla25
PHP | 2532 lines | 1744 code | 171 blank | 617 comment | 262 complexity | fc19291526ca41be0174feb8f8d04f02 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/*~ class.phpmailer.php
   3.---------------------------------------------------------------------------.
   4|  Software: PHPMailer - PHP email class                                    |
   5|   Version: 5.2.1                                                          |
   6|      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
   7| ------------------------------------------------------------------------- |
   8|     Admin: Jim Jagielski (project admininistrator)                        |
   9|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
  10|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
  11|          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
  12|   Founder: Brent R. Matzelle (original founder)                           |
  13| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved.              |
  14| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
  15| Copyright (c) 2001-2003, Brent R. Matzelle                                |
  16| ------------------------------------------------------------------------- |
  17|   License: Distributed under the Lesser General Public License (LGPL)     |
  18|            http://www.gnu.org/copyleft/lesser.html                        |
  19| This program is distributed in the hope that it will be useful - WITHOUT  |
  20| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
  21| FITNESS FOR A PARTICULAR PURPOSE.                                         |
  22'---------------------------------------------------------------------------'
  23*/
  24
  25/**
  26 * PHPMailer - PHP email transport class
  27 * NOTE: Requires PHP version 5 or later
  28 * @package PHPMailer
  29 * @author Andy Prevost
  30 * @author Marcus Bointon
  31 * @author Jim Jagielski
  32 * @copyright 2010 - 2013 Jim Jagielski
  33 * @copyright 2004 - 2009 Andy Prevost
  34 * @version $Id: class.phpmailer.php 450 2010-06-23 16:46:33Z coolbru $
  35 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  36 */
  37
  38if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
  39
  40class PHPMailer {
  41
  42  /////////////////////////////////////////////////
  43  // PROPERTIES, PUBLIC
  44  /////////////////////////////////////////////////
  45
  46  /**
  47   * Email priority (1 = High, 3 = Normal, 5 = low).
  48   * @var int
  49   */
  50  public $Priority          = 3;
  51
  52  /**
  53   * Sets the CharSet of the message.
  54   * @var string
  55   */
  56  public $CharSet           = 'iso-8859-1';
  57
  58  /**
  59   * Sets the Content-type of the message.
  60   * @var string
  61   */
  62  public $ContentType       = 'text/plain';
  63
  64  /**
  65   * Sets the Encoding of the message. Options for this are
  66   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
  67   * @var string
  68   */
  69  public $Encoding          = '8bit';
  70
  71  /**
  72   * Holds the most recent mailer error message.
  73   * @var string
  74   */
  75  public $ErrorInfo         = '';
  76
  77  /**
  78   * Sets the From email address for the message.
  79   * @var string
  80   */
  81  public $From              = 'root@localhost';
  82
  83  /**
  84   * Sets the From name of the message.
  85   * @var string
  86   */
  87  public $FromName          = 'Root User';
  88
  89  /**
  90   * Sets the Sender email (Return-Path) of the message.  If not empty,
  91   * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
  92   * @var string
  93   */
  94  public $Sender            = '';
  95
  96  /**
  97   * Sets the Subject of the message.
  98   * @var string
  99   */
 100  public $Subject           = '';
 101
 102  /**
 103   * Sets the Body of the message.  This can be either an HTML or text body.
 104   * If HTML then run IsHTML(true).
 105   * @var string
 106   */
 107  public $Body              = '';
 108
 109  /**
 110   * Sets the text-only body of the message.  This automatically sets the
 111   * email to multipart/alternative.  This body can be read by mail
 112   * clients that do not have HTML email capability such as mutt. Clients
 113   * that can read HTML will view the normal Body.
 114   * @var string
 115   */
 116  public $AltBody           = '';
 117
 118  /**
 119   * Stores the complete compiled MIME message body.
 120   * @var string
 121   * @access protected
 122   */
 123  protected $MIMEBody       = '';
 124
 125  /**
 126   * Stores the complete compiled MIME message headers.
 127   * @var string
 128   * @access protected
 129   */
 130  protected $MIMEHeader     = '';
 131
 132  /**
 133   * Stores the complete sent MIME message (Body and Headers)
 134   * @var string
 135   * @access protected
 136  */
 137  protected $SentMIMEMessage     = '';
 138
 139  /**
 140   * Sets word wrapping on the body of the message to a given number of
 141   * characters.
 142   * @var int
 143   */
 144  public $WordWrap          = 0;
 145
 146  /**
 147   * Method to send mail: ("mail", "sendmail", or "smtp").
 148   * @var string
 149   */
 150  public $Mailer            = 'mail';
 151
 152  /**
 153   * Sets the path of the sendmail program.
 154   * @var string
 155   */
 156  public $Sendmail          = '/usr/sbin/sendmail';
 157
 158  /**
 159   * Path to PHPMailer plugins.  Useful if the SMTP class
 160   * is in a different directory than the PHP include path.
 161   * @var string
 162   */
 163  public $PluginDir         = '';
 164
 165  /**
 166   * Sets the email address that a reading confirmation will be sent.
 167   * @var string
 168   */
 169  public $ConfirmReadingTo  = '';
 170
 171  /**
 172   * Sets the hostname to use in Message-Id and Received headers
 173   * and as default HELO string. If empty, the value returned
 174   * by SERVER_NAME is used or 'localhost.localdomain'.
 175   * @var string
 176   */
 177  public $Hostname          = '';
 178
 179  /**
 180   * Sets the message ID to be used in the Message-Id header.
 181   * If empty, a unique id will be generated.
 182   * @var string
 183   */
 184  public $MessageID         = '';
 185
 186  /////////////////////////////////////////////////
 187  // PROPERTIES FOR SMTP
 188  /////////////////////////////////////////////////
 189
 190  /**
 191   * Sets the SMTP hosts.  All hosts must be separated by a
 192   * semicolon.  You can also specify a different port
 193   * for each host by using this format: [hostname:port]
 194   * (e.g. "smtp1.example.com:25;smtp2.example.com").
 195   * Hosts will be tried in order.
 196   * @var string
 197   */
 198  public $Host          = 'localhost';
 199
 200  /**
 201   * Sets the default SMTP server port.
 202   * @var int
 203   */
 204  public $Port          = 25;
 205
 206  /**
 207   * Sets the SMTP HELO of the message (Default is $Hostname).
 208   * @var string
 209   */
 210  public $Helo          = '';
 211
 212  /**
 213   * Sets connection prefix.
 214   * Options are "", "ssl" or "tls"
 215   * @var string
 216   */
 217  public $SMTPSecure    = '';
 218
 219  /**
 220   * Sets SMTP authentication. Utilizes the Username and Password variables.
 221   * @var bool
 222   */
 223  public $SMTPAuth      = false;
 224
 225  /**
 226   * Sets SMTP username.
 227   * @var string
 228   */
 229  public $Username      = '';
 230
 231  /**
 232   * Sets SMTP password.
 233   * @var string
 234   */
 235  public $Password      = '';
 236
 237  /**
 238   * Sets the SMTP server timeout in seconds.
 239   * This function will not work with the win32 version.
 240   * @var int
 241   */
 242  public $Timeout       = 10;
 243
 244  /**
 245   * Sets SMTP class debugging on or off.
 246   * @var bool
 247   */
 248  public $SMTPDebug     = false;
 249
 250  /**
 251   * Prevents the SMTP connection from being closed after each mail
 252   * sending.  If this is set to true then to close the connection
 253   * requires an explicit call to SmtpClose().
 254   * @var bool
 255   */
 256  public $SMTPKeepAlive = false;
 257
 258  /**
 259   * Provides the ability to have the TO field process individual
 260   * emails, instead of sending to entire TO addresses
 261   * @var bool
 262   */
 263  public $SingleTo      = false;
 264
 265   /**
 266   * If SingleTo is true, this provides the array to hold the email addresses
 267   * @var bool
 268   */
 269  public $SingleToArray = array();
 270
 271 /**
 272   * Provides the ability to change the line ending
 273   * @var string
 274   */
 275  public $LE              = "\n";
 276
 277  /**
 278   * Used with DKIM DNS Resource Record
 279   * @var string
 280   */
 281  public $DKIM_selector   = 'phpmailer';
 282
 283  /**
 284   * Used with DKIM DNS Resource Record
 285   * optional, in format of email address 'you@yourdomain.com'
 286   * @var string
 287   */
 288  public $DKIM_identity   = '';
 289
 290  /**
 291   * Used with DKIM DNS Resource Record
 292   * @var string
 293   */
 294  public $DKIM_passphrase   = '';
 295
 296  /**
 297   * Used with DKIM DNS Resource Record
 298   * optional, in format of email address 'you@yourdomain.com'
 299   * @var string
 300   */
 301  public $DKIM_domain     = '';
 302
 303  /**
 304   * Used with DKIM DNS Resource Record
 305   * optional, in format of email address 'you@yourdomain.com'
 306   * @var string
 307   */
 308  public $DKIM_private    = '';
 309
 310  /**
 311   * Callback Action function name
 312   * the function that handles the result of the send email action. Parameters:
 313   *   bool    $result        result of the send action
 314   *   string  $to            email address of the recipient
 315   *   string  $cc            cc email addresses
 316   *   string  $bcc           bcc email addresses
 317   *   string  $subject       the subject
 318   *   string  $body          the email body
 319   * @var string
 320   */
 321  public $action_function = ''; //'callbackAction';
 322
 323  /**
 324   * Sets the PHPMailer Version number
 325   * @var string
 326   */
 327  public $Version         = '5.2.1';
 328
 329  /**
 330   * What to use in the X-Mailer header
 331   * @var string
 332   */
 333  public $XMailer         = '';
 334
 335  /////////////////////////////////////////////////
 336  // PROPERTIES, PRIVATE AND PROTECTED
 337  /////////////////////////////////////////////////
 338
 339  protected   $smtp           = NULL;
 340  protected   $to             = array();
 341  protected   $cc             = array();
 342  protected   $bcc            = array();
 343  protected   $ReplyTo        = array();
 344  protected   $all_recipients = array();
 345  protected   $attachment     = array();
 346  protected   $CustomHeader   = array();
 347  protected   $message_type   = '';
 348  protected   $boundary       = array();
 349  protected   $language       = array();
 350  protected   $error_count    = 0;
 351  protected   $sign_cert_file = '';
 352  protected   $sign_key_file  = '';
 353  protected   $sign_key_pass  = '';
 354  protected   $exceptions     = false;
 355
 356  /////////////////////////////////////////////////
 357  // CONSTANTS
 358  /////////////////////////////////////////////////
 359
 360  const STOP_MESSAGE  = 0; // message only, continue processing
 361  const STOP_CONTINUE = 1; // message?, likely ok to continue processing
 362  const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
 363
 364  /////////////////////////////////////////////////
 365  // METHODS, VARIABLES
 366  /////////////////////////////////////////////////
 367
 368  /**
 369   * Constructor
 370   * @param boolean $exceptions Should we throw external exceptions?
 371   */
 372  public function __construct($exceptions = false) {
 373    $this->exceptions = ($exceptions == true);
 374  }
 375
 376  /**
 377   * Sets message type to HTML.
 378   * @param bool $ishtml
 379   * @return void
 380   */
 381  public function IsHTML($ishtml = true) {
 382    if ($ishtml) {
 383      $this->ContentType = 'text/html';
 384    } else {
 385      $this->ContentType = 'text/plain';
 386    }
 387  }
 388
 389  /**
 390   * Sets Mailer to send message using SMTP.
 391   * @return void
 392   */
 393  public function IsSMTP() {
 394    $this->Mailer = 'smtp';
 395  }
 396
 397  /**
 398   * Sets Mailer to send message using PHP mail() function.
 399   * @return void
 400   */
 401  public function IsMail() {
 402    $this->Mailer = 'mail';
 403  }
 404
 405  /**
 406   * Sets Mailer to send message using the $Sendmail program.
 407   * @return void
 408   */
 409  public function IsSendmail() {
 410    if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
 411      $this->Sendmail = '/var/qmail/bin/sendmail';
 412    }
 413    $this->Mailer = 'sendmail';
 414  }
 415
 416  /**
 417   * Sets Mailer to send message using the qmail MTA.
 418   * @return void
 419   */
 420  public function IsQmail() {
 421    if (stristr(ini_get('sendmail_path'), 'qmail')) {
 422      $this->Sendmail = '/var/qmail/bin/sendmail';
 423    }
 424    $this->Mailer = 'sendmail';
 425  }
 426
 427  /////////////////////////////////////////////////
 428  // METHODS, RECIPIENTS
 429  /////////////////////////////////////////////////
 430
 431  /**
 432   * Adds a "To" address.
 433   * @param string $address
 434   * @param string $name
 435   * @return boolean true on success, false if address already used
 436   */
 437  public function AddAddress($address, $name = '') {
 438    return $this->AddAnAddress('to', $address, $name);
 439  }
 440
 441  /**
 442   * Adds a "Cc" address.
 443   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
 444   * @param string $address
 445   * @param string $name
 446   * @return boolean true on success, false if address already used
 447   */
 448  public function AddCC($address, $name = '') {
 449    return $this->AddAnAddress('cc', $address, $name);
 450  }
 451
 452  /**
 453   * Adds a "Bcc" address.
 454   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
 455   * @param string $address
 456   * @param string $name
 457   * @return boolean true on success, false if address already used
 458   */
 459  public function AddBCC($address, $name = '') {
 460    return $this->AddAnAddress('bcc', $address, $name);
 461  }
 462
 463  /**
 464   * Adds a "Reply-to" address.
 465   * @param string $address
 466   * @param string $name
 467   * @return boolean
 468   */
 469  public function AddReplyTo($address, $name = '') {
 470    return $this->AddAnAddress('Reply-To', $address, $name);
 471  }
 472
 473  /**
 474   * Adds an address to one of the recipient arrays
 475   * Addresses that have been added already return false, but do not throw exceptions
 476   * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
 477   * @param string $address The email address to send to
 478   * @param string $name
 479   * @return boolean true on success, false if address already used or invalid in some way
 480   * @access protected
 481   */
 482  protected function AddAnAddress($kind, $address, $name = '') {
 483    if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
 484      $this->SetError($this->Lang('Invalid recipient array').': '.$kind);
 485      if ($this->exceptions) {
 486        throw new phpmailerException('Invalid recipient array: ' . $kind);
 487      }
 488	  if ($this->SMTPDebug) {
 489        echo $this->Lang('Invalid recipient array').': '.$kind;
 490      }
 491      return false;
 492    }
 493    $address = trim($address);
 494    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
 495    if (!self::ValidateAddress($address)) {
 496      $this->SetError($this->Lang('invalid_address').': '. $address);
 497      if ($this->exceptions) {
 498        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
 499      }
 500	  if ($this->SMTPDebug) {
 501        echo $this->Lang('invalid_address').': '.$address;
 502      }
 503      return false;
 504    }
 505    if ($kind != 'Reply-To') {
 506      if (!isset($this->all_recipients[strtolower($address)])) {
 507        array_push($this->$kind, array($address, $name));
 508        $this->all_recipients[strtolower($address)] = true;
 509        return true;
 510      }
 511    } else {
 512      if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
 513        $this->ReplyTo[strtolower($address)] = array($address, $name);
 514      return true;
 515    }
 516  }
 517  return false;
 518}
 519
 520/**
 521 * Set the From and FromName properties
 522 * @param string $address
 523 * @param string $name
 524 * @return boolean
 525 */
 526  public function SetFrom($address, $name = '', $auto = 1) {
 527    $address = trim($address);
 528    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
 529    if (!self::ValidateAddress($address)) {
 530      $this->SetError($this->Lang('invalid_address').': '. $address);
 531      if ($this->exceptions) {
 532        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
 533      }
 534	  if ($this->SMTPDebug) {
 535        echo $this->Lang('invalid_address').': '.$address;
 536      }
 537      return false;
 538    }
 539    $this->From = $address;
 540    $this->FromName = $name;
 541    if ($auto) {
 542      if (empty($this->ReplyTo)) {
 543        $this->AddAnAddress('Reply-To', $address, $name);
 544      }
 545      if (empty($this->Sender)) {
 546        $this->Sender = $address;
 547      }
 548    }
 549    return true;
 550  }
 551
 552  /**
 553   * Check that a string looks roughly like an email address should
 554   * Static so it can be used without instantiation
 555   * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
 556   * Conforms approximately to RFC2822
 557   * @link http://www.hexillion.com/samples/#Regex Original pattern found here
 558   * @param string $address The email address to check
 559   * @return boolean
 560   * @static
 561   * @access public
 562   */
 563  public static function ValidateAddress($address) {
 564    if (function_exists('filter_var')) { //Introduced in PHP 5.2
 565      if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
 566        return false;
 567      } else {
 568        return true;
 569      }
 570    } else {
 571      return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
 572    }
 573  }
 574
 575  /////////////////////////////////////////////////
 576  // METHODS, MAIL SENDING
 577  /////////////////////////////////////////////////
 578
 579  /**
 580   * Creates message and assigns Mailer. If the message is
 581   * not sent successfully then it returns false.  Use the ErrorInfo
 582   * variable to view description of the error.
 583   * @return bool
 584   */
 585  public function Send() {
 586    try {
 587      if(!$this->PreSend()) return false;
 588      return $this->PostSend();
 589    } catch (phpmailerException $e) {
 590	  $this->SentMIMEMessage = '';
 591      $this->SetError($e->getMessage());
 592      if ($this->exceptions) {
 593        throw $e;
 594      }
 595      return false;
 596    }
 597  }
 598
 599  protected function PreSend() {
 600    try {
 601	  $mailHeader = "";
 602      if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
 603        throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
 604      }
 605
 606      // Set whether the message is multipart/alternative
 607      if(!empty($this->AltBody)) {
 608        $this->ContentType = 'multipart/alternative';
 609      }
 610
 611      $this->error_count = 0; // reset errors
 612      $this->SetMessageType();
 613      //Refuse to send an empty message
 614      if (empty($this->Body)) {
 615        throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
 616      }
 617
 618      $this->MIMEHeader = $this->CreateHeader();
 619      $this->MIMEBody = $this->CreateBody();
 620
 621      // To capture the complete message when using mail(), create
 622	  // an extra header list which CreateHeader() doesn't fold in
 623      if ($this->Mailer == 'mail') {
 624        if (count($this->to) > 0) {
 625          $mailHeader .= $this->AddrAppend("To", $this->to);
 626        } else {
 627          $mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;");
 628        }
 629        $mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject))));
 630        // if(count($this->cc) > 0) {
 631            // $mailHeader .= $this->AddrAppend("Cc", $this->cc);
 632        // }
 633      }
 634
 635      // digitally sign with DKIM if enabled
 636      if ($this->DKIM_domain && $this->DKIM_private) {
 637        $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
 638        $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
 639      }
 640
 641      $this->SentMIMEMessage = sprintf("%s%s\r\n\r\n%s",$this->MIMEHeader,$mailHeader,$this->MIMEBody);
 642      return true;
 643
 644    } catch (phpmailerException $e) {
 645      $this->SetError($e->getMessage());
 646      if ($this->exceptions) {
 647        throw $e;
 648      }
 649      return false;
 650    }
 651  }
 652
 653  protected function PostSend() {
 654    try {
 655      // Choose the mailer and send through it
 656      switch($this->Mailer) {
 657        case 'sendmail':
 658          return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
 659        case 'smtp':
 660          return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
 661        case 'mail':
 662          return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
 663        default:
 664          return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
 665      }
 666
 667    } catch (phpmailerException $e) {
 668      $this->SetError($e->getMessage());
 669      if ($this->exceptions) {
 670        throw $e;
 671      }
 672	  if ($this->SMTPDebug) {
 673        echo $e->getMessage()."\n";
 674      }
 675      return false;
 676    }
 677  }
 678
 679  /**
 680   * Sends mail using the $Sendmail program.
 681   * @param string $header The message headers
 682   * @param string $body The message body
 683   * @access protected
 684   * @return bool
 685   */
 686  protected function SendmailSend($header, $body) {
 687    if ($this->Sender != '') {
 688      $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
 689    } else {
 690      $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
 691    }
 692    if ($this->SingleTo === true) {
 693      foreach ($this->SingleToArray as $key => $val) {
 694        if(!@$mail = popen($sendmail, 'w')) {
 695          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
 696        }
 697        fputs($mail, "To: " . $val . "\n");
 698        fputs($mail, $header);
 699        fputs($mail, $body);
 700        $result = pclose($mail);
 701        // implement call back function if it exists
 702        $isSent = ($result == 0) ? 1 : 0;
 703        $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
 704        if($result != 0) {
 705          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
 706        }
 707      }
 708    } else {
 709      if(!@$mail = popen($sendmail, 'w')) {
 710        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
 711      }
 712      fputs($mail, $header);
 713      fputs($mail, $body);
 714      $result = pclose($mail);
 715      // implement call back function if it exists
 716      $isSent = ($result == 0) ? 1 : 0;
 717      $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
 718      if($result != 0) {
 719        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
 720      }
 721    }
 722    return true;
 723  }
 724
 725  /**
 726   * Sends mail using the PHP mail() function.
 727   * @param string $header The message headers
 728   * @param string $body The message body
 729   * @access protected
 730   * @return bool
 731   */
 732  protected function MailSend($header, $body) {
 733    $toArr = array();
 734    foreach($this->to as $t) {
 735      $toArr[] = $this->AddrFormat($t);
 736    }
 737    $to = implode(', ', $toArr);
 738
 739    if (empty($this->Sender)) {
 740      $params = "-oi ";
 741    } else {
 742      $params = sprintf("-oi -f %s", $this->Sender);
 743    }
 744    if ($this->Sender != '' and !ini_get('safe_mode')) {
 745      $old_from = ini_get('sendmail_from');
 746      ini_set('sendmail_from', $this->Sender);
 747      if ($this->SingleTo === true && count($toArr) > 1) {
 748        foreach ($toArr as $key => $val) {
 749          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
 750          // implement call back function if it exists
 751          $isSent = ($rt == 1) ? 1 : 0;
 752          $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
 753        }
 754      } else {
 755        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
 756        // implement call back function if it exists
 757        $isSent = ($rt == 1) ? 1 : 0;
 758        $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
 759      }
 760    } else {
 761      if ($this->SingleTo === true && count($toArr) > 1) {
 762        foreach ($toArr as $key => $val) {
 763          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
 764          // implement call back function if it exists
 765          $isSent = ($rt == 1) ? 1 : 0;
 766          $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
 767        }
 768      } else {
 769        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
 770        // implement call back function if it exists
 771        $isSent = ($rt == 1) ? 1 : 0;
 772        $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
 773      }
 774    }
 775    if (isset($old_from)) {
 776      ini_set('sendmail_from', $old_from);
 777    }
 778    if(!$rt) {
 779      throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
 780    }
 781    return true;
 782  }
 783
 784  /**
 785   * Sends mail via SMTP using PhpSMTP
 786   * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
 787   * @param string $header The message headers
 788   * @param string $body The message body
 789   * @uses SMTP
 790   * @access protected
 791   * @return bool
 792   */
 793  protected function SmtpSend($header, $body) {
 794    require_once $this->PluginDir . 'smtp.php';
 795    $bad_rcpt = array();
 796
 797    if(!$this->SmtpConnect()) {
 798      throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
 799    }
 800    $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
 801    if(!$this->smtp->Mail($smtp_from)) {
 802      throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
 803    }
 804
 805    // Attempt to send attach all recipients
 806    foreach($this->to as $to) {
 807      if (!$this->smtp->Recipient($to[0])) {
 808        $bad_rcpt[] = $to[0];
 809        // implement call back function if it exists
 810        $isSent = 0;
 811        $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
 812      } else {
 813        // implement call back function if it exists
 814        $isSent = 1;
 815        $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
 816      }
 817    }
 818    foreach($this->cc as $cc) {
 819      if (!$this->smtp->Recipient($cc[0])) {
 820        $bad_rcpt[] = $cc[0];
 821        // implement call back function if it exists
 822        $isSent = 0;
 823        $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
 824      } else {
 825        // implement call back function if it exists
 826        $isSent = 1;
 827        $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
 828      }
 829    }
 830    foreach($this->bcc as $bcc) {
 831      if (!$this->smtp->Recipient($bcc[0])) {
 832        $bad_rcpt[] = $bcc[0];
 833        // implement call back function if it exists
 834        $isSent = 0;
 835        $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
 836      } else {
 837        // implement call back function if it exists
 838        $isSent = 1;
 839        $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
 840      }
 841    }
 842
 843
 844    if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
 845      $badaddresses = implode(', ', $bad_rcpt);
 846      throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
 847    }
 848    if(!$this->smtp->Data($header . $body)) {
 849      throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
 850    }
 851    if($this->SMTPKeepAlive == true) {
 852      $this->smtp->Reset();
 853    }
 854    return true;
 855  }
 856
 857  /**
 858   * Initiates a connection to an SMTP server.
 859   * Returns false if the operation failed.
 860   * @uses SMTP
 861   * @access public
 862   * @return bool
 863   */
 864  public function SmtpConnect() {
 865    if(is_null($this->smtp)) {
 866      $this->smtp = new SMTP();
 867    }
 868
 869    $this->smtp->do_debug = $this->SMTPDebug;
 870    $hosts = explode(';', $this->Host);
 871    $index = 0;
 872    $connection = $this->smtp->Connected();
 873
 874    // Retry while there is no connection
 875    try {
 876      while($index < count($hosts) && !$connection) {
 877        $hostinfo = array();
 878        if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
 879          $host = $hostinfo[1];
 880          $port = $hostinfo[2];
 881        } else {
 882          $host = $hosts[$index];
 883          $port = $this->Port;
 884        }
 885
 886        $tls = ($this->SMTPSecure == 'tls');
 887        $ssl = ($this->SMTPSecure == 'ssl');
 888
 889        if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
 890
 891          $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
 892          $this->smtp->Hello($hello);
 893
 894          if ($tls) {
 895            if (!$this->smtp->StartTLS()) {
 896              throw new phpmailerException($this->Lang('tls'));
 897            }
 898
 899            //We must resend HELO after tls negotiation
 900            $this->smtp->Hello($hello);
 901          }
 902
 903          $connection = true;
 904          if ($this->SMTPAuth) {
 905            if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
 906              throw new phpmailerException($this->Lang('authenticate'));
 907            }
 908          }
 909        }
 910        $index++;
 911        if (!$connection) {
 912          throw new phpmailerException($this->Lang('connect_host'));
 913        }
 914      }
 915    } catch (phpmailerException $e) {
 916      $this->smtp->Reset();
 917	  if ($this->exceptions) {
 918        throw $e;
 919      }
 920    }
 921    return true;
 922  }
 923
 924  /**
 925   * Closes the active SMTP session if one exists.
 926   * @return void
 927   */
 928  public function SmtpClose() {
 929    if(!is_null($this->smtp)) {
 930      if($this->smtp->Connected()) {
 931        $this->smtp->Quit();
 932        $this->smtp->Close();
 933      }
 934    }
 935  }
 936
 937  /**
 938  * Sets the language for all class error messages.
 939  * Returns false if it cannot load the language file.  The default language is English.
 940  * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
 941  * @param string $lang_path Path to the language file directory
 942  * @access public
 943  */
 944  function SetLanguage($langcode = 'en', $lang_path = 'language/') {
 945    //Define full set of translatable strings
 946    $PHPMAILER_LANG = array(
 947      'provide_address' => 'You must provide at least one recipient email address.',
 948      'mailer_not_supported' => ' mailer is not supported.',
 949      'execute' => 'Could not execute: ',
 950      'instantiate' => 'Could not instantiate mail function.',
 951      'authenticate' => 'SMTP Error: Could not authenticate.',
 952      'from_failed' => 'The following From address failed: ',
 953      'recipients_failed' => 'SMTP Error: The following recipients failed: ',
 954      'data_not_accepted' => 'SMTP Error: Data not accepted.',
 955      'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
 956      'file_access' => 'Could not access file: ',
 957      'file_open' => 'File Error: Could not open file: ',
 958      'encoding' => 'Unknown encoding: ',
 959      'signing' => 'Signing Error: ',
 960      'smtp_error' => 'SMTP server error: ',
 961      'empty_message' => 'Message body empty',
 962      'invalid_address' => 'Invalid address',
 963      'variable_set' => 'Cannot set or reset variable: '
 964    );
 965    //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
 966    $l = true;
 967    if ($langcode != 'en') { //There is no English translation file
 968      $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
 969    }
 970    $this->language = $PHPMAILER_LANG;
 971    return ($l == true); //Returns false if language not found
 972  }
 973
 974  /**
 975  * Return the current array of language strings
 976  * @return array
 977  */
 978  public function GetTranslations() {
 979    return $this->language;
 980  }
 981
 982  /////////////////////////////////////////////////
 983  // METHODS, MESSAGE CREATION
 984  /////////////////////////////////////////////////
 985
 986  /**
 987   * Creates recipient headers.
 988   * @access public
 989   * @return string
 990   */
 991  public function AddrAppend($type, $addr) {
 992    $addr_str = $type . ': ';
 993    $addresses = array();
 994    foreach ($addr as $a) {
 995      $addresses[] = $this->AddrFormat($a);
 996    }
 997    $addr_str .= implode(', ', $addresses);
 998    $addr_str .= $this->LE;
 999
1000    return $addr_str;
1001  }
1002
1003  /**
1004   * Formats an address correctly.
1005   * @access public
1006   * @return string
1007   */
1008  public function AddrFormat($addr) {
1009    if (empty($addr[1])) {
1010      return $this->SecureHeader($addr[0]);
1011    } else {
1012      return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
1013    }
1014  }
1015
1016  /**
1017   * Wraps message for use with mailers that do not
1018   * automatically perform wrapping and for quoted-printable.
1019   * Original written by philippe.
1020   * @param string $message The message to wrap
1021   * @param integer $length The line length to wrap to
1022   * @param boolean $qp_mode Whether to run in Quoted-Printable mode
1023   * @access public
1024   * @return string
1025   */
1026  public function WrapText($message, $length, $qp_mode = false) {
1027    $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
1028    // If utf-8 encoding is used, we will need to make sure we don't
1029    // split multibyte characters when we wrap
1030    $is_utf8 = (strtolower($this->CharSet) == "utf-8");
1031
1032    $message = $this->FixEOL($message);
1033    if (substr($message, -1) == $this->LE) {
1034      $message = substr($message, 0, -1);
1035    }
1036
1037    $line = explode($this->LE, $message);
1038    $message = '';
1039    for ($i = 0 ;$i < count($line); $i++) {
1040      $line_part = explode(' ', $line[$i]);
1041      $buf = '';
1042      for ($e = 0; $e<count($line_part); $e++) {
1043        $word = $line_part[$e];
1044        if ($qp_mode and (strlen($word) > $length)) {
1045          $space_left = $length - strlen($buf) - 1;
1046          if ($e != 0) {
1047            if ($space_left > 20) {
1048              $len = $space_left;
1049              if ($is_utf8) {
1050                $len = $this->UTF8CharBoundary($word, $len);
1051              } elseif (substr($word, $len - 1, 1) == "=") {
1052                $len--;
1053              } elseif (substr($word, $len - 2, 1) == "=") {
1054                $len -= 2;
1055              }
1056              $part = substr($word, 0, $len);
1057              $word = substr($word, $len);
1058              $buf .= ' ' . $part;
1059              $message .= $buf . sprintf("=%s", $this->LE);
1060            } else {
1061              $message .= $buf . $soft_break;
1062            }
1063            $buf = '';
1064          }
1065          while (strlen($word) > 0) {
1066            $len = $length;
1067            if ($is_utf8) {
1068              $len = $this->UTF8CharBoundary($word, $len);
1069            } elseif (substr($word, $len - 1, 1) == "=") {
1070              $len--;
1071            } elseif (substr($word, $len - 2, 1) == "=") {
1072              $len -= 2;
1073            }
1074            $part = substr($word, 0, $len);
1075            $word = substr($word, $len);
1076
1077            if (strlen($word) > 0) {
1078              $message .= $part . sprintf("=%s", $this->LE);
1079            } else {
1080              $buf = $part;
1081            }
1082          }
1083        } else {
1084          $buf_o = $buf;
1085          $buf .= ($e == 0) ? $word : (' ' . $word);
1086
1087          if (strlen($buf) > $length and $buf_o != '') {
1088            $message .= $buf_o . $soft_break;
1089            $buf = $word;
1090          }
1091        }
1092      }
1093      $message .= $buf . $this->LE;
1094    }
1095
1096    return $message;
1097  }
1098
1099  /**
1100   * Finds last character boundary prior to maxLength in a utf-8
1101   * quoted (printable) encoded string.
1102   * Original written by Colin Brown.
1103   * @access public
1104   * @param string $encodedText utf-8 QP text
1105   * @param int    $maxLength   find last character boundary prior to this length
1106   * @return int
1107   */
1108  public function UTF8CharBoundary($encodedText, $maxLength) {
1109    $foundSplitPos = false;
1110    $lookBack = 3;
1111    while (!$foundSplitPos) {
1112      $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1113      $encodedCharPos = strpos($lastChunk, "=");
1114      if ($encodedCharPos !== false) {
1115        // Found start of encoded character byte within $lookBack block.
1116        // Check the encoded byte value (the 2 chars after the '=')
1117        $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1118        $dec = hexdec($hex);
1119        if ($dec < 128) { // Single byte character.
1120          // If the encoded char was found at pos 0, it will fit
1121          // otherwise reduce maxLength to start of the encoded char
1122          $maxLength = ($encodedCharPos == 0) ? $maxLength :
1123          $maxLength - ($lookBack - $encodedCharPos);
1124          $foundSplitPos = true;
1125        } elseif ($dec >= 192) { // First byte of a multi byte character
1126          // Reduce maxLength to split at start of character
1127          $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1128          $foundSplitPos = true;
1129        } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
1130          $lookBack += 3;
1131        }
1132      } else {
1133        // No encoded character found
1134        $foundSplitPos = true;
1135      }
1136    }
1137    return $maxLength;
1138  }
1139
1140
1141  /**
1142   * Set the body wrapping.
1143   * @access public
1144   * @return void
1145   */
1146  public function SetWordWrap() {
1147    if($this->WordWrap < 1) {
1148      return;
1149    }
1150
1151    switch($this->message_type) {
1152      case 'alt':
1153      case 'alt_inline':
1154      case 'alt_attach':
1155      case 'alt_inline_attach':
1156        $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
1157        break;
1158      default:
1159        $this->Body = $this->WrapText($this->Body, $this->WordWrap);
1160        break;
1161    }
1162  }
1163
1164  /**
1165   * Assembles message header.
1166   * @access public
1167   * @return string The assembled header
1168   */
1169  public function CreateHeader() {
1170    $result = '';
1171
1172    // Set the boundaries
1173    $uniq_id = md5(uniqid(time()));
1174    $this->boundary[1] = 'b1_' . $uniq_id;
1175    $this->boundary[2] = 'b2_' . $uniq_id;
1176    $this->boundary[3] = 'b3_' . $uniq_id;
1177
1178    $result .= $this->HeaderLine('Date', self::RFCDate());
1179    if($this->Sender == '') {
1180      $result .= $this->HeaderLine('Return-Path', trim($this->From));
1181    } else {
1182      $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
1183    }
1184
1185    // To be created automatically by mail()
1186    if($this->Mailer != 'mail') {
1187      if ($this->SingleTo === true) {
1188        foreach($this->to as $t) {
1189          $this->SingleToArray[] = $this->AddrFormat($t);
1190        }
1191      } else {
1192        if(count($this->to) > 0) {
1193          $result .= $this->AddrAppend('To', $this->to);
1194        } elseif (count($this->cc) == 0) {
1195          $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
1196        }
1197      }
1198	}
1199
1200    $from = array();
1201    $from[0][0] = trim($this->From);
1202    $from[0][1] = $this->FromName;
1203    $result .= $this->AddrAppend('From', $from);
1204
1205    // sendmail and mail() extract Cc from the header before sending
1206    if(count($this->cc) > 0) {
1207      $result .= $this->AddrAppend('Cc', $this->cc);
1208    }
1209
1210    // sendmail and mail() extract Bcc from the header before sending
1211    if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
1212      $result .= $this->AddrAppend('Bcc', $this->bcc);
1213    }
1214
1215    if(count($this->ReplyTo) > 0) {
1216      $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
1217    }
1218
1219    // mail() sets the subject itself
1220    if($this->Mailer != 'mail') {
1221      $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
1222    }
1223
1224    if($this->MessageID != '') {
1225      $result .= $this->HeaderLine('Message-ID', $this->MessageID);
1226    } else {
1227      $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
1228    }
1229    $result .= $this->HeaderLine('X-Priority', $this->Priority);
1230    if($this->XMailer) {
1231      $result .= $this->HeaderLine('X-Mailer', $this->XMailer);
1232    } else {
1233      $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)');
1234    }
1235
1236    if($this->ConfirmReadingTo != '') {
1237      $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1238    }
1239
1240    // Add custom headers
1241    for($index = 0; $index < count($this->CustomHeader); $index++) {
1242      $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
1243    }
1244    if (!$this->sign_key_file) {
1245      $result .= $this->HeaderLine('MIME-Version', '1.0');
1246      $result .= $this->GetMailMIME();
1247    }
1248
1249    return $result;
1250  }
1251
1252  /**
1253   * Returns the message MIME.
1254   * @access public
1255   * @return string
1256   */
1257  public function GetMailMIME() {
1258    $result = '';
1259    switch($this->message_type) {
1260      case 'plain':
1261        $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
1262        $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset="'.$this->CharSet.'"');
1263        break;
1264      case 'inline':
1265        $result .= $this->HeaderLine('Content-Type', 'multipart/related;');
1266        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1267        break;
1268      case 'attach':
1269      case 'inline_attach':
1270      case 'alt_attach':
1271      case 'alt_inline_attach':
1272        $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
1273        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1274        break;
1275      case 'alt':
1276      case 'alt_inline':
1277        $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1278        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1279        break;
1280    }
1281
1282    if($this->Mailer != 'mail') {
1283      $result .= $this->LE.$this->LE;
1284    }
1285
1286    return $result;
1287  }
1288
1289  /**
1290   * Returns the MIME message (headers and body). Only really valid post PreSend().
1291   * @access public
1292   * @return string
1293   */
1294  public function GetSentMIMEMessage() {
1295    return $this->SentMIMEMessage;
1296  }
1297
1298
1299  /**
1300   * Assembles the message body.  Returns an empty string on failure.
1301   * @access public
1302   * @return string The assembled message body
1303   */
1304  public function CreateBody() {
1305    $body = '';
1306
1307    if ($this->sign_key_file) {
1308      $body .= $this->GetMailMIME();
1309    }
1310
1311    $this->SetWordWrap();
1312
1313    switch($this->message_type) {
1314      case 'plain':
1315        $body .= $this->EncodeString($this->Body, $this->Encoding);
1316        break;
1317      case 'inline':
1318        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
1319        $body .= $this->EncodeString($this->Body, $this->Encoding);
1320        $body .= $this->LE.$this->LE;
1321        $body .= $this->AttachAll("inline", $this->boundary[1]);
1322        break;
1323      case 'attach':
1324        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
1325        $body .= $this->EncodeString($this->Body, $this->Encoding);
1326        $body .= $this->LE.$this->LE;
1327        $body .= $this->AttachAll("attachment", $this->boundary[1]);
1328        break;
1329      case 'inline_attach':
1330        $body .= $this->TextLine("--" . $this->boundary[1]);
1331        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1332        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1333        $body .= $this->LE;
1334        $body .= $this->GetBoundary($this->boundary[2], '', '', '');
1335        $body .= $this->EncodeString($this->Body, $this->Encoding);
1336        $body .= $this->LE.$this->LE;
1337        $body .= $this->AttachAll("inline", $this->boundary[2]);
1338        $body .= $this->LE;
1339        $body .= $this->AttachAll("attachment", $this->boundary[1]);
1340        break;
1341      case 'alt':
1342        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1343        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1344        $body .= $this->LE.$this->LE;
1345        $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
1346        $body .= $this->EncodeString($this->Body, $this->Encoding);
1347        $body .= $this->LE.$this->LE;
1348        $body .= $this->EndBoundary($this->boundary[1]);
1349        break;
1350      case 'alt_inline':
1351        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1352        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1353        $body .= $this->LE.$this->LE;
1354        $body .= $this->TextLine("--" . $this->boundary[1]);
1355        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1356        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1357        $body .= $this->LE;
1358        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
1359        $body .= $this->EncodeString($this->Body, $this->Encoding);
1360        $body .= $this->LE.$this->LE;
1361        $body .= $this->AttachAll("inline", $this->boundary[2]);
1362        $body .= $this->LE;
1363        $body .= $this->EndBoundary($this->boundary[1]);
1364        break;
1365      case 'alt_attach':
1366        $body .= $this->TextLine("--" . $this->boundary[1]);
1367        $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1368        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1369        $body .= $this->LE;
1370        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
1371        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1372        $body .= $this->LE.$this->LE;
1373        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
1374        $body .= $this->EncodeString($this->Body, $this->Encoding);
1375        $body .= $this->LE.$this->LE;
1376        $body .= $this->EndBoundary($this->boundary[2]);
1377        $body .= $this->LE;
1378        $body .= $this->AttachAll("attachment", $this->boundary[1]);
1379        break;
1380      case 'alt_inline_attach':
1381        $body .= $this->TextLine("--" . $this->boundary[1]);
1382        $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1383        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1384        $body .= $this->LE;
1385        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
1386        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1387        $body .= $this->LE.$this->LE;
1388        $body .= $this->TextLine("--" . $this->boundary[2]);
1389        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1390        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"');
1391        $body .= $this->LE;
1392        $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
1393        $body .= $this->EncodeString($this->Body, $this->Encoding);
1394        $body .= $this->LE.$this->LE;
1395        $body .= $this->AttachAll("inline", $this->boundary[3]);
1396        $body .= $this->LE;
1397        $body .= $this->EndBoundary($this->boundary[2]);
1398        $body .= $this->LE;
1399        $body .= $this->AttachAll("attachment", $this->boundary[1]);
1400        break;
1401    }
1402
1403    if ($this->IsError()) {
1404      $body = '';
1405    } elseif ($this->sign_key_file) {
1406      try {
1407        $file = tempnam('', 'mail');
1408        file_put_contents($file, $body); //TODO check this worked
1409        $signed = tempnam("", "signed");
1410        if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
1411          @unlink($file);
1412          $body = file_get_contents($signed);
1413          @unlink($signed);
1414        } else {
1415          @unlink($file);
1416          @unlink($signed);
1417          throw new phpmailerException($this->Lang("signing").openssl_error_string());
1418        }
1419      } catch (phpmailerException $e) {
1420        $body = '';
1421        if ($this->exceptions) {
1422          throw $e;
1423        }
1424      }
1425    }
1426
1427    return $body;
1428  }
1429
1430  /**
1431   * Returns the start of a message boundary.
1432   * @access protected
1433   * @return string
1434   */
1435  protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
1436    $result = '';
1437    if($charSet == '') {
1438      $charSet = $this->CharSet;
1439    }
1440    if($contentType == '') {
1441      $contentType = $this->ContentType;
1442    }
1443    if($encoding == '') {
1444      $encoding = $this->Encoding;
1445    }
1446    $result .= $this->TextLine('--' . $boundary);
1447    $result .= sprintf("Content-Type: %s; charset=\"%s\"", $contentType, $charSet);
1448    $result .= $this->LE;
1449    $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
1450    $result .= $this->LE;
1451
1452    return $result;
1453  }
1454
1455  /**
1456   * Returns the end of a message boundary.
1457   * @access protected
1458   * @return string
1459   */
1460  protected function EndBoundary($boundary) {
1461    return $this->LE . '--' . $boundary . '--' . $this->LE;
1462  }
1463
1464  /**
1465   * Sets the message type.
1466   * @access protected
1467   * @return void
1468   */
1469  protected function SetMessageType() {
1470    $this->message_type = array();
1471    if($this->AlternativeExists()) $this->message_type[] = "alt";
1472    if($this->InlineImageExists()) $this->message_type[] = "inline";
1473    if($this->AttachmentExists()) $this->message_type[] = "attach";
1474    $this->message_type = implode("_", $this->message_type);
1475    if($this->message_type == "") $this->message_type = "plain";
1476  }
1477
1478  /**
1479   *  Returns a formatted header line.
1480   * @access public
1481   * @return string
1482   */
1483  public function HeaderLine($name, $value) {
1484    return $name . ': ' . $value . $this->LE;
1485  }
1486
1487  /**
1488   * Returns a formatted mail line.
1489   * @access public
1490   * @return string
1491   */
1492  public function TextLine($value) {
1493    return $value . $this->LE;
1494  }
1495
1496  /////////////////////////////////////////////////
1497  // CLASS METHODS, ATTACHMENTS
1498  /////////////////////////////////////////////////
1499
1500  /**
1501   * Adds an attachment from a path on the filesystem.
1502   * Returns false if the file could not be found
1503   * or accessed.
1504   * @param string $path Path to the attachment.
1505   * @param string $name Overrides the attachment name.
1506   * @param string $encoding File encoding (see $Encoding).
1507   * @param string $type File extension (MIME) type.
1508   * @return bool
1509   */
1510  public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1511    try {
1512      if ( !@is_file($path) ) {
1513        throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
1514      }
1515      $filename = basename($path);
1516      if ( $name == '' ) {
1517        $name = $filename;
1518      }
1519
1520      $this->attachment[] = array(
1521        0 => $path,
1522        1 => $filename,
1523        2 => $name,
1524        3 => $encoding,
1525        4 => $type,
1526        5 => false,  // isStringAttachment
1527        6 => 'attachment',
1528        7 => 0
1529      );
1530
1531    } catch (phpmailerException $e) {
1532      $this->SetError($e->getMessage());
1533      if ($this->exceptions) {
1534        throw $e;
1535      }
1536	  if ($this->SMTPDebug) {
1537        echo $e->getMessage()."\n";
1538      }
1539      if ( $e->getCode() == self::STOP_CRITICAL ) {
1540        return false;
1541      }
1542    }
1543    return true;
1544  }
1545
1546  /**
1547  * Return the current array of attachments
1548  * @return array
1549  */
1550  public function GetAttachments() {
1551    return $this->attachment;
1552  }
1553
1554  /**
1555   * At…

Large files files are truncated, but you can click here to view the full file