Make WordPress Core

Changeset 17676


Ignore:
Timestamp:
04/21/2011 08:29:30 PM (13 years ago)
Author:
ryan
Message:

Update phpmailer and smtp to 5.1. Props MattyRob cnorris23. fixes #15912

Location:
trunk/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-phpmailer.php

    r11341 r17676  
    33.---------------------------------------------------------------------------.
    44|  Software: PHPMailer - PHP email class                                    |
    5 |   Version: 2.0.4                                                          |
    6 |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
     5|   Version: 5.1                                                            |
     6|   Contact: via sourceforge.net support pages (also www.worxware.com)      |
    77|      Info: http://phpmailer.sourceforge.net                               |
    88|   Support: http://sourceforge.net/projects/phpmailer/                     |
    99| ------------------------------------------------------------------------- |
    10 |    Author: Andy Prevost (project admininistrator)                         |
    11 |    Author: Brent R. Matzelle (original founder)                           |
    12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
     10|     Admin: Andy Prevost (project admininistrator)                         |
     11|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
     12|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
     13|   Founder: Brent R. Matzelle (original founder)                           |
     14| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
    1315| Copyright (c) 2001-2003, Brent R. Matzelle                                |
    1416| ------------------------------------------------------------------------- |
     
    1921| FITNESS FOR A PARTICULAR PURPOSE.                                         |
    2022| ------------------------------------------------------------------------- |
    21 | We offer a number of paid services (www.codeworxtech.com):                |
     23| We offer a number of paid services (www.worxware.com):                    |
    2224| - Web Hosting on highly optimized fast and secure servers                 |
    2325| - Technology Consulting                                                   |
    2426| - Oursourcing (highly qualified programmers and graphic designers)        |
    2527'---------------------------------------------------------------------------'
    26  */
     28*/
     29
    2730/**
    2831 * PHPMailer - PHP email transport class
     32 * NOTE: Requires PHP version 5 or later
    2933 * @package PHPMailer
    3034 * @author Andy Prevost
     35 * @author Marcus Bointon
    3136 * @copyright 2004 - 2009 Andy Prevost
     37 * @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $
     38 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
    3239 */
     40
     41if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
    3342
    3443class PHPMailer {
     
    4251   * @var int
    4352   */
    44   var $Priority          = 3;
     53  public $Priority          = 3;
    4554
    4655  /**
     
    4857   * @var string
    4958   */
    50   var $CharSet           = 'iso-8859-1';
     59  public $CharSet           = 'iso-8859-1';
    5160
    5261  /**
     
    5463   * @var string
    5564   */
    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';
     65  public $ContentType       = 'text/plain';
     66
     67  /**
     68   * Sets the Encoding of the message. Options for this are
     69   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
     70   * @var string
     71   */
     72  public $Encoding          = '8bit';
    6473
    6574  /**
     
    6776   * @var string
    6877   */
    69   var $ErrorInfo         = '';
     78  public $ErrorInfo         = '';
    7079
    7180  /**
     
    7382   * @var string
    7483   */
    75   var $From              = 'root@localhost';
     84  public $From              = 'root@localhost';
    7685
    7786  /**
     
    7988   * @var string
    8089   */
    81   var $FromName          = 'Root User';
     90  public $FromName          = 'Root User';
    8291
    8392  /**
     
    8695   * @var string
    8796   */
    88   var $Sender            = '';
     97  public $Sender            = '';
    8998
    9099  /**
     
    92101   * @var string
    93102   */
    94   var $Subject           = '';
     103  public $Subject           = '';
    95104
    96105  /**
     
    99108   * @var string
    100109   */
    101   var $Body              = '';
     110  public $Body              = '';
    102111
    103112  /**
     
    108117   * @var string
    109118   */
    110   var $AltBody           = '';
     119  public $AltBody           = '';
    111120
    112121  /**
     
    115124   * @var int
    116125   */
    117   var $WordWrap          = 0;
     126  public $WordWrap          = 0;
    118127
    119128  /**
     
    121130   * @var string
    122131   */
    123   var $Mailer            = 'mail';
     132  public $Mailer            = 'mail';
    124133
    125134  /**
     
    127136   * @var string
    128137   */
    129   var $Sendmail          = '/usr/sbin/sendmail';
    130 
    131   /**
    132    * Path to PHPMailer plugins.  This is now only useful if the SMTP class
     138  public $Sendmail          = '/usr/sbin/sendmail';
     139
     140  /**
     141   * Path to PHPMailer plugins.  Useful if the SMTP class
    133142   * is in a different directory than the PHP include path.
    134143   * @var string
    135144   */
    136   var $PluginDir         = '';
    137 
    138   /**
    139    * Holds PHPMailer version.
    140    * @var string
    141    */
    142   var $Version           = "2.0.4";
     145  public $PluginDir         = '';
    143146
    144147  /**
     
    146149   * @var string
    147150   */
    148   var $ConfirmReadingTo  = '';
     151  public $ConfirmReadingTo  = '';
    149152
    150153  /**
     
    154157   * @var string
    155158   */
    156   var $Hostname          = '';
     159  public $Hostname          = '';
    157160
    158161  /**
     
    161164   * @var string
    162165   */
    163   var $MessageID         = '';
     166  public $MessageID         = '';
    164167
    165168  /////////////////////////////////////////////////
     
    175178   * @var string
    176179   */
    177   var $Host        = 'localhost';
     180  public $Host          = 'localhost';
    178181
    179182  /**
     
    181184   * @var int
    182185   */
    183   var $Port        = 25;
     186  public $Port          = 25;
    184187
    185188  /**
     
    187190   * @var string
    188191   */
    189   var $Helo        = '';
     192  public $Helo          = '';
    190193
    191194  /**
     
    194197   * @var string
    195198   */
    196   var $SMTPSecure = "";
     199  public $SMTPSecure    = '';
    197200
    198201  /**
     
    200203   * @var bool
    201204   */
    202   var $SMTPAuth     = false;
     205  public $SMTPAuth      = false;
    203206
    204207  /**
     
    206209   * @var string
    207210   */
    208   var $Username     = '';
     211  public $Username      = '';
    209212
    210213  /**
     
    212215   * @var string
    213216   */
    214   var $Password     = '';
    215 
    216   /**
    217    * Sets the SMTP server timeout in seconds. This function will not
    218    * work with the win32 version.
     217  public $Password      = '';
     218
     219  /**
     220   * Sets the SMTP server timeout in seconds.
     221   * This function will not work with the win32 version.
    219222   * @var int
    220223   */
    221   var $Timeout      = 10;
     224  public $Timeout       = 10;
    222225
    223226  /**
     
    225228   * @var bool
    226229   */
    227   var $SMTPDebug    = false;
     230  public $SMTPDebug     = false;
    228231
    229232  /**
     
    233236   * @var bool
    234237   */
    235   var $SMTPKeepAlive = false;
     238  public $SMTPKeepAlive = false;
    236239
    237240  /**
     
    240243   * @var bool
    241244   */
    242   var $SingleTo = false;
     245  public $SingleTo      = false;
     246
     247   /**
     248   * If SingleTo is true, this provides the array to hold the email addresses
     249   * @var bool
     250   */
     251  public $SingleToArray = array();
     252
     253 /**
     254   * Provides the ability to change the line ending
     255   * @var string
     256   */
     257  public $LE              = "\n";
     258
     259  /**
     260   * Used with DKIM DNS Resource Record
     261   * @var string
     262   */
     263  public $DKIM_selector   = 'phpmailer';
     264
     265  /**
     266   * Used with DKIM DNS Resource Record
     267   * optional, in format of email address 'you@yourdomain.com'
     268   * @var string
     269   */
     270  public $DKIM_identity   = '';
     271
     272  /**
     273   * Used with DKIM DNS Resource Record
     274   * optional, in format of email address 'you@yourdomain.com'
     275   * @var string
     276   */
     277  public $DKIM_domain     = '';
     278
     279  /**
     280   * Used with DKIM DNS Resource Record
     281   * optional, in format of email address 'you@yourdomain.com'
     282   * @var string
     283   */
     284  public $DKIM_private    = '';
     285
     286  /**
     287   * Callback Action function name
     288   * the function that handles the result of the send email action. Parameters:
     289   *   bool    $result        result of the send action
     290   *   string  $to            email address of the recipient
     291   *   string  $cc            cc email addresses
     292   *   string  $bcc           bcc email addresses
     293   *   string  $subject       the subject
     294   *   string  $body          the email body
     295   * @var string
     296   */
     297  public $action_function = ''; //'callbackAction';
     298
     299  /**
     300   * Sets the PHPMailer Version number
     301   * @var string
     302   */
     303  public $Version         = '5.1';
    243304
    244305  /////////////////////////////////////////////////
    245   // PROPERTIES, PRIVATE
     306  // PROPERTIES, PRIVATE AND PROTECTED
    246307  /////////////////////////////////////////////////
    247308
    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   = "";
     309  private   $smtp           = NULL;
     310  private   $to             = array();
     311  private   $cc             = array();
     312  private   $bcc            = array();
     313  private   $ReplyTo        = array();
     314  private   $all_recipients = array();
     315  private   $attachment     = array();
     316  private   $CustomHeader   = array();
     317  private   $message_type   = '';
     318  private   $boundary       = array();
     319  protected $language       = array();
     320  private   $error_count    = 0;
     321  private   $sign_cert_file = "";
     322  private   $sign_key_file  = "";
     323  private   $sign_key_pass  = "";
     324  private   $exceptions     = false;
     325
     326  /////////////////////////////////////////////////
     327  // CONSTANTS
     328  /////////////////////////////////////////////////
     329
     330  const STOP_MESSAGE  = 0; // message only, continue processing
     331  const STOP_CONTINUE = 1; // message?, likely ok to continue processing
     332  const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
    263333
    264334  /////////////////////////////////////////////////
     
    267337
    268338  /**
     339   * Constructor
     340   * @param boolean $exceptions Should we throw external exceptions?
     341   */
     342  public function __construct($exceptions = false) {
     343    $this->exceptions = ($exceptions == true);
     344  }
     345
     346  /**
    269347   * Sets message type to HTML.
    270    * @param bool $bool
     348   * @param bool $ishtml
    271349   * @return void
    272350   */
    273   function IsHTML($bool) {
    274     if($bool == true) {
     351  public function IsHTML($ishtml = true) {
     352    if ($ishtml) {
    275353      $this->ContentType = 'text/html';
    276354    } else {
     
    283361   * @return void
    284362   */
    285   function IsSMTP() {
     363  public function IsSMTP() {
    286364    $this->Mailer = 'smtp';
    287365  }
     
    291369   * @return void
    292370   */
    293   function IsMail() {
     371  public function IsMail() {
    294372    $this->Mailer = 'mail';
    295373  }
     
    299377   * @return void
    300378   */
    301   function IsSendmail() {
     379  public function IsSendmail() {
     380    if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
     381      $this->Sendmail = '/var/qmail/bin/sendmail';
     382    }
    302383    $this->Mailer = 'sendmail';
    303384  }
     
    307388   * @return void
    308389   */
    309   function IsQmail() {
    310     $this->Sendmail = '/var/qmail/bin/sendmail';
     390  public function IsQmail() {
     391    if (stristr(ini_get('sendmail_path'), 'qmail')) {
     392      $this->Sendmail = '/var/qmail/bin/sendmail';
     393    }
    311394    $this->Mailer = 'sendmail';
    312395  }
     
    320403   * @param string $address
    321404   * @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.
     405   * @return boolean true on success, false if address already used
     406   */
     407  public function AddAddress($address, $name = '') {
     408    return $this->AddAnAddress('to', $address, $name);
     409  }
     410
     411  /**
     412   * Adds a "Cc" address.
     413   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
    334414   * @param string $address
    335415   * @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.
     416   * @return boolean true on success, false if address already used
     417   */
     418  public function AddCC($address, $name = '') {
     419    return $this->AddAnAddress('cc', $address, $name);
     420  }
     421
     422  /**
     423   * Adds a "Bcc" address.
     424   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
    348425   * @param string $address
    349426   * @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.
     427   * @return boolean true on success, false if address already used
     428   */
     429  public function AddBCC($address, $name = '') {
     430    return $this->AddAnAddress('bcc', $address, $name);
     431  }
     432
     433  /**
     434   * Adds a "Reply-to" address.
    360435   * @param string $address
    361436   * @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;
     437   * @return boolean
     438   */
     439  public function AddReplyTo($address, $name = '') {
     440    return $this->AddAnAddress('ReplyTo', $address, $name);
     441  }
     442
     443  /**
     444   * Adds an address to one of the recipient arrays
     445   * Addresses that have been added already return false, but do not throw exceptions
     446   * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
     447   * @param string $address The email address to send to
     448   * @param string $name
     449   * @return boolean true on success, false if address already used or invalid in some way
     450   * @access private
     451   */
     452  private function AddAnAddress($kind, $address, $name = '') {
     453    if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
     454      echo 'Invalid recipient array: ' . kind;
     455      return false;
     456    }
     457    $address = trim($address);
     458    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
     459    if (!self::ValidateAddress($address)) {
     460      $this->SetError($this->Lang('invalid_address').': '. $address);
     461      if ($this->exceptions) {
     462        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
     463      }
     464      echo $this->Lang('invalid_address').': '.$address;
     465      return false;
     466    }
     467    if ($kind != 'ReplyTo') {
     468      if (!isset($this->all_recipients[strtolower($address)])) {
     469        array_push($this->$kind, array($address, $name));
     470        $this->all_recipients[strtolower($address)] = true;
     471        return true;
     472      }
     473    } else {
     474      if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
     475        $this->ReplyTo[strtolower($address)] = array($address, $name);
     476      return true;
     477    }
     478  }
     479  return false;
     480}
     481
     482/**
     483 * Set the From and FromName properties
     484 * @param string $address
     485 * @param string $name
     486 * @return boolean
     487 */
     488  public function SetFrom($address, $name = '',$auto=1) {
     489    $address = trim($address);
     490    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
     491    if (!self::ValidateAddress($address)) {
     492      $this->SetError($this->Lang('invalid_address').': '. $address);
     493      if ($this->exceptions) {
     494        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
     495      }
     496      echo $this->Lang('invalid_address').': '.$address;
     497      return false;
     498    }
     499    $this->From = $address;
     500    $this->FromName = $name;
     501    if ($auto) {
     502      if (empty($this->ReplyTo)) {
     503        $this->AddAnAddress('ReplyTo', $address, $name);
     504      }
     505      if (empty($this->Sender)) {
     506        $this->Sender = $address;
     507      }
     508    }
     509    return true;
     510  }
     511
     512  /**
     513   * Check that a string looks roughly like an email address should
     514   * Static so it can be used without instantiation
     515   * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
     516   * Conforms approximately to RFC2822
     517   * @link http://www.hexillion.com/samples/#Regex Original pattern found here
     518   * @param string $address The email address to check
     519   * @return boolean
     520   * @static
     521   * @access public
     522   */
     523  public static function ValidateAddress($address) {
     524    if (function_exists('filter_var')) { //Introduced in PHP 5.2
     525      if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
     526        return false;
     527      } else {
     528        return true;
     529      }
     530    } else {
     531      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);
     532    }
    368533  }
    369534
     
    378543   * @return bool
    379544   */
    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'));
     545  public function Send() {
     546    try {
     547      if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
     548        throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
     549      }
     550
     551      // Set whether the message is multipart/alternative
     552      if(!empty($this->AltBody)) {
     553        $this->ContentType = 'multipart/alternative';
     554      }
     555
     556      $this->error_count = 0; // reset errors
     557      $this->SetMessageType();
     558      $header = $this->CreateHeader();
     559      $body = $this->CreateBody();
     560
     561      if (empty($this->Body)) {
     562        throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
     563      }
     564
     565      // digitally sign with DKIM if enabled
     566      if ($this->DKIM_domain && $this->DKIM_private) {
     567        $header_dkim = $this->DKIM_Add($header,$this->Subject,$body);
     568        $header = str_replace("\r\n","\n",$header_dkim) . $header;
     569      }
     570
     571      // Choose the mailer and send through it
     572      switch($this->Mailer) {
     573        case 'sendmail':
     574          return $this->SendmailSend($header, $body);
     575        case 'smtp':
     576          return $this->SmtpSend($header, $body);
     577        default:
     578          return $this->MailSend($header, $body);
     579      }
     580
     581    } catch (phpmailerException $e) {
     582      $this->SetError($e->getMessage());
     583      if ($this->exceptions) {
     584        throw $e;
     585      }
     586      echo $e->getMessage()."\n";
    387587      return false;
    388588    }
    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;
    424589  }
    425590
    426591  /**
    427592   * Sends mail using the $Sendmail program.
    428    * @access private
     593   * @param string $header The message headers
     594   * @param string $body The message body
     595   * @access protected
    429596   * @return bool
    430597   */
    431   function SendmailSend($header, $body) {
     598  protected function SendmailSend($header, $body) {
    432599    if ($this->Sender != '') {
    433600      $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
     
    435602      $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
    436603    }
    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;
     604    if ($this->SingleTo === true) {
     605      foreach ($this->SingleToArray as $key => $val) {
     606        if(!@$mail = popen($sendmail, 'w')) {
     607          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
     608        }
     609        fputs($mail, "To: " . $val . "\n");
     610        fputs($mail, $header);
     611        fputs($mail, $body);
     612        $result = pclose($mail);
     613        // implement call back function if it exists
     614        $isSent = ($result == 0) ? 1 : 0;
     615        $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
     616        if($result != 0) {
     617          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
     618        }
     619      }
     620    } else {
     621      if(!@$mail = popen($sendmail, 'w')) {
     622        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
     623      }
     624      fputs($mail, $header);
     625      fputs($mail, $body);
     626      $result = pclose($mail);
     627      // implement call back function if it exists
     628      $isSent = ($result == 0) ? 1 : 0;
     629      $this->doCallback($isSent,$this->to,$this->cc,$this->bcc,$this->Subject,$body);
     630      if($result != 0) {
     631        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
     632      }
    453633    }
    454634    return true;
     
    457637  /**
    458638   * Sends mail using the PHP mail() function.
    459    * @access private
     639   * @param string $header The message headers
     640   * @param string $body The message body
     641   * @access protected
    460642   * @return bool
    461643   */
    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);
     644  protected function MailSend($header, $body) {
     645    $toArr = array();
     646    foreach($this->to as $t) {
     647      $toArr[] = $this->AddrFormat($t);
     648    }
     649    $to = implode(', ', $toArr);
    471650
    472651    $params = sprintf("-oi -f %s", $this->Sender);
    473     if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {
     652    if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
    474653      $old_from = ini_get('sendmail_from');
    475654      ini_set('sendmail_from', $this->Sender);
     
    477656        foreach ($toArr as $key => $val) {
    478657          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
     658          // implement call back function if it exists
     659          $isSent = ($rt == 1) ? 1 : 0;
     660          $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
    479661        }
    480662      } else {
    481663        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
     664        // implement call back function if it exists
     665        $isSent = ($rt == 1) ? 1 : 0;
     666        $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body);
    482667      }
    483668    } else {
     
    485670        foreach ($toArr as $key => $val) {
    486671          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
     672          // implement call back function if it exists
     673          $isSent = ($rt == 1) ? 1 : 0;
     674          $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body);
    487675        }
    488676      } else {
    489677        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
    490       }
    491     }
    492 
     678        // implement call back function if it exists
     679        $isSent = ($rt == 1) ? 1 : 0;
     680        $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body);
     681      }
     682    }
    493683    if (isset($old_from)) {
    494684      ini_set('sendmail_from', $old_from);
    495685    }
    496 
    497686    if(!$rt) {
    498       $this->SetError($this->Lang('instantiate'));
    499       return false;
    500     }
    501 
     687      throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
     688    }
    502689    return true;
    503690  }
    504691
    505692  /**
    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
     693   * Sends mail via SMTP using PhpSMTP
     694   * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
     695   * @param string $header The message headers
     696   * @param string $body The message body
     697   * @uses SMTP
     698   * @access protected
    510699   * @return bool
    511700   */
    512   function SmtpSend($header, $body) {
    513     include_once($this->PluginDir . 'class-smtp.php');
    514     $error = '';
     701  protected function SmtpSend($header, $body) {
     702    require_once $this->PluginDir . 'class-smtp.php';
    515703    $bad_rcpt = array();
    516704
    517705    if(!$this->SmtpConnect()) {
    518       return false;
    519     }
    520 
     706      throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
     707    }
    521708    $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
    522709    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 
     710      throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
     711    }
     712
     713    // Attempt to send attach all recipients
     714    foreach($this->to as $to) {
     715      if (!$this->smtp->Recipient($to[0])) {
     716        $bad_rcpt[] = $to[0];
     717        // implement call back function if it exists
     718        $isSent = 0;
     719        $this->doCallback($isSent,$to[0],'','',$this->Subject,$body);
     720      } else {
     721        // implement call back function if it exists
     722        $isSent = 1;
     723        $this->doCallback($isSent,$to[0],'','',$this->Subject,$body);
     724      }
     725    }
     726    foreach($this->cc as $cc) {
     727      if (!$this->smtp->Recipient($cc[0])) {
     728        $bad_rcpt[] = $cc[0];
     729        // implement call back function if it exists
     730        $isSent = 0;
     731        $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body);
     732      } else {
     733        // implement call back function if it exists
     734        $isSent = 1;
     735        $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body);
     736      }
     737    }
     738    foreach($this->bcc as $bcc) {
     739      if (!$this->smtp->Recipient($bcc[0])) {
     740        $bad_rcpt[] = $bcc[0];
     741        // implement call back function if it exists
     742        $isSent = 0;
     743        $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body);
     744      } else {
     745        // implement call back function if it exists
     746        $isSent = 1;
     747        $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body);
     748      }
     749    }
     750
     751
     752    if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
     753      $badaddresses = implode(', ', $bad_rcpt);
     754      throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
     755    }
    559756    if(!$this->smtp->Data($header . $body)) {
    560       $this->SetError($this->Lang('data_not_accepted'));
    561       $this->smtp->Reset();
    562       return false;
     757      throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
    563758    }
    564759    if($this->SMTPKeepAlive == true) {
    565760      $this->smtp->Reset();
    566     } else {
    567       $this->SmtpClose();
    568     }
    569 
     761    }
    570762    return true;
    571763  }
    572764
    573765  /**
    574    * Initiates a connection to an SMTP server.  Returns false if the
    575    * operation failed.
    576    * @access private
     766   * Initiates a connection to an SMTP server.
     767   * Returns false if the operation failed.
     768   * @uses SMTP
     769   * @access public
    577770   * @return bool
    578771   */
    579   function SmtpConnect() {
    580     if($this->smtp == NULL) {
     772  public function SmtpConnect() {
     773    if(is_null($this->smtp)) {
    581774      $this->smtp = new SMTP();
    582775    }
     
    585778    $hosts = explode(';', $this->Host);
    586779    $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);
     780    $connection = $this->smtp->Connected();
     781
     782    // Retry while there is no connection
     783    try {
     784      while($index < count($hosts) && !$connection) {
     785        $hostinfo = array();
     786        if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
     787          $host = $hostinfo[1];
     788          $port = $hostinfo[2];
    603789        } else {
    604           $this->smtp->Hello($this->ServerHostname());
     790          $host = $hosts[$index];
     791          $port = $this->Port;
    605792        }
    606793
    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;
     794        $tls = ($this->SMTPSecure == 'tls');
     795        $ssl = ($this->SMTPSecure == 'ssl');
     796
     797        if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
     798
     799          $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
     800          $this->smtp->Hello($hello);
     801
     802          if ($tls) {
     803            if (!$this->smtp->StartTLS()) {
     804              throw new phpmailerException($this->Lang('tls'));
     805            }
     806
     807            //We must resend HELO after tls negotiation
     808            $this->smtp->Hello($hello);
     809          }
     810
     811          $connection = true;
     812          if ($this->SMTPAuth) {
     813            if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
     814              throw new phpmailerException($this->Lang('authenticate'));
     815            }
    613816          }
    614817        }
    615       }
    616       $index++;
    617     }
    618     if(!$connection) {
    619       $this->SetError($this->Lang('connect_host'));
    620     }
    621 
    622     return $connection;
     818        $index++;
     819        if (!$connection) {
     820          throw new phpmailerException($this->Lang('connect_host'));
     821        }
     822      }
     823    } catch (phpmailerException $e) {
     824      $this->smtp->Reset();
     825      throw $e;
     826    }
     827    return true;
    623828  }
    624829
     
    627832   * @return void
    628833   */
    629   function SmtpClose() {
    630     if($this->smtp != NULL) {
     834  public function SmtpClose() {
     835    if(!is_null($this->smtp)) {
    631836      if($this->smtp->Connected()) {
    632837        $this->smtp->Quit();
     
    637842
    638843  /**
    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: ';
     844  * Sets the language for all class error messages.
     845  * Returns false if it cannot load the language file.  The default language is English.
     846  * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
     847  * @param string $lang_path Path to the language file directory
     848  * @access public
     849  */
     850  function SetLanguage($langcode = 'en', $lang_path = 'language/') {
     851    //Define full set of translatable strings
     852    $PHPMAILER_LANG = array(
     853      'provide_address' => 'You must provide at least one recipient email address.',
     854      'mailer_not_supported' => ' mailer is not supported.',
     855      'execute' => 'Could not execute: ',
     856      'instantiate' => 'Could not instantiate mail function.',
     857      'authenticate' => 'SMTP Error: Could not authenticate.',
     858      'from_failed' => 'The following From address failed: ',
     859      'recipients_failed' => 'SMTP Error: The following recipients failed: ',
     860      'data_not_accepted' => 'SMTP Error: Data not accepted.',
     861      'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
     862      'file_access' => 'Could not access file: ',
     863      'file_open' => 'File Error: Could not open file: ',
     864      'encoding' => 'Unknown encoding: ',
     865      'signing' => 'Signing Error: ',
     866      'smtp_error' => 'SMTP server error: ',
     867      'empty_message' => 'Message body empty',
     868      'invalid_address' => 'Invalid address',
     869      'variable_set' => 'Cannot set or reset variable: '
     870    );
     871    //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
     872    $l = true;
     873    if ($langcode != 'en') { //There is no English translation file
     874      $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
    667875    }
    668876    $this->language = $PHPMAILER_LANG;
    669 
    670     return true;
     877    return ($l == true); //Returns false if language not found
     878  }
     879
     880  /**
     881  * Return the current array of language strings
     882  * @return array
     883  */
     884  public function GetTranslations() {
     885    return $this->language;
    671886  }
    672887
     
    677892  /**
    678893   * Creates recipient headers.
    679    * @access private
     894   * @access public
    680895   * @return string
    681896   */
    682   function AddrAppend($type, $addr) {
     897  public function AddrAppend($type, $addr) {
    683898    $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     }
     899    $addresses = array();
     900    foreach ($addr as $a) {
     901      $addresses[] = $this->AddrFormat($a);
     902    }
     903    $addr_str .= implode(', ', $addresses);
    690904    $addr_str .= $this->LE;
    691905
     
    695909  /**
    696910   * Formats an address correctly.
    697    * @access private
     911   * @access public
    698912   * @return string
    699913   */
    700   function AddrFormat($addr) {
    701     if(empty($addr[1])) {
    702       $formatted = $this->SecureHeader($addr[0]);
     914  public function AddrFormat($addr) {
     915    if (empty($addr[1])) {
     916      return $this->SecureHeader($addr[0]);
    703917    } else {
    704       $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
    705     }
    706 
    707     return $formatted;
     918      return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
     919    }
    708920  }
    709921
     
    712924   * automatically perform wrapping and for quoted-printable.
    713925   * Original written by philippe.
    714    * @access private
     926   * @param string $message The message to wrap
     927   * @param integer $length The line length to wrap to
     928   * @param boolean $qp_mode Whether to run in Quoted-Printable mode
     929   * @access public
    715930   * @return string
    716931   */
    717   function WrapText($message, $length, $qp_mode = false) {
     932  public function WrapText($message, $length, $qp_mode = false) {
    718933    $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
    719934    // If utf-8 encoding is used, we will need to make sure we don't
     
    7921007   * quoted (printable) encoded string.
    7931008   * Original written by Colin Brown.
    794    * @access private
     1009   * @access public
    7951010   * @param string $encodedText utf-8 QP text
    7961011   * @param int    $maxLength   find last character boundary prior to this length
    7971012   * @return int
    7981013   */
    799   function UTF8CharBoundary($encodedText, $maxLength) {
     1014  public function UTF8CharBoundary($encodedText, $maxLength) {
    8001015    $foundSplitPos = false;
    8011016    $lookBack = 3;
     
    8291044  }
    8301045
     1046
    8311047  /**
    8321048   * Set the body wrapping.
    833    * @access private
     1049   * @access public
    8341050   * @return void
    8351051   */
    836   function SetWordWrap() {
     1052  public function SetWordWrap() {
    8371053    if($this->WordWrap < 1) {
    8381054      return;
     
    8411057    switch($this->message_type) {
    8421058      case 'alt':
    843         /* fall through */
    8441059      case 'alt_attachments':
    8451060        $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
     
    8531068  /**
    8541069   * Assembles message header.
    855    * @access private
    856    * @return string
    857    */
    858   function CreateHeader() {
     1070   * @access public
     1071   * @return string The assembled header
     1072   */
     1073  public function CreateHeader() {
    8591074    $result = '';
    8601075
    861     /* Set the boundaries */
     1076    // Set the boundaries
    8621077    $uniq_id = md5(uniqid(time()));
    8631078    $this->boundary[1] = 'b1_' . $uniq_id;
    8641079    $this->boundary[2] = 'b2_' . $uniq_id;
    8651080
    866     $result .= $this->HeaderLine('Date', $this->RFCDate());
     1081    $result .= $this->HeaderLine('Date', self::RFCDate());
    8671082    if($this->Sender == '') {
    8681083      $result .= $this->HeaderLine('Return-Path', trim($this->From));
     
    8711086    }
    8721087
    873     /* To be created automatically by mail() */
     1088    // To be created automatically by mail()
    8741089    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:;');
     1090      if ($this->SingleTo === true) {
     1091        foreach($this->to as $t) {
     1092          $this->SingleToArray[] = $this->AddrFormat($t);
     1093        }
     1094      } else {
     1095        if(count($this->to) > 0) {
     1096          $result .= $this->AddrAppend('To', $this->to);
     1097        } elseif (count($this->cc) == 0) {
     1098          $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
     1099        }
    8791100      }
    8801101    }
     
    8851106    $result .= $this->AddrAppend('From', $from);
    8861107
    887     /* sendmail and mail() extract Cc from the header before sending */
    888     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
     1108    // sendmail and mail() extract Cc from the header before sending
     1109    if(count($this->cc) > 0) {
    8891110      $result .= $this->AddrAppend('Cc', $this->cc);
    8901111    }
    8911112
    892     /* sendmail and mail() extract Bcc from the header before sending */
     1113    // sendmail and mail() extract Bcc from the header before sending
    8931114    if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
    8941115      $result .= $this->AddrAppend('Bcc', $this->bcc);
     
    8961117
    8971118    if(count($this->ReplyTo) > 0) {
    898       $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
    899     }
    900 
    901     /* mail() sets the subject itself */
     1119      $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
     1120    }
     1121
     1122    // mail() sets the subject itself
    9021123    if($this->Mailer != 'mail') {
    9031124      $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
     
    9101131    }
    9111132    $result .= $this->HeaderLine('X-Priority', $this->Priority);
    912     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');
     1133    $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)');
    9131134
    9141135    if($this->ConfirmReadingTo != '') {
     
    9301151  /**
    9311152   * Returns the message MIME.
    932    * @access private
     1153   * @access public
    9331154   * @return string
    9341155   */
    935   function GetMailMIME() {
     1156  public function GetMailMIME() {
    9361157    $result = '';
    9371158    switch($this->message_type) {
     
    9411162        break;
    9421163      case 'attachments':
    943         /* fall through */
    9441164      case 'alt_attachments':
    9451165        if($this->InlineImageExists()){
     
    9651185  /**
    9661186   * Assembles the message body.  Returns an empty string on failure.
    967    * @access private
    968    * @return string
    969    */
    970   function CreateBody() {
    971     $result = '';
     1187   * @access public
     1188   * @return string The assembled message body
     1189   */
     1190  public function CreateBody() {
     1191    $body = '';
     1192
    9721193    if ($this->sign_key_file) {
    973       $result .= $this->GetMailMIME();
     1194      $body .= $this->GetMailMIME();
    9741195    }
    9751196
     
    9781199    switch($this->message_type) {
    9791200      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]);
     1201        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
     1202        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
     1203        $body .= $this->LE.$this->LE;
     1204        $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
     1205        $body .= $this->EncodeString($this->Body, $this->Encoding);
     1206        $body .= $this->LE.$this->LE;
     1207        $body .= $this->EndBoundary($this->boundary[1]);
    9871208        break;
    9881209      case 'plain':
    989         $result .= $this->EncodeString($this->Body, $this->Encoding);
     1210        $body .= $this->EncodeString($this->Body, $this->Encoding);
    9901211        break;
    9911212      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();
     1213        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
     1214        $body .= $this->EncodeString($this->Body, $this->Encoding);
     1215        $body .= $this->LE;
     1216        $body .= $this->AttachAll();
    9961217        break;
    9971218      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();
     1219        $body .= sprintf("--%s%s", $this->boundary[1], $this->LE);
     1220        $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
     1221        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
     1222        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
     1223        $body .= $this->LE.$this->LE;
     1224        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
     1225        $body .= $this->EncodeString($this->Body, $this->Encoding);
     1226        $body .= $this->LE.$this->LE;
     1227        $body .= $this->EndBoundary($this->boundary[2]);
     1228        $body .= $this->AttachAll();
    10081229        break;
    10091230    }
    10101231
    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);
     1232    if ($this->IsError()) {
     1233      $body = '';
     1234    } elseif ($this->sign_key_file) {
     1235      try {
     1236        $file = tempnam('', 'mail');
     1237        file_put_contents($file, $body); //TODO check this worked
     1238        $signed = tempnam("", "signed");
     1239        if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
     1240          @unlink($file);
     1241          @unlink($signed);
     1242          $body = file_get_contents($signed);
     1243        } else {
     1244          @unlink($file);
     1245          @unlink($signed);
     1246          throw new phpmailerException($this->Lang("signing").openssl_error_string());
    10261247        }
    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;
     1248      } catch (phpmailerException $e) {
     1249        $body = '';
     1250        if ($this->exceptions) {
     1251          throw $e;
     1252        }
     1253      }
     1254    }
     1255
     1256    return $body;
    10381257  }
    10391258
     
    10421261   * @access private
    10431262   */
    1044   function GetBoundary($boundary, $charSet, $contentType, $encoding) {
     1263  private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
    10451264    $result = '';
    10461265    if($charSet == '') {
     
    10661285   * @access private
    10671286   */
    1068   function EndBoundary($boundary) {
     1287  private function EndBoundary($boundary) {
    10691288    return $this->LE . '--' . $boundary . '--' . $this->LE;
    10701289  }
     
    10751294   * @return void
    10761295   */
    1077   function SetMessageType() {
     1296  private function SetMessageType() {
    10781297    if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
    10791298      $this->message_type = 'plain';
     
    10911310  }
    10921311
    1093   /* Returns a formatted header line.
    1094    * @access private
     1312  /**
     1313   *  Returns a formatted header line.
     1314   * @access public
    10951315   * @return string
    10961316   */
    1097   function HeaderLine($name, $value) {
     1317  public function HeaderLine($name, $value) {
    10981318    return $name . ': ' . $value . $this->LE;
    10991319  }
     
    11011321  /**
    11021322   * Returns a formatted mail line.
    1103    * @access private
     1323   * @access public
    11041324   * @return string
    11051325   */
    1106   function TextLine($value) {
     1326  public function TextLine($value) {
    11071327    return $value . $this->LE;
    11081328  }
     
    11221342   * @return bool
    11231343   */
    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 
     1344  public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
     1345    try {
     1346      if ( !@is_file($path) ) {
     1347        throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
     1348      }
     1349      $filename = basename($path);
     1350      if ( $name == '' ) {
     1351        $name = $filename;
     1352      }
     1353
     1354      $this->attachment[] = array(
     1355        0 => $path,
     1356        1 => $filename,
     1357        2 => $name,
     1358        3 => $encoding,
     1359        4 => $type,
     1360        5 => false,  // isStringAttachment
     1361        6 => 'attachment',
     1362        7 => 0
     1363      );
     1364
     1365    } catch (phpmailerException $e) {
     1366      $this->SetError($e->getMessage());
     1367      if ($this->exceptions) {
     1368        throw $e;
     1369      }
     1370      echo $e->getMessage()."\n";
     1371      if ( $e->getCode() == self::STOP_CRITICAL ) {
     1372        return false;
     1373      }
     1374    }
    11451375    return true;
     1376  }
     1377
     1378  /**
     1379  * Return the current array of attachments
     1380  * @return array
     1381  */
     1382  public function GetAttachments() {
     1383    return $this->attachment;
    11461384  }
    11471385
     
    11521390   * @return string
    11531391   */
    1154   function AttachAll() {
    1155     /* Return text of body */
     1392  private function AttachAll() {
     1393    // Return text of body
    11561394    $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];
     1395    $cidUniq = array();
     1396    $incl = array();
     1397
     1398    // Add all attachments
     1399    foreach ($this->attachment as $attachment) {
     1400      // Check for string attachment
     1401      $bString = $attachment[5];
    11621402      if ($bString) {
    1163         $string = $this->attachment[$i][0];
     1403        $string = $attachment[0];
    11641404      } 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];
     1405        $path = $attachment[0];
     1406      }
     1407
     1408      if (in_array($attachment[0], $incl)) { continue; }
     1409      $filename    = $attachment[1];
     1410      $name        = $attachment[2];
     1411      $encoding    = $attachment[3];
     1412      $type        = $attachment[4];
     1413      $disposition = $attachment[6];
     1414      $cid         = $attachment[7];
     1415      $incl[]      = $attachment[0];
     1416      if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
     1417      $cidUniq[$cid] = true;
    11741418
    11751419      $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
     
    11831427      $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
    11841428
    1185       /* Encode as string attachment */
     1429      // Encode as string attachment
    11861430      if($bString) {
    11871431        $mime[] = $this->EncodeString($string, $encoding);
     
    12051449
    12061450  /**
    1207    * Encodes attachment in requested format.  Returns an
    1208    * empty string on failure.
     1451   * Encodes attachment in requested format.
     1452   * Returns an empty string on failure.
     1453   * @param string $path The full path to the file
     1454   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
     1455   * @see EncodeFile()
    12091456   * @access private
    12101457   * @return string
    12111458   */
    1212   function EncodeFile ($path, $encoding = 'base64') {
    1213     if(!@$fd = fopen($path, 'rb')) {
    1214       $this->SetError($this->Lang('file_open') . $path);
     1459  private function EncodeFile($path, $encoding = 'base64') {
     1460    try {
     1461      if (!is_readable($path)) {
     1462        throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
     1463      }
     1464      if (function_exists('get_magic_quotes')) {
     1465        function get_magic_quotes() {
     1466          return false;
     1467        }
     1468      }
     1469      if (PHP_VERSION < 6) {
     1470        $magic_quotes = get_magic_quotes_runtime();
     1471        set_magic_quotes_runtime(0);
     1472      }
     1473      $file_buffer  = file_get_contents($path);
     1474      $file_buffer  = $this->EncodeString($file_buffer, $encoding);
     1475      if (PHP_VERSION < 6) { set_magic_quotes_runtime($magic_quotes); }
     1476      return $file_buffer;
     1477    } catch (Exception $e) {
     1478      $this->SetError($e->getMessage());
    12151479      return '';
    12161480    }
    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
     1481  }
     1482
     1483  /**
     1484   * Encodes string to requested format.
     1485   * Returns an empty string on failure.
     1486   * @param string $str The text to encode
     1487   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
     1488   * @access public
    12311489   * @return string
    12321490   */
    1233   function EncodeString ($str, $encoding = 'base64') {
     1491  public function EncodeString ($str, $encoding = 'base64') {
    12341492    $encoded = '';
    12351493    switch(strtolower($encoding)) {
    12361494      case 'base64':
    1237         /* chunk_split is found in PHP >= 3.0.6 */
    12381495        $encoded = chunk_split(base64_encode($str), 76, $this->LE);
    12391496        break;
     
    12411498      case '8bit':
    12421499        $encoded = $this->FixEOL($str);
     1500        //Make sure it ends with a line break
    12431501        if (substr($encoded, -(strlen($this->LE))) != $this->LE)
    12441502          $encoded .= $this->LE;
     
    12581516
    12591517  /**
    1260    * Encode a header string to best of Q, B, quoted or none.
    1261    * @access private
     1518   * Encode a header string to best (shortest) of Q, B, quoted or none.
     1519   * @access public
    12621520   * @return string
    12631521   */
    1264   function EncodeHeader ($str, $position = 'text') {
     1522  public function EncodeHeader($str, $position = 'text') {
    12651523    $x = 0;
    12661524
     
    12681526      case 'phrase':
    12691527        if (!preg_match('/[\200-\377]/', $str)) {
    1270           /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
     1528          // Can't use addslashes as we don't know what value has magic_quotes_sybase
    12711529          $encoded = addcslashes($str, "\0..\37\177\\\"");
    12721530          if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
     
    12801538      case 'comment':
    12811539        $x = preg_match_all('/[()"]/', $str, $matches);
    1282         /* Fall-through */
     1540        // Fall-through
    12831541      case 'text':
    12841542      default:
     
    12921550
    12931551    $maxlen = 75 - 7 - strlen($this->CharSet);
    1294     /* Try to select the encoding which should produce the shortest output */
     1552    // Try to select the encoding which should produce the shortest output
    12951553    if (strlen($str)/3 < $x) {
    12961554      $encoding = 'B';
    12971555      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
     1556        // Use a custom function which correctly encodes and wraps long
     1557        // multibyte strings without breaking lines within a character
    13001558        $encoded = $this->Base64EncodeWrapMB($str);
    13011559      } else {
     
    13191577  /**
    13201578   * Checks if a string contains multibyte characters.
    1321    * @access private
     1579   * @access public
    13221580   * @param string $str multi-byte text to wrap encode
    13231581   * @return bool
    13241582   */
    1325   function HasMultiBytes($str) {
     1583  public function HasMultiBytes($str) {
    13261584    if (function_exists('mb_strlen')) {
    13271585      return (strlen($str) > mb_strlen($str, $this->CharSet));
    13281586    } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
    1329       return False;
     1587      return false;
    13301588    }
    13311589  }
     
    13351593   * without breaking lines within a character.
    13361594   * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
    1337    * @access private
     1595   * @access public
    13381596   * @param string $str multi-byte text to wrap encode
    13391597   * @return string
    13401598   */
    1341   function Base64EncodeWrapMB($str) {
     1599  public function Base64EncodeWrapMB($str) {
    13421600    $start = "=?".$this->CharSet."?B?";
    13431601    $end = "?=";
     
    13721630
    13731631  /**
    1374    * Encode string to quoted-printable.
    1375    * @access private
    1376    * @return string
    1377    */
    1378   function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
     1632  * Encode string to quoted-printable.
     1633  * Only uses standard PHP, slow, but will always work
     1634  * @access public
     1635  * @param string $string the text to encode
     1636  * @param integer $line_max Number of chars allowed on a line before wrapping
     1637  * @return string
     1638  */
     1639  public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
    13791640    $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
    13801641    $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
     
    14181679
    14191680  /**
    1420    * Callback for converting to "=XX".
    1421    * @access private
     1681  * Encode string to RFC2045 (6.7) quoted-printable format
     1682  * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
     1683  * Also results in same content as you started with after decoding
     1684  * @see EncodeQPphp()
     1685  * @access public
     1686  * @param string $string the text to encode
     1687  * @param integer $line_max Number of chars allowed on a line before wrapping
     1688  * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
     1689  * @return string
     1690  * @author Marcus Bointon
     1691  */
     1692  public function EncodeQP($string, $line_max = 76, $space_conv = false) {
     1693    if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
     1694      return quoted_printable_encode($string);
     1695    }
     1696    $filters = stream_get_filters();
     1697    if (!in_array('convert.*', $filters)) { //Got convert stream filter?
     1698      return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
     1699    }
     1700    $fp = fopen('php://temp/', 'r+');
     1701    $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
     1702    $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
     1703    $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
     1704    fputs($fp, $string);
     1705    rewind($fp);
     1706    $out = stream_get_contents($fp);
     1707    stream_filter_remove($s);
     1708    $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
     1709    fclose($fp);
     1710    return $out;
     1711  }
     1712
     1713  /**
     1714   * Encode string to q encoding.
     1715   * @link http://tools.ietf.org/html/rfc2047
     1716   * @param string $str the text to encode
     1717   * @param string $position Where the text is going to be used, see the RFC for what that means
     1718   * @access public
    14221719   * @return string
    14231720   */
    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);
     1721  public function EncodeQ ($str, $position = 'text') {
     1722    // There should not be any EOL in the string
     1723    $encoded = preg_replace('/[\r\n]*/', '', $str);
    14361724
    14371725    switch (strtolower($position)) {
    14381726      case 'phrase':
    1439         $encoded = preg_replace_callback("/([^A-Za-z0-9!*+\/ -])/",
    1440                                          array('PHPMailer', 'EncodeQ_callback'), $encoded);
     1727        $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
    14411728        break;
    14421729      case 'comment':
    1443         $encoded = preg_replace_callback("/([\(\)\"])/",
    1444                                          array('PHPMailer', 'EncodeQ_callback'), $encoded);
    1445         break;
     1730        $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
    14461731      case 'text':
    14471732      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);
     1733        // Replace every high ascii, control =, ? and _ characters
     1734        //TODO using /e (equivalent to eval()) is probably not a good idea
     1735        $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
     1736              "'='.sprintf('%02X', ord('\\1'))", $encoded);
    14511737        break;
    14521738    }
    14531739
    1454     /* Replace every spaces to _ (more readable than =20) */
     1740    // Replace every spaces to _ (more readable than =20)
    14551741    $encoded = str_replace(' ', '_', $encoded);
    14561742
     
    14681754   * @return void
    14691755   */
    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;
     1756  public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
     1757    // Append to $attachment array
     1758    $this->attachment[] = array(
     1759      0 => $string,
     1760      1 => $filename,
     1761      2 => basename($filename),
     1762      3 => $encoding,
     1763      4 => $type,
     1764      5 => true,  // isStringAttachment
     1765      6 => 'attachment',
     1766      7 => 0
     1767    );
    14811768  }
    14821769
     
    14941781   * @return bool
    14951782   */
    1496   function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
    1497 
    1498     if(!@is_file($path)) {
     1783  public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
     1784
     1785    if ( !@is_file($path) ) {
    14991786      $this->SetError($this->Lang('file_access') . $path);
    15001787      return false;
     
    15021789
    15031790    $filename = basename($path);
    1504     if($name == '') {
     1791    if ( $name == '' ) {
    15051792      $name = $filename;
    15061793    }
    15071794
    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;
     1795    // Append to $attachment array
     1796    $this->attachment[] = array(
     1797      0 => $path,
     1798      1 => $filename,
     1799      2 => $name,
     1800      3 => $encoding,
     1801      4 => $type,
     1802      5 => false,  // isStringAttachment
     1803      6 => 'inline',
     1804      7 => $cid
     1805    );
    15181806
    15191807    return true;
     
    15221810  /**
    15231811   * Returns true if an inline attachment is present.
    1524    * @access private
     1812   * @access public
    15251813   * @return bool
    15261814   */
    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;
     1815  public function InlineImageExists() {
     1816    foreach($this->attachment as $attachment) {
     1817      if ($attachment[6] == 'inline') {
     1818        return true;
     1819      }
     1820    }
     1821    return false;
    15371822  }
    15381823
     
    15451830   * @return void
    15461831   */
    1547   function ClearAddresses() {
     1832  public function ClearAddresses() {
     1833    foreach($this->to as $to) {
     1834      unset($this->all_recipients[strtolower($to[0])]);
     1835    }
    15481836    $this->to = array();
    15491837  }
     
    15531841   * @return void
    15541842   */
    1555   function ClearCCs() {
     1843  public function ClearCCs() {
     1844    foreach($this->cc as $cc) {
     1845      unset($this->all_recipients[strtolower($cc[0])]);
     1846    }
    15561847    $this->cc = array();
    15571848  }
     
    15611852   * @return void
    15621853   */
    1563   function ClearBCCs() {
     1854  public function ClearBCCs() {
     1855    foreach($this->bcc as $bcc) {
     1856      unset($this->all_recipients[strtolower($bcc[0])]);
     1857    }
    15641858    $this->bcc = array();
    15651859  }
     
    15691863   * @return void
    15701864   */
    1571   function ClearReplyTos() {
     1865  public function ClearReplyTos() {
    15721866    $this->ReplyTo = array();
    15731867  }
     
    15781872   * @return void
    15791873   */
    1580   function ClearAllRecipients() {
     1874  public function ClearAllRecipients() {
    15811875    $this->to = array();
    15821876    $this->cc = array();
    15831877    $this->bcc = array();
     1878    $this->all_recipients = array();
    15841879  }
    15851880
     
    15891884   * @return void
    15901885   */
    1591   function ClearAttachments() {
     1886  public function ClearAttachments() {
    15921887    $this->attachment = array();
    15931888  }
     
    15971892   * @return void
    15981893   */
    1599   function ClearCustomHeaders() {
     1894  public function ClearCustomHeaders() {
    16001895    $this->CustomHeader = array();
    16011896  }
     
    16071902  /**
    16081903   * Adds the error message to the error container.
    1609    * Returns void.
    1610    * @access private
     1904   * @access protected
    16111905   * @return void
    16121906   */
    1613   function SetError($msg) {
     1907  protected function SetError($msg) {
    16141908    $this->error_count++;
     1909    if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
     1910      $lasterror = $this->smtp->getError();
     1911      if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
     1912        $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
     1913      }
     1914    }
    16151915    $this->ErrorInfo = $msg;
    16161916  }
     
    16181918  /**
    16191919   * Returns the proper RFC 822 formatted date.
    1620    * @access private
     1920   * @access public
    16211921   * @return string
    1622    */
    1623   function RFCDate() {
     1922   * @static
     1923   */
     1924  public static function RFCDate() {
    16241925    $tz = date('Z');
    16251926    $tzs = ($tz < 0) ? '-' : '+';
     
    16321933
    16331934  /**
    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   /**
    16591935   * Returns the server hostname or 'localhost.localdomain' if unknown.
    16601936   * @access private
    16611937   * @return string
    16621938   */
    1663   function ServerHostname() {
    1664     if ($this->Hostname != '') {
     1939  private function ServerHostname() {
     1940    if (!empty($this->Hostname)) {
    16651941      $result = $this->Hostname;
    1666     } elseif ($this->ServerVar('SERVER_NAME') != '') {
    1667       $result = $this->ServerVar('SERVER_NAME');
     1942    } elseif (isset($_SERVER['SERVER_NAME'])) {
     1943      $result = $_SERVER['SERVER_NAME'];
    16681944    } else {
    16691945      $result = 'localhost.localdomain';
     
    16781954   * @return string
    16791955   */
    1680   function Lang($key) {
     1956  private function Lang($key) {
    16811957    if(count($this->language) < 1) {
    16821958      $this->SetLanguage('en'); // set the default language
     
    16921968  /**
    16931969   * Returns true if an error occurred.
     1970   * @access public
    16941971   * @return bool
    16951972   */
    1696   function IsError() {
     1973  public function IsError() {
    16971974    return ($this->error_count > 0);
    16981975  }
     
    17031980   * @return string
    17041981   */
    1705   function FixEOL($str) {
     1982  private function FixEOL($str) {
    17061983    $str = str_replace("\r\n", "\n", $str);
    17071984    $str = str_replace("\r", "\n", $str);
     
    17121989  /**
    17131990   * Adds a custom header.
     1991   * @access public
    17141992   * @return void
    17151993   */
    1716   function AddCustomHeader($custom_header) {
     1994  public function AddCustomHeader($custom_header) {
    17171995    $this->CustomHeader[] = explode(':', $custom_header, 2);
    17181996  }
     
    17232001   * @return $message
    17242002   */
    1725   function MsgHTML($message,$basedir='') {
     2003  public function MsgHTML($message, $basedir = '') {
    17262004    preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
    17272005    if(isset($images[2])) {
    17282006      foreach($images[2] as $i => $url) {
    17292007        // do not change urls for absolute images (thanks to corvuscorax)
    1730         if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) {
     2008        if (!preg_match('#^[A-z]+://#',$url)) {
    17312009          $filename = basename($url);
    17322010          $directory = dirname($url);
    17332011          ($directory == '.')?$directory='':'';
    17342012          $cid = 'cid:' . md5($filename);
    1735           $fileParts = split("\.", $filename);
    1736           $ext = $fileParts[1];
    1737           $mimeType = $this->_mime_types($ext);
     2013          $ext = pathinfo($filename, PATHINFO_EXTENSION);
     2014          $mimeType  = self::_mime_types($ext);
    17382015          if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
    17392016          if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
     
    17472024    $this->Body = $message;
    17482025    $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
    1749     if ( !empty($textMsg) && empty($this->AltBody) ) {
     2026    if (!empty($textMsg) && empty($this->AltBody)) {
    17502027      $this->AltBody = html_entity_decode($textMsg);
    17512028    }
    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 = '') {
     2029    if (empty($this->AltBody)) {
     2030      $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
     2031    }
     2032  }
     2033
     2034  /**
     2035   * Gets the MIME type of the embedded or inline image
     2036   * @param string File extension
     2037   * @access public
     2038   * @return string MIME type of ext
     2039   * @static
     2040   */
     2041  public static function _mime_types($ext = '') {
    17632042    $mimes = array(
     2043      'hqx'   =>  'application/mac-binhex40',
     2044      'cpt'   =>  'application/mac-compactpro',
     2045      'doc'   =>  'application/msword',
     2046      'bin'   =>  'application/macbinary',
     2047      'dms'   =>  'application/octet-stream',
     2048      'lha'   =>  'application/octet-stream',
     2049      'lzh'   =>  'application/octet-stream',
     2050      'exe'   =>  'application/octet-stream',
     2051      'class' =>  'application/octet-stream',
     2052      'psd'   =>  'application/octet-stream',
     2053      'so'    =>  'application/octet-stream',
     2054      'sea'   =>  'application/octet-stream',
     2055      'dll'   =>  'application/octet-stream',
     2056      'oda'   =>  'application/oda',
     2057      'pdf'   =>  'application/pdf',
    17642058      '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',
     2059      'eps'   =>  'application/postscript',
     2060      'ps'    =>  'application/postscript',
     2061      'smi'   =>  'application/smil',
     2062      'smil'  =>  'application/smil',
     2063      'mif'   =>  'application/vnd.mif',
     2064      'xls'   =>  'application/vnd.ms-excel',
     2065      'ppt'   =>  'application/vnd.ms-powerpoint',
     2066      'wbxml' =>  'application/vnd.wap.wbxml',
     2067      'wmlc'  =>  'application/vnd.wap.wmlc',
    17742068      'dcr'   =>  'application/x-director',
    17752069      'dir'   =>  'application/x-director',
    1776       'dll'   =>  'application/octet-stream',
    1777       'dms'   =>  'application/octet-stream',
    1778       'doc'   =>  'application/msword',
     2070      'dxr'   =>  'application/x-director',
    17792071      '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',
    17852072      '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',
     2073      'php'   =>  'application/x-httpd-php',
     2074      'php4'  =>  'application/x-httpd-php',
     2075      'php3'  =>  'application/x-httpd-php',
     2076      'phtml' =>  'application/x-httpd-php',
     2077      'phps'  =>  'application/x-httpd-php-source',
    17922078      'js'    =>  'application/x-javascript',
    1793       'lha'   =>  'application/octet-stream',
    1794       'log'   =>  'text/plain',
    1795       'lzh'   =>  'application/octet-stream',
     2079      'swf'   =>  'application/x-shockwave-flash',
     2080      'sit'   =>  'application/x-stuffit',
     2081      'tar'   =>  'application/x-tar',
     2082      'tgz'   =>  'application/x-tar',
     2083      'xhtml' =>  'application/xhtml+xml',
     2084      'xht'   =>  'application/xhtml+xml',
     2085      'zip'   =>  'application/zip',
    17962086      'mid'   =>  'audio/midi',
    17972087      'midi'  =>  'audio/midi',
    1798       'mif'   =>  'application/vnd.mif',
    1799       'mov'   =>  'video/quicktime',
    1800       'movie' =>  'video/x-sgi-movie',
     2088      'mpga'  =>  'audio/mpeg',
    18012089      'mp2'   =>  'audio/mpeg',
    18022090      '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',
     2091      'aif'   =>  'audio/x-aiff',
     2092      'aiff'  =>  'audio/x-aiff',
     2093      'aifc'  =>  'audio/x-aiff',
    18202094      'ram'   =>  'audio/x-pn-realaudio',
    18212095      'rm'    =>  'audio/x-pn-realaudio',
    18222096      'rpm'   =>  'audio/x-pn-realaudio-plugin',
     2097      'ra'    =>  'audio/x-realaudio',
     2098      'rv'    =>  'video/vnd.rn-realvideo',
     2099      'wav'   =>  'audio/x-wav',
     2100      'bmp'   =>  'image/bmp',
     2101      'gif'   =>  'image/gif',
     2102      'jpeg'  =>  'image/jpeg',
     2103      'jpg'   =>  'image/jpeg',
     2104      'jpe'   =>  'image/jpeg',
     2105      'png'   =>  'image/png',
     2106      'tiff'  =>  'image/tiff',
     2107      'tif'   =>  'image/tiff',
     2108      'css'   =>  'text/css',
     2109      'html'  =>  'text/html',
     2110      'htm'   =>  'text/html',
     2111      'shtml' =>  'text/html',
     2112      'txt'   =>  'text/plain',
     2113      'text'  =>  'text/plain',
     2114      'log'   =>  'text/plain',
     2115      'rtx'   =>  'text/richtext',
    18232116      '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',
    18472117      'xml'   =>  'text/xml',
    18482118      'xsl'   =>  'text/xml',
    1849       'zip'   =>  'application/zip'
     2119      'mpeg'  =>  'video/mpeg',
     2120      'mpg'   =>  'video/mpeg',
     2121      'mpe'   =>  'video/mpeg',
     2122      'qt'    =>  'video/quicktime',
     2123      'mov'   =>  'video/quicktime',
     2124      'avi'   =>  'video/x-msvideo',
     2125      'movie' =>  'video/x-sgi-movie',
     2126      'doc'   =>  'application/msword',
     2127      'word'  =>  'application/msword',
     2128      'xl'    =>  'application/excel',
     2129      'eml'   =>  'message/rfc822'
    18502130    );
    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     }
     2131    return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
     2132  }
     2133
     2134  /**
     2135  * Set (or reset) Class Objects (variables)
     2136  *
     2137  * Usage Example:
     2138  * $page->set('X-Priority', '3');
     2139  *
     2140  * @access public
     2141  * @param string $name Parameter Name
     2142  * @param mixed $value Parameter Value
     2143  * NOTE: will not work with arrays, there are no arrays to set/reset
     2144  * @todo Should this not be using __set() magic function?
     2145  */
     2146  public function set($name, $value = '') {
     2147    try {
     2148      if (isset($this->$name) ) {
     2149        $this->$name = $value;
     2150      } else {
     2151        throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
     2152      }
     2153    } catch (Exception $e) {
     2154      $this->SetError($e->getMessage());
     2155      if ($e->getCode() == self::STOP_CRITICAL) {
     2156        return false;
     2157      }
     2158    }
     2159    return true;
    18912160  }
    18922161
    18932162  /**
    18942163   * Strips newlines to prevent header injection.
    1895    * @access private
     2164   * @access public
    18962165   * @param string $str String
    18972166   * @return string
    18982167   */
    1899   function SecureHeader($str) {
    1900     $str = trim($str);
    1901     $str = str_replace("\r", "", $str);
    1902     $str = str_replace("\n", "", $str);
    1903     return $str;
     2168  public function SecureHeader($str) {
     2169    $str = str_replace("\r", '', $str);
     2170    $str = str_replace("\n", '', $str);
     2171    return trim($str);
    19042172  }
    19052173
     
    19112179   * @param string $key_pass Password for private key
    19122180   */
    1913   function Sign($cert_filename, $key_filename, $key_pass) {
     2181  public function Sign($cert_filename, $key_filename, $key_pass) {
    19142182    $this->sign_cert_file = $cert_filename;
    19152183    $this->sign_key_file = $key_filename;
     
    19172185  }
    19182186
     2187  /**
     2188   * Set the private key file and password to sign the message.
     2189   *
     2190   * @access public
     2191   * @param string $key_filename Parameter File Name
     2192   * @param string $key_pass Password for private key
     2193   */
     2194  public function DKIM_QP($txt) {
     2195    $tmp="";
     2196    $line="";
     2197    for ($i=0;$i<strlen($txt);$i++) {
     2198      $ord=ord($txt[$i]);
     2199      if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
     2200        $line.=$txt[$i];
     2201      } else {
     2202        $line.="=".sprintf("%02X",$ord);
     2203      }
     2204    }
     2205    return $line;
     2206  }
     2207
     2208  /**
     2209   * Generate DKIM signature
     2210   *
     2211   * @access public
     2212   * @param string $s Header
     2213   */
     2214  public function DKIM_Sign($s) {
     2215    $privKeyStr = file_get_contents($this->DKIM_private);
     2216    if ($this->DKIM_passphrase!='') {
     2217      $privKey = openssl_pkey_get_private($privKeyStr,$this->DKIM_passphrase);
     2218    } else {
     2219      $privKey = $privKeyStr;
     2220    }
     2221    if (openssl_sign($s, $signature, $privKey)) {
     2222      return base64_encode($signature);
     2223    }
     2224  }
     2225
     2226  /**
     2227   * Generate DKIM Canonicalization Header
     2228   *
     2229   * @access public
     2230   * @param string $s Header
     2231   */
     2232  public function DKIM_HeaderC($s) {
     2233    $s=preg_replace("/\r\n\s+/"," ",$s);
     2234    $lines=explode("\r\n",$s);
     2235    foreach ($lines as $key=>$line) {
     2236      list($heading,$value)=explode(":",$line,2);
     2237      $heading=strtolower($heading);
     2238      $value=preg_replace("/\s+/"," ",$value) ; // Compress useless spaces
     2239      $lines[$key]=$heading.":".trim($value) ; // Don't forget to remove WSP around the value
     2240    }
     2241    $s=implode("\r\n",$lines);
     2242    return $s;
     2243  }
     2244
     2245  /**
     2246   * Generate DKIM Canonicalization Body
     2247   *
     2248   * @access public
     2249   * @param string $body Message Body
     2250   */
     2251  public function DKIM_BodyC($body) {
     2252    if ($body == '') return "\r\n";
     2253    // stabilize line endings
     2254    $body=str_replace("\r\n","\n",$body);
     2255    $body=str_replace("\n","\r\n",$body);
     2256    // END stabilize line endings
     2257    while (substr($body,strlen($body)-4,4) == "\r\n\r\n") {
     2258      $body=substr($body,0,strlen($body)-2);
     2259    }
     2260    return $body;
     2261  }
     2262
     2263  /**
     2264   * Create the DKIM header, body, as new header
     2265   *
     2266   * @access public
     2267   * @param string $headers_line Header lines
     2268   * @param string $subject Subject
     2269   * @param string $body Body
     2270   */
     2271  public function DKIM_Add($headers_line,$subject,$body) {
     2272    $DKIMsignatureType    = 'rsa-sha1'; // Signature & hash algorithms
     2273    $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
     2274    $DKIMquery            = 'dns/txt'; // Query method
     2275    $DKIMtime             = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
     2276    $subject_header       = "Subject: $subject";
     2277    $headers              = explode("\r\n",$headers_line);
     2278    foreach($headers as $header) {
     2279      if (strpos($header,'From:') === 0) {
     2280        $from_header=$header;
     2281      } elseif (strpos($header,'To:') === 0) {
     2282        $to_header=$header;
     2283      }
     2284    }
     2285    $from     = str_replace('|','=7C',$this->DKIM_QP($from_header));
     2286    $to       = str_replace('|','=7C',$this->DKIM_QP($to_header));
     2287    $subject  = str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
     2288    $body     = $this->DKIM_BodyC($body);
     2289    $DKIMlen  = strlen($body) ; // Length of body
     2290    $DKIMb64  = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
     2291    $ident    = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
     2292    $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
     2293                "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
     2294                "\th=From:To:Subject;\r\n".
     2295                "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
     2296                "\tz=$from\r\n".
     2297                "\t|$to\r\n".
     2298                "\t|$subject;\r\n".
     2299                "\tbh=" . $DKIMb64 . ";\r\n".
     2300                "\tb=";
     2301    $toSign   = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
     2302    $signed   = $this->DKIM_Sign($toSign);
     2303    return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n";
     2304  }
     2305
     2306  protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) {
     2307    if (!empty($this->action_function) && function_exists($this->action_function)) {
     2308      $params = array($isSent,$to,$cc,$bcc,$subject,$body);
     2309      call_user_func_array($this->action_function,$params);
     2310    }
     2311  }
    19192312}
    19202313
     2314class phpmailerException extends Exception {
     2315  public function errorMessage() {
     2316    $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
     2317    return $errorMsg;
     2318  }
     2319}
    19212320?>
  • trunk/wp-includes/class-smtp.php

    r13425 r17676  
    33.---------------------------------------------------------------------------.
    44|  Software: PHPMailer - PHP email class                                    |
    5 |   Version: 2.0.4                                                          |
     5|   Version: 5.1                                                            |
    66|   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
    77|      Info: http://phpmailer.sourceforge.net                               |
    88|   Support: http://sourceforge.net/projects/phpmailer/                     |
    99| ------------------------------------------------------------------------- |
    10 |    Author: Andy Prevost (project admininistrator)                         |
    11 |    Author: Brent R. Matzelle (original founder)                           |
    12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
     10|     Admin: Andy Prevost (project admininistrator)                         |
     11|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
     12|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
     13|   Founder: Brent R. Matzelle (original founder)                           |
     14| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
    1315| Copyright (c) 2001-2003, Brent R. Matzelle                                |
    1416| ------------------------------------------------------------------------- |
     
    2426| - Oursourcing (highly qualified programmers and graphic designers)        |
    2527'---------------------------------------------------------------------------'
     28*/
     29
     30/**
     31 * PHPMailer - PHP SMTP email transport class
     32 * NOTE: Designed for use with PHP version 5 and up
     33 * @package PHPMailer
     34 * @author Andy Prevost
     35 * @author Marcus Bointon
     36 * @copyright 2004 - 2008 Andy Prevost
     37 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
     38 * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $
    2639 */
     40
    2741/**
    2842 * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
     
    3044 * error. SMTP also provides some utility methods for sending mail
    3145 * to an SMTP server.
    32  * @package PHPMailer
    33  * @author Chris Ryan
     46 * original author: Chris Ryan
    3447 */
    3548
    36 class SMTP
    37 {
     49class SMTP {
    3850  /**
    3951   *  SMTP server port
    4052   *  @var int
    4153   */
    42   var $SMTP_PORT = 25;
     54  public $SMTP_PORT = 25;
    4355
    4456  /**
     
    4658   *  @var string
    4759   */
    48   var $CRLF = "\r\n";
     60  public $CRLF = "\r\n";
    4961
    5062  /**
     
    5264   *  @var bool
    5365   */
    54   var $do_debug;       # the level of debug to perform
     66  public $do_debug;       // the level of debug to perform
    5567
    5668  /**
     
    5870   *  @var bool
    5971   */
    60   var $do_verp = false;
    61 
    62   /**#@+
    63    * @access private
    64    */
    65   var $smtp_conn;      # the socket to the server
    66   var $error;          # error if any on the last call
    67   var $helo_rply;      # the reply the server sent to us for HELO
    68   /**#@-*/
     72  public $do_verp = false;
     73
     74  /////////////////////////////////////////////////
     75  // PROPERTIES, PRIVATE AND PROTECTED
     76  /////////////////////////////////////////////////
     77
     78  private $smtp_conn; // the socket to the server
     79  private $error;     // error if any on the last call
     80  private $helo_rply; // the reply the server sent to us for HELO
    6981
    7082  /**
     
    7385   * @return void
    7486   */
    75   function SMTP() {
     87  public function __construct() {
    7688    $this->smtp_conn = 0;
    7789    $this->error = null;
     
    8193  }
    8294
    83   /*************************************************************
    84    *                    CONNECTION FUNCTIONS                  *
    85    ***********************************************************/
     95  /////////////////////////////////////////////////
     96  // CONNECTION FUNCTIONS
     97  /////////////////////////////////////////////////
    8698
    8799  /**
     
    98110   * @return bool
    99111   */
    100   function Connect($host,$port=0,$tval=30) {
    101     # set the error val to null so there is no confusion
     112  public function Connect($host, $port = 0, $tval = 30) {
     113    // set the error val to null so there is no confusion
    102114    $this->error = null;
    103115
    104     # make sure we are __not__ connected
     116    // make sure we are __not__ connected
    105117    if($this->connected()) {
    106       # ok we are connected! what should we do?
    107       # for now we will just give an error saying we
    108       # are already connected
     118      // already connected, generate error
    109119      $this->error = array("error" => "Already connected to a server");
    110120      return false;
     
    115125    }
    116126
    117     #connect to the smtp server
    118     $this->smtp_conn = fsockopen($host,    # the host of the server
    119                                  $port,    # the port to use
    120                                  $errno,   # error number if any
    121                                  $errstr,  # error message if any
    122                                  $tval);   # give up after ? secs
    123     # verify we connected properly
     127    // connect to the smtp server
     128    $this->smtp_conn = @fsockopen($host,    // the host of the server
     129                                 $port,    // the port to use
     130                                 $errno,   // error number if any
     131                                 $errstr,  // error message if any
     132                                 $tval);   // give up after ? secs
     133    // verify we connected properly
    124134    if(empty($this->smtp_conn)) {
    125135      $this->error = array("error" => "Failed to connect to server",
     
    127137                           "errstr" => $errstr);
    128138      if($this->do_debug >= 1) {
    129         echo "SMTP -> ERROR: " . $this->error["error"] .
    130                  ": $errstr ($errno)" . $this->CRLF;
    131       }
    132       return false;
    133     }
    134 
    135     # sometimes the SMTP server takes a little longer to respond
    136     # so we will give it a longer timeout for the first read
    137     // Windows still does not have support for this timeout function
     139        echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
     140      }
     141      return false;
     142    }
     143
     144    // SMTP server can take longer to respond, give longer timeout for first read
     145    // Windows does not have support for this timeout function
    138146    if(substr(PHP_OS, 0, 3) != "WIN")
    139147     socket_set_timeout($this->smtp_conn, $tval, 0);
    140148
    141     # get any announcement stuff
     149    // get any announcement
    142150    $announce = $this->get_lines();
    143151
    144     # set the timeout  of any socket functions at 1/10 of a second
    145     //if(function_exists("socket_set_timeout"))
    146     //   socket_set_timeout($this->smtp_conn, 0, 100000);
    147 
    148     if($this->do_debug >= 2) {
    149       echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
     152    if($this->do_debug >= 2) {
     153      echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
     154    }
     155
     156    return true;
     157  }
     158
     159  /**
     160   * Initiate a TLS communication with the server.
     161   *
     162   * SMTP CODE 220 Ready to start TLS
     163   * SMTP CODE 501 Syntax error (no parameters allowed)
     164   * SMTP CODE 454 TLS not available due to temporary reason
     165   * @access public
     166   * @return bool success
     167   */
     168  public function StartTLS() {
     169    $this->error = null; # to avoid confusion
     170
     171    if(!$this->connected()) {
     172      $this->error = array("error" => "Called StartTLS() without being connected");
     173      return false;
     174    }
     175
     176    fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
     177
     178    $rply = $this->get_lines();
     179    $code = substr($rply,0,3);
     180
     181    if($this->do_debug >= 2) {
     182      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
     183    }
     184
     185    if($code != 220) {
     186      $this->error =
     187         array("error"     => "STARTTLS not accepted from server",
     188               "smtp_code" => $code,
     189               "smtp_msg"  => substr($rply,4));
     190      if($this->do_debug >= 1) {
     191        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
     192      }
     193      return false;
     194    }
     195
     196    // Begin encrypted connection
     197    if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
     198      return false;
    150199    }
    151200
     
    159208   * @return bool
    160209   */
    161   function Authenticate($username, $password) {
     210  public function Authenticate($username, $password) {
    162211    // Start authentication
    163212    fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
     
    172221              "smtp_msg" => substr($rply,4));
    173222      if($this->do_debug >= 1) {
    174         echo "SMTP -> ERROR: " . $this->error["error"] .
    175                  ": " . $rply . $this->CRLF;
     223        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    176224      }
    177225      return false;
     
    190238              "smtp_msg" => substr($rply,4));
    191239      if($this->do_debug >= 1) {
    192         echo "SMTP -> ERROR: " . $this->error["error"] .
    193                  ": " . $rply . $this->CRLF;
     240        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    194241      }
    195242      return false;
     
    208255              "smtp_msg" => substr($rply,4));
    209256      if($this->do_debug >= 1) {
    210         echo "SMTP -> ERROR: " . $this->error["error"] .
    211                  ": " . $rply . $this->CRLF;
     257        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    212258      }
    213259      return false;
     
    219265  /**
    220266   * Returns true if connected to a server otherwise false
    221    * @access private
    222    * @return bool
    223    */
    224   function Connected() {
     267   * @access public
     268   * @return bool
     269   */
     270  public function Connected() {
    225271    if(!empty($this->smtp_conn)) {
    226272      $sock_status = socket_get_status($this->smtp_conn);
    227273      if($sock_status["eof"]) {
    228         # hmm this is an odd situation... the socket is
    229         # valid but we are not connected anymore
     274        // the socket is valid but we are not connected
    230275        if($this->do_debug >= 1) {
    231             echo "SMTP -> NOTICE:" . $this->CRLF .
    232                  "EOF caught while checking if connected";
     276            echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
    233277        }
    234278        $this->Close();
    235279        return false;
    236280      }
    237       return true; # everything looks good
     281      return true; // everything looks good
    238282    }
    239283    return false;
     
    247291   * @return void
    248292   */
    249   function Close() {
    250     $this->error = null; # so there is no confusion
     293  public function Close() {
     294    $this->error = null; // so there is no confusion
    251295    $this->helo_rply = null;
    252296    if(!empty($this->smtp_conn)) {
    253       # close the connection and cleanup
     297      // close the connection and cleanup
    254298      fclose($this->smtp_conn);
    255299      $this->smtp_conn = 0;
     
    257301  }
    258302
    259   /***************************************************************
    260    *                        SMTP COMMANDS                       *
    261    *************************************************************/
     303  /////////////////////////////////////////////////
     304  // SMTP COMMANDS
     305  /////////////////////////////////////////////////
    262306
    263307  /**
     
    266310   * that is to be send with the headers. Each header needs to be
    267311   * on a single line followed by a <CRLF> with the message headers
    268    * and the message body being separated by and additional <CRLF>.
     312   * and the message body being seperated by and additional <CRLF>.
    269313   *
    270314   * Implements rfc 821: DATA <CRLF>
     
    280324   * @return bool
    281325   */
    282   function Data($msg_data) {
    283     $this->error = null; # so no confusion is caused
     326  public function Data($msg_data) {
     327    $this->error = null; // so no confusion is caused
    284328
    285329    if(!$this->connected()) {
     
    295339
    296340    if($this->do_debug >= 2) {
    297       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     341      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    298342    }
    299343
     
    304348              "smtp_msg" => substr($rply,4));
    305349      if($this->do_debug >= 1) {
    306         echo "SMTP -> ERROR: " . $this->error["error"] .
    307                  ": " . $rply . $this->CRLF;
    308       }
    309       return false;
    310     }
    311 
    312     # the server is ready to accept data!
    313     # according to rfc 821 we should not send more than 1000
    314     # including the CRLF
    315     # characters on a single line so we will break the data up
    316     # into lines by \r and/or \n then if needed we will break
    317     # each of those into smaller lines to fit within the limit.
    318     # in addition we will be looking for lines that start with
    319     # a period '.' and append and additional period '.' to that
    320     # line. NOTE: this does not count towards are limit.
    321 
    322     # normalize the line breaks so we know the explode works
     350        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
     351      }
     352      return false;
     353    }
     354
     355    /* the server is ready to accept data!
     356     * according to rfc 821 we should not send more than 1000
     357     * including the CRLF
     358     * characters on a single line so we will break the data up
     359     * into lines by \r and/or \n then if needed we will break
     360     * each of those into smaller lines to fit within the limit.
     361     * in addition we will be looking for lines that start with
     362     * a period '.' and append and additional period '.' to that
     363     * line. NOTE: this does not count towards limit.
     364     */
     365
     366    // normalize the line breaks so we know the explode works
    323367    $msg_data = str_replace("\r\n","\n",$msg_data);
    324368    $msg_data = str_replace("\r","\n",$msg_data);
    325369    $lines = explode("\n",$msg_data);
    326370
    327     # we need to find a good way to determine is headers are
    328     # in the msg_data or if it is a straight msg body
    329     # currently I am assuming rfc 822 definitions of msg headers
    330     # and if the first field of the first line (':' sperated)
    331     # does not contain a space then it _should_ be a header
    332     # and we can process all lines before a blank "" line as
    333     # headers.
     371    /* we need to find a good way to determine is headers are
     372     * in the msg_data or if it is a straight msg body
     373     * currently I am assuming rfc 822 definitions of msg headers
     374     * and if the first field of the first line (':' sperated)
     375     * does not contain a space then it _should_ be a header
     376     * and we can process all lines before a blank "" line as
     377     * headers.
     378     */
     379
    334380    $field = substr($lines[0],0,strpos($lines[0],":"));
    335381    $in_headers = false;
     
    338384    }
    339385
    340     $max_line_length = 998; # used below; set here for ease in change
     386    $max_line_length = 998; // used below; set here for ease in change
    341387
    342388    while(list(,$line) = @each($lines)) {
     
    345391        $in_headers = false;
    346392      }
    347       # ok we need to break this line up into several
    348       # smaller lines
     393      // ok we need to break this line up into several smaller lines
    349394      while(strlen($line) > $max_line_length) {
    350395        $pos = strrpos(substr($line,0,$max_line_length)," ");
    351396
    352         # Patch to fix DOS attack
     397        // Patch to fix DOS attack
    353398        if(!$pos) {
    354399          $pos = $max_line_length - 1;
     400          $lines_out[] = substr($line,0,$pos);
     401          $line = substr($line,$pos);
     402        } else {
     403          $lines_out[] = substr($line,0,$pos);
     404          $line = substr($line,$pos + 1);
    355405        }
    356406
    357         $lines_out[] = substr($line,0,$pos);
    358         $line = substr($line,$pos + 1);
    359         # if we are processing headers we need to
    360         # add a LWSP-char to the front of the new line
    361         # rfc 822 on long msg headers
     407        /* if processing headers add a LWSP-char to the front of new line
     408         * rfc 822 on long msg headers
     409         */
    362410        if($in_headers) {
    363411          $line = "\t" . $line;
     
    366414      $lines_out[] = $line;
    367415
    368       # now send the lines to the server
     416      // send the lines to the server
    369417      while(list(,$line_out) = @each($lines_out)) {
    370418        if(strlen($line_out) > 0)
     
    378426    }
    379427
    380     # ok all the message data has been sent so lets get this
    381     # over with aleady
     428    // message data has been sent
    382429    fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
    383430
     
    386433
    387434    if($this->do_debug >= 2) {
    388       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     435      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    389436    }
    390437
     
    395442              "smtp_msg" => substr($rply,4));
    396443      if($this->do_debug >= 1) {
    397         echo "SMTP -> ERROR: " . $this->error["error"] .
    398                  ": " . $rply . $this->CRLF;
    399       }
    400       return false;
    401     }
    402     return true;
    403   }
    404 
    405   /**
    406    * Expand takes the name and asks the server to list all the
    407    * people who are members of the _list_. Expand will return
    408    * back and array of the result or false if an error occurs.
    409    * Each value in the array returned has the format of:
    410    *     [ <full-name> <sp> ] <path>
    411    * The definition of <path> is defined in rfc 821
    412    *
    413    * Implements rfc 821: EXPN <SP> <string> <CRLF>
    414    *
    415    * SMTP CODE SUCCESS: 250
    416    * SMTP CODE FAILURE: 550
    417    * SMTP CODE ERROR  : 500,501,502,504,421
    418    * @access public
    419    * @return string array
    420    */
    421   function Expand($name) {
    422     $this->error = null; # so no confusion is caused
    423 
    424     if(!$this->connected()) {
    425       $this->error = array(
    426             "error" => "Called Expand() without being connected");
    427       return false;
    428     }
    429 
    430     fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
    431 
    432     $rply = $this->get_lines();
    433     $code = substr($rply,0,3);
    434 
    435     if($this->do_debug >= 2) {
    436       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    437     }
    438 
    439     if($code != 250) {
    440       $this->error =
    441         array("error" => "EXPN not accepted from server",
    442               "smtp_code" => $code,
    443               "smtp_msg" => substr($rply,4));
    444       if($this->do_debug >= 1) {
    445         echo "SMTP -> ERROR: " . $this->error["error"] .
    446                  ": " . $rply . $this->CRLF;
    447       }
    448       return false;
    449     }
    450 
    451     # parse the reply and place in our array to return to user
    452     $entries = explode($this->CRLF,$rply);
    453     while(list(,$l) = @each($entries)) {
    454       $list[] = substr($l,4);
    455     }
    456 
    457     return $list;
     444        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
     445      }
     446      return false;
     447    }
     448    return true;
    458449  }
    459450
     
    470461   * @return bool
    471462   */
    472   function Hello($host="") {
    473     $this->error = null; # so no confusion is caused
     463  public function Hello($host = '') {
     464    $this->error = null; // so no confusion is caused
    474465
    475466    if(!$this->connected()) {
     
    479470    }
    480471
    481     # if a hostname for the HELO was not specified determine
    482     # a suitable one to send
     472    // if hostname for HELO was not specified send default
    483473    if(empty($host)) {
    484       # we need to determine some sort of appopiate default
    485       # to send to the server
     474      // determine appropriate default to send to server
    486475      $host = "localhost";
    487476    }
    488477
    489478    // Send extended hello first (RFC 2821)
    490     if(!$this->SendHello("EHLO", $host))
    491     {
    492       if(!$this->SendHello("HELO", $host))
    493           return false;
     479    if(!$this->SendHello("EHLO", $host)) {
     480      if(!$this->SendHello("HELO", $host)) {
     481        return false;
     482      }
    494483    }
    495484
     
    502491   * @return bool
    503492   */
    504   function SendHello($hello, $host) {
     493  private function SendHello($hello, $host) {
    505494    fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
    506495
     
    509498
    510499    if($this->do_debug >= 2) {
    511       echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
     500      echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
    512501    }
    513502
     
    518507              "smtp_msg" => substr($rply,4));
    519508      if($this->do_debug >= 1) {
    520         echo "SMTP -> ERROR: " . $this->error["error"] .
    521                  ": " . $rply . $this->CRLF;
     509        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    522510      }
    523511      return false;
     
    527515
    528516    return true;
    529   }
    530 
    531   /**
    532    * Gets help information on the keyword specified. If the keyword
    533    * is not specified then returns generic help, ussually contianing
    534    * A list of keywords that help is available on. This function
    535    * returns the results back to the user. It is up to the user to
    536    * handle the returned data. If an error occurs then false is
    537    * returned with $this->error set appropiately.
    538    *
    539    * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
    540    *
    541    * SMTP CODE SUCCESS: 211,214
    542    * SMTP CODE ERROR  : 500,501,502,504,421
    543    * @access public
    544    * @return string
    545    */
    546   function Help($keyword="") {
    547     $this->error = null; # to avoid confusion
    548 
    549     if(!$this->connected()) {
    550       $this->error = array(
    551               "error" => "Called Help() without being connected");
    552       return false;
    553     }
    554 
    555     $extra = "";
    556     if(!empty($keyword)) {
    557       $extra = " " . $keyword;
    558     }
    559 
    560     fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
    561 
    562     $rply = $this->get_lines();
    563     $code = substr($rply,0,3);
    564 
    565     if($this->do_debug >= 2) {
    566       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    567     }
    568 
    569     if($code != 211 && $code != 214) {
    570       $this->error =
    571         array("error" => "HELP not accepted from server",
    572               "smtp_code" => $code,
    573               "smtp_msg" => substr($rply,4));
    574       if($this->do_debug >= 1) {
    575         echo "SMTP -> ERROR: " . $this->error["error"] .
    576                  ": " . $rply . $this->CRLF;
    577       }
    578       return false;
    579     }
    580 
    581     return $rply;
    582517  }
    583518
     
    596531   * @return bool
    597532   */
    598   function Mail($from) {
    599     $this->error = null; # so no confusion is caused
     533  public function Mail($from) {
     534    $this->error = null; // so no confusion is caused
    600535
    601536    if(!$this->connected()) {
     
    612547
    613548    if($this->do_debug >= 2) {
    614       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     549      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    615550    }
    616551
     
    621556              "smtp_msg" => substr($rply,4));
    622557      if($this->do_debug >= 1) {
    623         echo "SMTP -> ERROR: " . $this->error["error"] .
    624                  ": " . $rply . $this->CRLF;
    625       }
    626       return false;
    627     }
    628     return true;
    629   }
    630 
    631   /**
    632    * Sends the command NOOP to the SMTP server.
    633    *
    634    * Implements from rfc 821: NOOP <CRLF>
    635    *
    636    * SMTP CODE SUCCESS: 250
    637    * SMTP CODE ERROR  : 500, 421
    638    * @access public
    639    * @return bool
    640    */
    641   function Noop() {
    642     $this->error = null; # so no confusion is caused
    643 
    644     if(!$this->connected()) {
    645       $this->error = array(
    646               "error" => "Called Noop() without being connected");
    647       return false;
    648     }
    649 
    650     fputs($this->smtp_conn,"NOOP" . $this->CRLF);
    651 
    652     $rply = $this->get_lines();
    653     $code = substr($rply,0,3);
    654 
    655     if($this->do_debug >= 2) {
    656       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    657     }
    658 
    659     if($code != 250) {
    660       $this->error =
    661         array("error" => "NOOP not accepted from server",
    662               "smtp_code" => $code,
    663               "smtp_msg" => substr($rply,4));
    664       if($this->do_debug >= 1) {
    665         echo "SMTP -> ERROR: " . $this->error["error"] .
    666                  ": " . $rply . $this->CRLF;
     558        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    667559      }
    668560      return false;
     
    682574   * @return bool
    683575   */
    684   function Quit($close_on_error=true) {
    685     $this->error = null; # so there is no confusion
     576  public function Quit($close_on_error = true) {
     577    $this->error = null; // so there is no confusion
    686578
    687579    if(!$this->connected()) {
     
    691583    }
    692584
    693     # send the quit command to the server
     585    // send the quit command to the server
    694586    fputs($this->smtp_conn,"quit" . $this->CRLF);
    695587
    696     # get any good-bye messages
     588    // get any good-bye messages
    697589    $byemsg = $this->get_lines();
    698590
    699591    if($this->do_debug >= 2) {
    700       echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
     592      echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
    701593    }
    702594
     
    706598    $code = substr($byemsg,0,3);
    707599    if($code != 221) {
    708       # use e as a tmp var cause Close will overwrite $this->error
     600      // use e as a tmp var cause Close will overwrite $this->error
    709601      $e = array("error" => "SMTP server rejected quit command",
    710602                 "smtp_code" => $code,
     
    712604      $rval = false;
    713605      if($this->do_debug >= 1) {
    714         echo "SMTP -> ERROR: " . $e["error"] . ": " .
    715                  $byemsg . $this->CRLF;
     606        echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
    716607      }
    717608    }
     
    736627   * @return bool
    737628   */
    738   function Recipient($to) {
    739     $this->error = null; # so no confusion is caused
     629  public function Recipient($to) {
     630    $this->error = null; // so no confusion is caused
    740631
    741632    if(!$this->connected()) {
     
    751642
    752643    if($this->do_debug >= 2) {
    753       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     644      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    754645    }
    755646
     
    760651              "smtp_msg" => substr($rply,4));
    761652      if($this->do_debug >= 1) {
    762         echo "SMTP -> ERROR: " . $this->error["error"] .
    763                  ": " . $rply . $this->CRLF;
     653        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    764654      }
    765655      return false;
     
    780670   * @return bool
    781671   */
    782   function Reset() {
    783     $this->error = null; # so no confusion is caused
     672  public function Reset() {
     673    $this->error = null; // so no confusion is caused
    784674
    785675    if(!$this->connected()) {
     
    795685
    796686    if($this->do_debug >= 2) {
    797       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     687      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    798688    }
    799689
     
    804694              "smtp_msg" => substr($rply,4));
    805695      if($this->do_debug >= 1) {
    806         echo "SMTP -> ERROR: " . $this->error["error"] .
    807                  ": " . $rply . $this->CRLF;
    808       }
    809       return false;
    810     }
    811 
    812     return true;
    813   }
    814 
    815   /**
    816    * Starts a mail transaction from the email address specified in
    817    * $from. Returns true if successful or false otherwise. If True
    818    * the mail transaction is started and then one or more Recipient
    819    * commands may be called followed by a Data command. This command
    820    * will send the message to the users terminal if they are logged
    821    * in.
    822    *
    823    * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
    824    *
    825    * SMTP CODE SUCCESS: 250
    826    * SMTP CODE SUCCESS: 552,451,452
    827    * SMTP CODE SUCCESS: 500,501,502,421
    828    * @access public
    829    * @return bool
    830    */
    831   function Send($from) {
    832     $this->error = null; # so no confusion is caused
    833 
    834     if(!$this->connected()) {
    835       $this->error = array(
    836               "error" => "Called Send() without being connected");
    837       return false;
    838     }
    839 
    840     fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
    841 
    842     $rply = $this->get_lines();
    843     $code = substr($rply,0,3);
    844 
    845     if($this->do_debug >= 2) {
    846       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    847     }
    848 
    849     if($code != 250) {
    850       $this->error =
    851         array("error" => "SEND not accepted from server",
    852               "smtp_code" => $code,
    853               "smtp_msg" => substr($rply,4));
    854       if($this->do_debug >= 1) {
    855         echo "SMTP -> ERROR: " . $this->error["error"] .
    856                  ": " . $rply . $this->CRLF;
    857       }
    858       return false;
    859     }
     696        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
     697      }
     698      return false;
     699    }
     700
    860701    return true;
    861702  }
     
    877718   * @return bool
    878719   */
    879   function SendAndMail($from) {
    880     $this->error = null; # so no confusion is caused
     720  public function SendAndMail($from) {
     721    $this->error = null; // so no confusion is caused
    881722
    882723    if(!$this->connected()) {
     
    892733
    893734    if($this->do_debug >= 2) {
    894       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
     735      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    895736    }
    896737
     
    901742              "smtp_msg" => substr($rply,4));
    902743      if($this->do_debug >= 1) {
    903         echo "SMTP -> ERROR: " . $this->error["error"] .
    904                  ": " . $rply . $this->CRLF;
    905       }
    906       return false;
    907     }
    908     return true;
    909   }
    910 
    911   /**
    912    * Starts a mail transaction from the email address specified in
    913    * $from. Returns true if successful or false otherwise. If True
    914    * the mail transaction is started and then one or more Recipient
    915    * commands may be called followed by a Data command. This command
    916    * will send the message to the users terminal if they are logged
    917    * in or mail it to them if they are not.
    918    *
    919    * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
    920    *
    921    * SMTP CODE SUCCESS: 250
    922    * SMTP CODE SUCCESS: 552,451,452
    923    * SMTP CODE SUCCESS: 500,501,502,421
    924    * @access public
    925    * @return bool
    926    */
    927   function SendOrMail($from) {
    928     $this->error = null; # so no confusion is caused
    929 
    930     if(!$this->connected()) {
    931       $this->error = array(
    932           "error" => "Called SendOrMail() without being connected");
    933       return false;
    934     }
    935 
    936     fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
    937 
    938     $rply = $this->get_lines();
    939     $code = substr($rply,0,3);
    940 
    941     if($this->do_debug >= 2) {
    942       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    943     }
    944 
    945     if($code != 250) {
    946       $this->error =
    947         array("error" => "SOML not accepted from server",
    948               "smtp_code" => $code,
    949               "smtp_msg" => substr($rply,4));
    950       if($this->do_debug >= 1) {
    951         echo "SMTP -> ERROR: " . $this->error["error"] .
    952                  ": " . $rply . $this->CRLF;
     744        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    953745      }
    954746      return false;
     
    970762   * @return bool
    971763   */
    972   function Turn() {
     764  public function Turn() {
    973765    $this->error = array("error" => "This method, TURN, of the SMTP ".
    974766                                    "is not implemented");
    975767    if($this->do_debug >= 1) {
    976       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
     768      echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
    977769    }
    978770    return false;
     
    980772
    981773  /**
    982    * Verifies that the name is recognized by the server.
    983    * Returns false if the name could not be verified otherwise
    984    * the response from the server is returned.
    985    *
    986    * Implements rfc 821: VRFY <SP> <string> <CRLF>
    987    *
    988    * SMTP CODE SUCCESS: 250,251
    989    * SMTP CODE FAILURE: 550,551,553
    990    * SMTP CODE ERROR  : 500,501,502,421
    991    * @access public
    992    * @return int
    993    */
    994   function Verify($name) {
    995     $this->error = null; # so no confusion is caused
    996 
    997     if(!$this->connected()) {
    998       $this->error = array(
    999               "error" => "Called Verify() without being connected");
    1000       return false;
    1001     }
    1002 
    1003     fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
    1004 
    1005     $rply = $this->get_lines();
    1006     $code = substr($rply,0,3);
    1007 
    1008     if($this->do_debug >= 2) {
    1009       echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
    1010     }
    1011 
    1012     if($code != 250 && $code != 251) {
    1013       $this->error =
    1014         array("error" => "VRFY failed on name '$name'",
    1015               "smtp_code" => $code,
    1016               "smtp_msg" => substr($rply,4));
    1017       if($this->do_debug >= 1) {
    1018         echo "SMTP -> ERROR: " . $this->error["error"] .
    1019                  ": " . $rply . $this->CRLF;
    1020       }
    1021       return false;
    1022     }
    1023     return $rply;
    1024   }
    1025 
    1026   /*******************************************************************
    1027    *                       INTERNAL FUNCTIONS                       *
    1028    ******************************************************************/
     774  * Get the current error
     775  * @access public
     776  * @return array
     777  */
     778  public function getError() {
     779    return $this->error;
     780  }
     781
     782  /////////////////////////////////////////////////
     783  // INTERNAL FUNCTIONS
     784  /////////////////////////////////////////////////
    1029785
    1030786  /**
     
    1037793   * @return string
    1038794   */
    1039   function get_lines() {
     795  private function get_lines() {
    1040796    $data = "";
    1041797    while($str = @fgets($this->smtp_conn,515)) {
    1042798      if($this->do_debug >= 4) {
    1043         echo "SMTP -> get_lines(): \$data was \"$data\"" .
    1044                  $this->CRLF;
    1045         echo "SMTP -> get_lines(): \$str is \"$str\"" .
    1046                  $this->CRLF;
     799        echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
     800        echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
    1047801      }
    1048802      $data .= $str;
    1049803      if($this->do_debug >= 4) {
    1050         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
    1051       }
    1052       # if the 4th character is a space then we are done reading
    1053       # so just break the loop
     804        echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
     805      }
     806      // if 4th character is a space, we are done reading, break the loop
    1054807      if(substr($str,3,1) == " ") { break; }
    1055808    }
     
    1059812}
    1060813
    1061 
    1062  ?>
     814?>
Note: See TracChangeset for help on using the changeset viewer.