WordPress.org

Make WordPress Core

Ticket #15912: 15912.001.diff

File 15912.001.diff, 156.4 KB (added by cnorris23, 7 years ago)
  • wp-includes/class-phpmailer.php

     
    22/*~ class.phpmailer.php
    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| ------------------------------------------------------------------------- |
    1517|   License: Distributed under the Lesser General Public License (LGPL)     |
     
    1820| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
    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 */
    3340
     41if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
     42
    3443class PHPMailer {
    3544
    3645  /////////////////////////////////////////////////
     
    4150   * Email priority (1 = High, 3 = Normal, 5 = low).
    4251   * @var int
    4352   */
    44   var $Priority          = 3;
     53  public $Priority          = 3;
    4554
    4655  /**
    4756   * Sets the CharSet of the message.
    4857   * @var string
    4958   */
    50   var $CharSet           = 'iso-8859-1';
     59  public $CharSet           = 'iso-8859-1';
    5160
    5261  /**
    5362   * Sets the Content-type of the message.
    5463   * @var string
    5564   */
    56   var $ContentType        = 'text/plain';
     65  public $ContentType       = 'text/plain';
    5766
    5867  /**
    59    * Sets the Encoding of the message. Options for this are "8bit",
    60    * "7bit", "binary", "base64", and "quoted-printable".
     68   * Sets the Encoding of the message. Options for this are
     69   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
    6170   * @var string
    6271   */
    63   var $Encoding          = '8bit';
     72  public $Encoding          = '8bit';
    6473
    6574  /**
    6675   * Holds the most recent mailer error message.
    6776   * @var string
    6877   */
    69   var $ErrorInfo         = '';
     78  public $ErrorInfo         = '';
    7079
    7180  /**
    7281   * Sets the From email address for the message.
    7382   * @var string
    7483   */
    75   var $From              = 'root@localhost';
     84  public $From              = 'root@localhost';
    7685
    7786  /**
    7887   * Sets the From name of the message.
    7988   * @var string
    8089   */
    81   var $FromName          = 'Root User';
     90  public $FromName          = 'Root User';
    8291
    8392  /**
    8493   * Sets the Sender email (Return-Path) of the message.  If not empty,
    8594   * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
    8695   * @var string
    8796   */
    88   var $Sender            = '';
     97  public $Sender            = '';
    8998
    9099  /**
    91100   * Sets the Subject of the message.
    92101   * @var string
    93102   */
    94   var $Subject           = '';
     103  public $Subject           = '';
    95104
    96105  /**
    97106   * Sets the Body of the message.  This can be either an HTML or text body.
    98107   * If HTML then run IsHTML(true).
    99108   * @var string
    100109   */
    101   var $Body              = '';
     110  public $Body              = '';
    102111
    103112  /**
    104113   * Sets the text-only body of the message.  This automatically sets the
     
    107116   * that can read HTML will view the normal Body.
    108117   * @var string
    109118   */
    110   var $AltBody           = '';
     119  public $AltBody           = '';
    111120
    112121  /**
    113122   * Sets word wrapping on the body of the message to a given number of
    114123   * characters.
    115124   * @var int
    116125   */
    117   var $WordWrap          = 0;
     126  public $WordWrap          = 0;
    118127
    119128  /**
    120129   * Method to send mail: ("mail", "sendmail", or "smtp").
    121130   * @var string
    122131   */
    123   var $Mailer            = 'mail';
     132  public $Mailer            = 'mail';
    124133
    125134  /**
    126135   * Sets the path of the sendmail program.
    127136   * @var string
    128137   */
    129   var $Sendmail          = '/usr/sbin/sendmail';
     138  public $Sendmail          = '/usr/sbin/sendmail';
    130139
    131140  /**
    132    * Path to PHPMailer plugins.  This is now only useful if the SMTP class
     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         = '';
     145  public $PluginDir         = '';
    137146
    138147  /**
    139    * Holds PHPMailer version.
    140    * @var string
    141    */
    142   var $Version           = "2.0.4";
    143 
    144   /**
    145148   * Sets the email address that a reading confirmation will be sent.
    146149   * @var string
    147150   */
    148   var $ConfirmReadingTo  = '';
     151  public $ConfirmReadingTo  = '';
    149152
    150153  /**
    151154   * Sets the hostname to use in Message-Id and Received headers
     
    153156   * by SERVER_NAME is used or 'localhost.localdomain'.
    154157   * @var string
    155158   */
    156   var $Hostname          = '';
     159  public $Hostname          = '';
    157160
    158161  /**
    159162   * Sets the message ID to be used in the Message-Id header.
    160163   * If empty, a unique id will be generated.
    161164   * @var string
    162165   */
    163   var $MessageID         = '';
     166  public $MessageID         = '';
    164167
    165168  /////////////////////////////////////////////////
    166169  // PROPERTIES FOR SMTP
     
    174177   * Hosts will be tried in order.
    175178   * @var string
    176179   */
    177   var $Host        = 'localhost';
     180  public $Host          = 'localhost';
    178181
    179182  /**
    180183   * Sets the default SMTP server port.
    181184   * @var int
    182185   */
    183   var $Port        = 25;
     186  public $Port          = 25;
    184187
    185188  /**
    186189   * Sets the SMTP HELO of the message (Default is $Hostname).
    187190   * @var string
    188191   */
    189   var $Helo        = '';
     192  public $Helo          = '';
    190193
    191194  /**
    192195   * Sets connection prefix.
    193196   * Options are "", "ssl" or "tls"
    194197   * @var string
    195198   */
    196   var $SMTPSecure = "";
     199  public $SMTPSecure    = '';
    197200
    198201  /**
    199202   * Sets SMTP authentication. Utilizes the Username and Password variables.
    200203   * @var bool
    201204   */
    202   var $SMTPAuth     = false;
     205  public $SMTPAuth      = false;
    203206
    204207  /**
    205208   * Sets SMTP username.
    206209   * @var string
    207210   */
    208   var $Username     = '';
     211  public $Username      = '';
    209212
    210213  /**
    211214   * Sets SMTP password.
    212215   * @var string
    213216   */
    214   var $Password     = '';
     217  public $Password      = '';
    215218
    216219  /**
    217    * Sets the SMTP server timeout in seconds. This function will not
    218    * work with the win32 version.
     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  /**
    224227   * Sets SMTP class debugging on or off.
    225228   * @var bool
    226229   */
    227   var $SMTPDebug    = false;
     230  public $SMTPDebug     = false;
    228231
    229232  /**
    230233   * Prevents the SMTP connection from being closed after each mail
     
    232235   * requires an explicit call to SmtpClose().
    233236   * @var bool
    234237   */
    235   var $SMTPKeepAlive = false;
     238  public $SMTPKeepAlive = false;
    236239
    237240  /**
    238241   * Provides the ability to have the TO field process individual
    239242   * emails, instead of sending to entire TO addresses
    240243   * @var bool
    241244   */
    242   var $SingleTo = false;
     245  public $SingleTo      = false;
    243246
     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';
     304
    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;
    263325
    264326  /////////////////////////////////////////////////
     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
     333
     334  /////////////////////////////////////////////////
    265335  // METHODS, VARIABLES
    266336  /////////////////////////////////////////////////
    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 {
    277355      $this->ContentType = 'text/plain';
     
    282360   * Sets Mailer to send message using SMTP.
    283361   * @return void
    284362   */
    285   function IsSMTP() {
     363  public function IsSMTP() {
    286364    $this->Mailer = 'smtp';
    287365  }
    288366
     
    290368   * Sets Mailer to send message using PHP mail() function.
    291369   * @return void
    292370   */
    293   function IsMail() {
     371  public function IsMail() {
    294372    $this->Mailer = 'mail';
    295373  }
    296374
     
    298376   * Sets Mailer to send message using the $Sendmail program.
    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  }
    304385
     
    306387   * Sets Mailer to send message using the qmail MTA.
    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  }
    313396
     
    319402   * Adds a "To" address.
    320403   * @param string $address
    321404   * @param string $name
    322    * @return void
     405   * @return boolean true on success, false if address already used
    323406   */
    324   function AddAddress($address, $name = '') {
    325     $cur = count($this->to);
    326     $this->to[$cur][0] = trim($address);
    327     $this->to[$cur][1] = $name;
     407  public function AddAddress($address, $name = '') {
     408    return $this->AddAnAddress('to', $address, $name);
    328409  }
    329410
    330411  /**
    331    * Adds a "Cc" address. Note: this function works
    332    * with the SMTP mailer on win32, not with the "mail"
    333    * mailer.
     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
     416   * @return boolean true on success, false if address already used
    337417   */
    338   function AddCC($address, $name = '') {
    339     $cur = count($this->cc);
    340     $this->cc[$cur][0] = trim($address);
    341     $this->cc[$cur][1] = $name;
     418  public function AddCC($address, $name = '') {
     419    return $this->AddAnAddress('cc', $address, $name);
    342420  }
    343421
    344422  /**
    345    * Adds a "Bcc" address. Note: this function works
    346    * with the SMTP mailer on win32, not with the "mail"
    347    * mailer.
     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
     427   * @return boolean true on success, false if address already used
    351428   */
    352   function AddBCC($address, $name = '') {
    353     $cur = count($this->bcc);
    354     $this->bcc[$cur][0] = trim($address);
    355     $this->bcc[$cur][1] = $name;
     429  public function AddBCC($address, $name = '') {
     430    return $this->AddAnAddress('bcc', $address, $name);
    356431  }
    357432
    358433  /**
    359    * Adds a "Reply-To" address.
     434   * Adds a "Reply-to" address.
    360435   * @param string $address
    361436   * @param string $name
    362    * @return void
     437   * @return boolean
    363438   */
    364   function AddReplyTo($address, $name = '') {
    365     $cur = count($this->ReplyTo);
    366     $this->ReplyTo[$cur][0] = trim($address);
    367     $this->ReplyTo[$cur][1] = $name;
     439  public function AddReplyTo($address, $name = '') {
     440    return $this->AddAnAddress('ReplyTo', $address, $name);
    368441  }
    369442
     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    }
     533  }
     534
    370535  /////////////////////////////////////////////////
    371536  // METHODS, MAIL SENDING
    372537  /////////////////////////////////////////////////
     
    377542   * variable to view description of the error.
    378543   * @return bool
    379544   */
    380   function Send() {
    381     $header = '';
    382     $body = '';
    383     $result = true;
     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      }
    384550
    385     if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
    386       $this->SetError($this->Lang('provide_address'));
    387       return false;
    388     }
     551      // Set whether the message is multipart/alternative
     552      if(!empty($this->AltBody)) {
     553        $this->ContentType = 'multipart/alternative';
     554      }
    389555
    390     /* Set whether the message is multipart/alternative */
    391     if(!empty($this->AltBody)) {
    392       $this->ContentType = 'multipart/alternative';
    393     }
     556      $this->error_count = 0; // reset errors
     557      $this->SetMessageType();
     558      $header = $this->CreateHeader();
     559      $body = $this->CreateBody();
    394560
    395     $this->error_count = 0; // reset errors
    396     $this->SetMessageType();
    397     $header .= $this->CreateHeader();
    398     $body = $this->CreateBody();
     561      if (empty($this->Body)) {
     562        throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
     563      }
    399564
    400     if($body == '') {
     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";
    401587      return false;
    402588    }
    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));
    434601    } else {
    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;
     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      }
    441633    }
    442 
    443     fputs($mail, $header);
    444     fputs($mail, $body);
    445 
    446     $result = pclose($mail);
    447     if (version_compare(phpversion(), '4.2.3') == -1) {
    448       $result = $result >> 8 & 0xFF;
    449     }
    450     if($result != 0) {
    451       $this->SetError($this->Lang('execute') . $this->Sendmail);
    452       return false;
    453     }
    454634    return true;
    455635  }
    456636
    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]);
     644  protected function MailSend($header, $body) {
     645    $toArr = array();
     646    foreach($this->to as $t) {
     647      $toArr[] = $this->AddrFormat($t);
    468648    }
     649    $to = implode(', ', $toArr);
    469650
    470     $toArr = split(',', $to);
    471 
    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);
    476655      if ($this->SingleTo === true && count($toArr) > 1) {
    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 {
    484669      if ($this->SingleTo === true && count($toArr) > 1) {
    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);
     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);
    490681      }
    491682    }
    492 
    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;
     687      throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
    500688    }
    501 
    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;
     706      throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
    519707    }
    520 
    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;
     710      throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
    527711    }
    528712
    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];
     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);
    533724      }
    534725    }
    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];
     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);
    538736      }
    539737    }
    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];
     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);
    543748      }
    544749    }
    545750
    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;
     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);
    557755    }
    558 
    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();
    568761    }
    569 
    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    }
    583776
    584777    $this->smtp->do_debug = $this->SMTPDebug;
    585778    $hosts = explode(';', $this->Host);
    586779    $index = 0;
    587     $connection = ($this->smtp->Connected());
     780    $connection = $this->smtp->Connected();
    588781
    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);
     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);
    613809          }
     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            }
     816          }
    614817        }
     818        $index++;
     819        if (!$connection) {
     820          throw new phpmailerException($this->Lang('connect_host'));
     821        }
    615822      }
    616       $index++;
     823    } catch (phpmailerException $e) {
     824      $this->smtp->Reset();
     825      throw $e;
    617826    }
    618     if(!$connection) {
    619       $this->SetError($this->Lang('connect_host'));
    620     }
    621 
    622     return $connection;
     827    return true;
    623828  }
    624829
    625830  /**
    626831   * Closes the active SMTP session if one exists.
    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();
    633838        $this->smtp->Close();
     
    636841  }
    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;
     877    return ($l == true); //Returns false if language not found
     878  }
    669879
    670     return true;
     880  /**
     881  * Return the current array of language strings
     882  * @return array
     883  */
     884  public function GetTranslations() {
     885    return $this->language;
    671886  }
    672887
    673888  /////////////////////////////////////////////////
     
    676891
    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       }
     899    $addresses = array();
     900    foreach ($addr as $a) {
     901      $addresses[] = $this->AddrFormat($a);
    689902    }
     903    $addr_str .= implode(', ', $addresses);
    690904    $addr_str .= $this->LE;
    691905
    692906    return $addr_str;
     
    694908
    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]) . ">";
     918      return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
    705919    }
    706 
    707     return $formatted;
    708920  }
    709921
    710922  /**
    711923   * Wraps message for use with mailers that do not
    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
    720935    // split multibyte characters when we wrap
     
    7911006   * Finds last character boundary prior to maxLength in a utf-8
    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;
    8021017    while (!$foundSplitPos) {
     
    8281043    return $maxLength;
    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;
    8391055    }
    8401056
    8411057    switch($this->message_type) {
    8421058      case 'alt':
    843         /* fall through */
    8441059      case 'alt_attachments':
    8451060        $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
    8461061        break;
     
    8521067
    8531068  /**
    8541069   * Assembles message header.
    855    * @access private
    856    * @return string
     1070   * @access public
     1071   * @return string The assembled header
    8571072   */
    858   function CreateHeader() {
     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));
    8691084    } else {
    8701085      $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
    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    }
    8811102
     
    8841105    $from[0][1] = $this->FromName;
    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);
    8951116    }
    8961117
    8971118    if(count($this->ReplyTo) > 0) {
    898       $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
     1119      $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
    8991120    }
    9001121
    901     /* mail() sets the subject itself */
     1122    // mail() sets the subject itself
    9021123    if($this->Mailer != 'mail') {
    9031124      $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
    9041125    }
     
    9091130      $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
    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 != '') {
    9151136      $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
     
    9291150
    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) {
    9381159      case 'plain':
     
    9401161        $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
    9411162        break;
    9421163      case 'attachments':
    943         /* fall through */
    9441164      case 'alt_attachments':
    9451165        if($this->InlineImageExists()){
    9461166          $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
     
    9641184
    9651185  /**
    9661186   * Assembles the message body.  Returns an empty string on failure.
    967    * @access private
    968    * @return string
     1187   * @access public
     1188   * @return string The assembled message body
    9691189   */
    970   function CreateBody() {
    971     $result = '';
     1190  public function CreateBody() {
     1191    $body = '';
     1192
    9721193    if ($this->sign_key_file) {
    973       $result .= $this->GetMailMIME();
     1194      $body .= $this->GetMailMIME();
    9741195    }
    9751196
    9761197    $this->SetWordWrap();
    9771198
    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 = '';
     1248      } catch (phpmailerException $e) {
     1249        $body = '';
     1250        if ($this->exceptions) {
     1251          throw $e;
     1252        }
    10311253      }
    1032 
    1033       unlink($file);
    1034       unlink($signed);
    10351254    }
    10361255
    1037     return $result;
     1256    return $body;
    10381257  }
    10391258
    10401259  /**
    10411260   * Returns the start of a message boundary.
    10421261   * @access private
    10431262   */
    1044   function GetBoundary($boundary, $charSet, $contentType, $encoding) {
     1263  private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
    10451264    $result = '';
    10461265    if($charSet == '') {
    10471266      $charSet = $this->CharSet;
     
    10651284   * Returns the end of a message boundary.
    10661285   * @access private
    10671286   */
    1068   function EndBoundary($boundary) {
     1287  private function EndBoundary($boundary) {
    10691288    return $this->LE . '--' . $boundary . '--' . $this->LE;
    10701289  }
    10711290
     
    10741293   * @access private
    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';
    10801299    } else {
     
    10901309    }
    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  }
    11001320
    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  }
    11091329
     
    11211341   * @param string $type File extension (MIME) type.
    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     }
     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      }
    11291353
    1130     $filename = basename($path);
    1131     if($name == '') {
    1132       $name = $filename;
     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      }
    11331374    }
    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 
    11451375    return true;
    11461376  }
    11471377
    11481378  /**
     1379  * Return the current array of attachments
     1380  * @return array
     1381  */
     1382  public function GetAttachments() {
     1383    return $this->attachment;
     1384  }
     1385
     1386  /**
    11491387   * Attaches all fs, string, and binary attachments to the message.
    11501388   * Returns an empty string on failure.
    11511389   * @access private
    11521390   * @return string
    11531391   */
    1154   function AttachAll() {
    1155     /* Return text of body */
     1392  private function AttachAll() {
     1393    // Return text of body
    11561394    $mime = array();
     1395    $cidUniq = array();
     1396    $incl = array();
    11571397
    1158     /* Add all attachments */
    1159     for($i = 0; $i < count($this->attachment); $i++) {
    1160       /* Check for string attachment */
    1161       $bString = $this->attachment[$i][5];
     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];
     1405        $path = $attachment[0];
    11661406      }
    11671407
    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];
     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);
    11761420      $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
     
    11821426
    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);
    11881432        if($this->IsError()) {
     
    12041448  }
    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;
    12251481  }
    12261482
    12271483  /**
    1228    * Encodes string to requested format. Returns an
    1229    * empty string on failure.
    1230    * @access private
     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;
    12401497      case '7bit':
    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;
    12451503        break;
     
    12571515  }
    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
    12671525    switch (strtolower($position)) {
    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)) {
    12731531            return ($encoded);
     
    12791537        break;
    12801538      case 'comment':
    12811539        $x = preg_match_all('/[()"]/', $str, $matches);
    1282         /* Fall-through */
     1540        // Fall-through
    12831541      case 'text':
    12841542      default:
    12851543        $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
     
    12911549    }
    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 {
    13021560        $encoded = base64_encode($str);
     
    13181576
    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  }
    13321590
     
    13341592   * Correctly encodes and wraps long multibyte strings for mail headers
    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 = "?=";
    13441602    $encoded = "";
     
    13711629  }
    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);
    13811642    $eol = "\r\n";
     
    14171678  }
    14181679
    14191680  /**
    1420    * Callback for converting to "=XX".
    1421    * @access private
    1422    * @return string
    1423    */
    1424   function EncodeQ_callback ($matches) {
    1425     return sprintf('=%02X', ord($matches[1]));
     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;
    14261711  }
    14271712
    14281713  /**
    14291714   * Encode string to q encoding.
    1430    * @access private
     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
    14311719   * @return string
    14321720   */
    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
    14571743    return $encoded;
     
    14671753   * @param string $type File extension (MIME) type.
    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
    14831770  /**
     
    14931780   * @param string $type File extension (MIME) type.
    14941781   * @return bool
    14951782   */
    1496   function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
     1783  public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
    14971784
    1498     if(!@is_file($path)) {
     1785    if ( !@is_file($path) ) {
    14991786      $this->SetError($this->Lang('file_access') . $path);
    15001787      return false;
    15011788    }
    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;
    15201808  }
    15211809
    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;
     1815  public function InlineImageExists() {
     1816    foreach($this->attachment as $attachment) {
     1817      if ($attachment[6] == 'inline') {
     1818        return true;
    15331819      }
    15341820    }
    1535 
    1536     return $result;
     1821    return false;
    15371822  }
    15381823
    15391824  /////////////////////////////////////////////////
     
    15441829   * Clears all recipients assigned in the TO array.  Returns void.
    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  }
    15501838
     
    15521840   * Clears all recipients assigned in the CC array.  Returns void.
    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  }
    15581849
     
    15601851   * Clears all recipients assigned in the BCC array.  Returns void.
    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  }
    15661860
     
    15681862   * Clears all recipients assigned in the ReplyTo array.  Returns void.
    15691863   * @return void
    15701864   */
    1571   function ClearReplyTos() {
     1865  public function ClearReplyTos() {
    15721866    $this->ReplyTo = array();
    15731867  }
    15741868
     
    15771871   * array.  Returns void.
    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
    15861881  /**
     
    15881883   * attachments.  Returns void.
    15891884   * @return void
    15901885   */
    1591   function ClearAttachments() {
     1886  public function ClearAttachments() {
    15921887    $this->attachment = array();
    15931888  }
    15941889
     
    15961891   * Clears all custom headers.  Returns void.
    15971892   * @return void
    15981893   */
    1599   function ClearCustomHeaders() {
     1894  public function ClearCustomHeaders() {
    16001895    $this->CustomHeader = array();
    16011896  }
    16021897
     
    16061901
    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  }
    16171917
    16181918  /**
    16191919   * Returns the proper RFC 822 formatted date.
    1620    * @access private
     1920   * @access public
    16211921   * @return string
     1922   * @static
    16221923   */
    1623   function RFCDate() {
     1924  public static function RFCDate() {
    16241925    $tz = date('Z');
    16251926    $tzs = ($tz < 0) ? '-' : '+';
    16261927    $tz = abs($tz);
     
    16311932  }
    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';
    16701946    }
     
    16771953   * @access private
    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
    16831959    }
     
    16911967
    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  }
    16991976
     
    17021979   * @access private
    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);
    17081985    $str = str_replace("\n", $this->LE, $str);
     
    17111988
    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  }
    17191997
     
    17222000   * @access public
    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 .= '/'; }
    17402017          if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
     
    17462023    $this->IsHTML(true);
    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";
     2029    if (empty($this->AltBody)) {
     2030      $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
    17542031    }
    17552032  }
    17562033
    17572034  /**
    1758    * Gets the mime type of the embedded or inline image
    1759    * @access private
    1760    * @return mime type of ext
     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
    17612040   */
    1762   function _mime_types($ext = '') {
     2041  public static function _mime_types($ext = '') {
    17632042    $mimes = array(
    1764       'ai'    =>  'application/postscript',
    1765       'aif'   =>  'audio/x-aiff',
    1766       'aifc'  =>  'audio/x-aiff',
    1767       'aiff'  =>  'audio/x-aiff',
    1768       'avi'   =>  'video/x-msvideo',
     2043      'hqx'   =>  'application/mac-binhex40',
     2044      'cpt'   =>  'application/mac-compactpro',
     2045      'doc'   =>  'application/msword',
    17692046      'bin'   =>  'application/macbinary',
    1770       'bmp'   =>  'image/bmp',
     2047      'dms'   =>  'application/octet-stream',
     2048      'lha'   =>  'application/octet-stream',
     2049      'lzh'   =>  'application/octet-stream',
     2050      'exe'   =>  'application/octet-stream',
    17712051      'class' =>  'application/octet-stream',
    1772       'cpt'   =>  'application/mac-compactpro',
    1773       'css'   =>  'text/css',
     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',
     2058      'ai'    =>  'application/postscript',
     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',
    1823       'rtf'   =>  'text/rtf',
    1824       'rtx'   =>  'text/richtext',
     2097      'ra'    =>  'audio/x-realaudio',
    18252098      'rv'    =>  'video/vnd.rn-realvideo',
    1826       'sea'   =>  'application/octet-stream',
     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',
    18272111      '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',
     2112      'txt'   =>  'text/plain',
    18342113      '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',
     2114      'log'   =>  'text/plain',
     2115      'rtx'   =>  'text/richtext',
     2116      'rtf'   =>  'text/rtf',
     2117      'xml'   =>  'text/xml',
     2118      'xsl'   =>  'text/xml',
     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',
    18422127      'word'  =>  'application/msword',
    1843       'xht'   =>  'application/xhtml+xml',
    1844       'xhtml' =>  'application/xhtml+xml',
    18452128      'xl'    =>  'application/excel',
    1846       'xls'   =>  'application/vnd.ms-excel',
    1847       'xml'   =>  'text/xml',
    1848       'xsl'   =>  'text/xml',
    1849       'zip'   =>  'application/zip'
     2129      'eml'   =>  'message/rfc822'
    18502130    );
    1851     return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
     2131    return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
    18522132  }
    18532133
    18542134  /**
    1855    * Set (or reset) Class Objects (variables)
     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;
     2160  }
     2161
     2162  /**
     2163   * Strips newlines to prevent header injection.
     2164   * @access public
     2165   * @param string $str String
     2166   * @return string
     2167   */
     2168  public function SecureHeader($str) {
     2169    $str = str_replace("\r", '', $str);
     2170    $str = str_replace("\n", '', $str);
     2171    return trim($str);
     2172  }
     2173
     2174  /**
     2175   * Set the private key file and password to sign the message.
    18562176   *
    1857    * Usage Example:
    1858    * $page->set('X-Priority', '3');
     2177   * @access public
     2178   * @param string $key_filename Parameter File Name
     2179   * @param string $key_pass Password for private key
     2180   */
     2181  public function Sign($cert_filename, $key_filename, $key_pass) {
     2182    $this->sign_cert_file = $cert_filename;
     2183    $this->sign_key_file = $key_filename;
     2184    $this->sign_key_pass = $key_pass;
     2185  }
     2186
     2187  /**
     2188   * Set the private key file and password to sign the message.
    18592189   *
    18602190   * @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
     2191   * @param string $key_filename Parameter File Name
     2192   * @param string $key_pass Password for private key
    18642193   */
    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;
     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      }
    18712204    }
     2205    return $line;
    18722206  }
    18732207
    18742208  /**
    1875    * Read a file from a supplied filename and return it.
     2209   * Generate DKIM signature
    18762210   *
    18772211   * @access public
    1878    * @param string $filename Parameter File Name
     2212   * @param string $s Header
    18792213   */
    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;
     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);
    18882218    } else {
    1889       return false;
     2219      $privKey = $privKeyStr;
    18902220    }
     2221    if (openssl_sign($s, $signature, $privKey)) {
     2222      return base64_encode($signature);
     2223    }
    18912224  }
    18922225
    18932226  /**
    1894    * Strips newlines to prevent header injection.
    1895    * @access private
    1896    * @param string $str String
    1897    * @return string
     2227   * Generate DKIM Canonicalization Header
     2228   *
     2229   * @access public
     2230   * @param string $s Header
    18982231   */
    1899   function SecureHeader($str) {
    1900     $str = trim($str);
    1901     $str = str_replace("\r", "", $str);
    1902     $str = str_replace("\n", "", $str);
    1903     return $str;
     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;
    19042243  }
    19052244
    19062245  /**
    1907    * Set the private key file and password to sign the message.
     2246   * Generate DKIM Canonicalization Body
    19082247   *
    19092248   * @access public
    1910    * @param string $key_filename Parameter File Name
    1911    * @param string $key_pass Password for private key
     2249   * @param string $body Message Body
    19122250   */
    1913   function Sign($cert_filename, $key_filename, $key_pass) {
    1914     $this->sign_cert_file = $cert_filename;
    1915     $this->sign_key_file = $key_filename;
    1916     $this->sign_key_pass = $key_pass;
     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;
    19172261  }
    19182262
     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
    1921 ?>
     2314class phpmailerException extends Exception {
     2315  public function errorMessage() {
     2316    $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
     2317    return $errorMsg;
     2318  }
     2319}
     2320?>
     2321 No newline at end of file
  • wp-includes/class-pop3.php

     
    11<?php
     2/*~ class.pop3.php
     3.---------------------------------------------------------------------------.
     4|  Software: PHPMailer - PHP email class                                    |
     5|   Version: 5.1                                                            |
     6|   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
     7|      Info: http://phpmailer.sourceforge.net                               |
     8|   Support: http://sourceforge.net/projects/phpmailer/                     |
     9| ------------------------------------------------------------------------- |
     10|     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.               |
     15| Copyright (c) 2001-2003, Brent R. Matzelle                                |
     16| ------------------------------------------------------------------------- |
     17|   License: Distributed under the Lesser General Public License (LGPL)     |
     18|            http://www.gnu.org/copyleft/lesser.html                        |
     19| This program is distributed in the hope that it will be useful - WITHOUT  |
     20| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
     21| FITNESS FOR A PARTICULAR PURPOSE.                                         |
     22| ------------------------------------------------------------------------- |
     23| We offer a number of paid services (www.codeworxtech.com):                |
     24| - Web Hosting on highly optimized fast and secure servers                 |
     25| - Technology Consulting                                                   |
     26| - Oursourcing (highly qualified programmers and graphic designers)        |
     27'---------------------------------------------------------------------------'
     28*/
     29
    230/**
    3  * mail_fetch/setup.php
     31 * PHPMailer - PHP POP Before SMTP Authentication 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 - 2009 Andy Prevost
     37 * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
     38 * @version $Id$
     39 */
     40
     41/**
     42 * POP Before SMTP Authentication Class
     43 * Version 5.0.0
    444 *
    5  * @package SquirrelMail
     45 * Author: Richard Davey (rich@corephp.co.uk)
     46 * Modifications: Andy Prevost
     47 * License: LGPL, see PHPMailer License
    648 *
    7  * @copyright (c) 1999-2006 The SquirrelMail Project Team
     49 * Specifically for PHPMailer to allow POP before SMTP authentication.
     50 * Does not yet work with APOP - if you have an APOP account, contact Richard Davey
     51 * and we can test changes to this script.
    852 *
    9  * @copyright (c) 1999 CDI (cdi@thewebmasters.net) All Rights Reserved
    10  * Modified by Philippe Mingo 2001 mingo@rotedic.com
    11  * An RFC 1939 compliant wrapper class for the POP3 protocol.
     53 * This class is based on the structure of the SMTP class originally authored by Chris Ryan
    1254 *
    13  * Licensed under the GNU GPL. For full terms see the file COPYING.
    14  * @license http://opensource.org/licenses/gpl-license.php GNU General Public License
     55 * This class is rfc 1939 compliant and implements all the commands
     56 * required for POP3 connection, authentication and disconnection.
    1557 *
    16  * pop3 class
    17  *
    18  * $Id$
     58 * @package PHPMailer
     59 * @author Richard Davey
    1960 */
    2061
    2162class POP3 {
    22     var $ERROR      = '';       //  Error string.
     63  /**
     64   * Default POP3 port
     65   * @var int
     66   */
     67  public $POP3_PORT = 110;
    2368
    24     var $TIMEOUT    = 60;       //  Default timeout before giving up on a
    25                                 //  network operation.
     69  /**
     70   * Default Timeout
     71   * @var int
     72   */
     73  public $POP3_TIMEOUT = 30;
    2674
    27     var $COUNT      = -1;       //  Mailbox msg count
     75  /**
     76   * POP3 Carriage Return + Line Feed
     77   * @var string
     78   */
     79  public $CRLF = "\r\n";
    2880
    29     var $BUFFER     = 512;      //  Socket buffer for socket fgets() calls.
    30                                 //  Per RFC 1939 the returned line a POP3
    31                                 //  server can send is 512 bytes.
     81  /**
     82   * Displaying Debug warnings? (0 = now, 1+ = yes)
     83   * @var int
     84   */
     85  public $do_debug = 2;
    3286
    33     var $FP         = '';       //  The connection to the server's
    34                                 //  file descriptor
     87  /**
     88   * POP3 Mail Server
     89   * @var string
     90   */
     91  public $host;
    3592
    36     var $MAILSERVER = '';       // Set this to hard code the server name
     93  /**
     94   * POP3 Port
     95   * @var int
     96   */
     97  public $port;
    3798
    38     var $DEBUG      = FALSE;    // set to true to echo pop3
    39                                 // commands and responses to error_log
    40                                 // this WILL log passwords!
     99  /**
     100   * POP3 Timeout Value
     101   * @var int
     102   */
     103  public $tval;
    41104
    42     var $BANNER     = '';       //  Holds the banner returned by the
    43                                 //  pop server - used for apop()
     105  /**
     106   * POP3 Username
     107   * @var string
     108   */
     109  public $username;
    44110
    45     var $ALLOWAPOP  = FALSE;    //  Allow or disallow apop()
    46                                 //  This must be set to true
    47                                 //  manually
     111  /**
     112   * POP3 Password
     113   * @var string
     114   */
     115  public $password;
    48116
    49     function POP3 ( $server = '', $timeout = '' ) {
    50         settype($this->BUFFER,"integer");
    51         if( !empty($server) ) {
    52             // Do not allow programs to alter MAILSERVER
    53             // if it is already specified. They can get around
    54             // this if they -really- want to, so don't count on it.
    55             if(empty($this->MAILSERVER))
    56                 $this->MAILSERVER = $server;
    57         }
    58         if(!empty($timeout)) {
    59             settype($timeout,"integer");
    60             $this->TIMEOUT = $timeout;
    61             if (!ini_get('safe_mode'))
    62                 set_time_limit($timeout);
    63         }
    64         return true;
    65     }
     117  /////////////////////////////////////////////////
     118  // PROPERTIES, PRIVATE AND PROTECTED
     119  /////////////////////////////////////////////////
    66120
    67     function update_timer () {
    68         if (!ini_get('safe_mode'))
    69             set_time_limit($this->TIMEOUT);
    70         return true;
    71     }
     121  private $pop_conn;
     122  private $connected;
     123  private $error;     //  Error log array
    72124
    73     function connect ($server, $port = 110)  {
    74         //  Opens a socket to the specified server. Unless overridden,
    75         //  port defaults to 110. Returns true on success, false on fail
     125  /**
     126   * Constructor, sets the initial values
     127   * @access public
     128   * @return POP3
     129   */
     130  public function __construct() {
     131    $this->pop_conn  = 0;
     132    $this->connected = false;
     133    $this->error     = null;
     134  }
    76135
    77         // If MAILSERVER is set, override $server with it's value
     136  /**
     137   * Combination of public events - connect, login, disconnect
     138   * @access public
     139   * @param string $host
     140   * @param integer $port
     141   * @param integer $tval
     142   * @param string $username
     143   * @param string $password
     144   */
     145  public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) {
     146    $this->host = $host;
    78147
    79         if (!isset($port) || !$port) {$port = 110;}
    80         if(!empty($this->MAILSERVER))
    81             $server = $this->MAILSERVER;
     148    //  If no port value is passed, retrieve it
     149    if ($port == false) {
     150      $this->port = $this->POP3_PORT;
     151    } else {
     152      $this->port = $port;
     153    }
    82154
    83         if(empty($server)){
    84             $this->ERROR = "POP3 connect: " . _("No server specified");
    85             unset($this->FP);
    86             return false;
    87         }
     155    //  If no port value is passed, retrieve it
     156    if ($tval == false) {
     157      $this->tval = $this->POP3_TIMEOUT;
     158    } else {
     159      $this->tval = $tval;
     160    }
    88161
    89         $fp = @fsockopen("$server", $port, $errno, $errstr);
     162    $this->do_debug = $debug_level;
     163    $this->username = $username;
     164    $this->password = $password;
    90165
    91         if(!$fp) {
    92             $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]";
    93             unset($this->FP);
    94             return false;
    95         }
     166    //  Refresh the error log
     167    $this->error = null;
    96168
    97         socket_set_blocking($fp,-1);
    98         $this->update_timer();
    99         $reply = fgets($fp,$this->BUFFER);
    100         $reply = $this->strip_clf($reply);
    101         if($this->DEBUG)
    102             error_log("POP3 SEND [connect: $server] GOT [$reply]",0);
    103         if(!$this->is_ok($reply)) {
    104             $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]";
    105             unset($this->FP);
    106             return false;
    107         }
    108         $this->FP = $fp;
    109         $this->BANNER = $this->parse_banner($reply);
    110         return true;
    111     }
     169    //  Connect
     170    $result = $this->Connect($this->host, $this->port, $this->tval);
    112171
    113     function user ($user = "") {
    114         // Sends the USER command, returns true or false
     172    if ($result) {
     173      $login_result = $this->Login($this->username, $this->password);
    115174
    116         if( empty($user) ) {
    117             $this->ERROR = "POP3 user: " . _("no login ID submitted");
    118             return false;
    119         } elseif(!isset($this->FP)) {
    120             $this->ERROR = "POP3 user: " . _("connection not established");
    121             return false;
    122         } else {
    123             $reply = $this->send_cmd("USER $user");
    124             if(!$this->is_ok($reply)) {
    125                 $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]";
    126                 return false;
    127             } else
    128                 return true;
    129         }
    130     }
     175      if ($login_result) {
     176        $this->Disconnect();
    131177
    132     function pass ($pass = "")     {
    133         // Sends the PASS command, returns # of msgs in mailbox,
    134         // returns false (undef) on Auth failure
     178        return true;
     179      }
    135180
    136         if(empty($pass)) {
    137             $this->ERROR = "POP3 pass: " . _("No password submitted");
    138             return false;
    139         } elseif(!isset($this->FP)) {
    140             $this->ERROR = "POP3 pass: " . _("connection not established");
    141             return false;
    142         } else {
    143             $reply = $this->send_cmd("PASS $pass");
    144             if(!$this->is_ok($reply)) {
    145                 $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]";
    146                 $this->quit();
    147                 return false;
    148             } else {
    149                 //  Auth successful.
    150                 $count = $this->last("count");
    151                 $this->COUNT = $count;
    152                 return $count;
    153             }
    154         }
    155181    }
    156182
    157     function apop ($login,$pass) {
    158         //  Attempts an APOP login. If this fails, it'll
    159         //  try a standard login. YOUR SERVER MUST SUPPORT
    160         //  THE USE OF THE APOP COMMAND!
    161         //  (apop is optional per rfc1939)
     183    //  We need to disconnect regardless if the login succeeded
     184    $this->Disconnect();
    162185
    163         if(!isset($this->FP)) {
    164             $this->ERROR = "POP3 apop: " . _("No connection to server");
    165             return false;
    166         } elseif(!$this->ALLOWAPOP) {
    167             $retVal = $this->login($login,$pass);
    168             return $retVal;
    169         } elseif(empty($login)) {
    170             $this->ERROR = "POP3 apop: " . _("No login ID submitted");
    171             return false;
    172         } elseif(empty($pass)) {
    173             $this->ERROR = "POP3 apop: " . _("No password submitted");
    174             return false;
    175         } else {
    176             $banner = $this->BANNER;
    177             if( (!$banner) or (empty($banner)) ) {
    178                 $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort");
    179                 $retVal = $this->login($login,$pass);
    180                 return $retVal;
    181             } else {
    182                 $AuthString = $banner;
    183                 $AuthString .= $pass;
    184                 $APOPString = md5($AuthString);
    185                 $cmd = "APOP $login $APOPString";
    186                 $reply = $this->send_cmd($cmd);
    187                 if(!$this->is_ok($reply)) {
    188                     $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort");
    189                     $retVal = $this->login($login,$pass);
    190                     return $retVal;
    191                 } else {
    192                     //  Auth successful.
    193                     $count = $this->last("count");
    194                     $this->COUNT = $count;
    195                     return $count;
    196                 }
    197             }
    198         }
    199     }
     186    return false;
     187  }
    200188
    201     function login ($login = "", $pass = "") {
    202         // Sends both user and pass. Returns # of msgs in mailbox or
    203         // false on failure (or -1, if the error occurs while getting
    204         // the number of messages.)
    205 
    206         if( !isset($this->FP) ) {
    207             $this->ERROR = "POP3 login: " . _("No connection to server");
    208             return false;
    209         } else {
    210             $fp = $this->FP;
    211             if( !$this->user( $login ) ) {
    212                 //  Preserve the error generated by user()
    213                 return false;
    214             } else {
    215                 $count = $this->pass($pass);
    216                 if( (!$count) || ($count == -1) ) {
    217                     //  Preserve the error generated by last() and pass()
    218                     return false;
    219                 } else
    220                     return $count;
    221             }
    222         }
     189  /**
     190   * Connect to the POP3 server
     191   * @access public
     192   * @param string $host
     193   * @param integer $port
     194   * @param integer $tval
     195   * @return boolean
     196   */
     197  public function Connect ($host, $port = false, $tval = 30) {
     198    //  Are we already connected?
     199    if ($this->connected) {
     200      return true;
    223201    }
    224202
    225     function top ($msgNum, $numLines = "0") {
    226         //  Gets the header and first $numLines of the msg body
    227         //  returns data in an array with each returned line being
    228         //  an array element. If $numLines is empty, returns
    229         //  only the header information, and none of the body.
     203    /*
     204    On Windows this will raise a PHP Warning error if the hostname doesn't exist.
     205    Rather than supress it with @fsockopen, let's capture it cleanly instead
     206    */
    230207
    231         if(!isset($this->FP)) {
    232             $this->ERROR = "POP3 top: " . _("No connection to server");
    233             return false;
    234         }
    235         $this->update_timer();
     208    set_error_handler(array(&$this, 'catchWarning'));
    236209
    237         $fp = $this->FP;
    238         $buffer = $this->BUFFER;
    239         $cmd = "TOP $msgNum $numLines";
    240         fwrite($fp, "TOP $msgNum $numLines\r\n");
    241         $reply = fgets($fp, $buffer);
    242         $reply = $this->strip_clf($reply);
    243         if($this->DEBUG) {
    244             @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
    245         }
    246         if(!$this->is_ok($reply))
    247         {
    248             $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]";
    249             return false;
    250         }
     210    //  Connect to the POP3 server
     211    $this->pop_conn = fsockopen($host,    //  POP3 Host
     212                  $port,    //  Port #
     213                  $errno,   //  Error Number
     214                  $errstr,  //  Error Message
     215                  $tval);   //  Timeout (seconds)
    251216
    252         $count = 0;
    253         $MsgArray = array();
     217    //  Restore the error handler
     218    restore_error_handler();
    254219
    255         $line = fgets($fp,$buffer);
    256         while ( !ereg("^\.\r\n",$line))
    257         {
    258             $MsgArray[$count] = $line;
    259             $count++;
    260             $line = fgets($fp,$buffer);
    261             if(empty($line))    { break; }
    262         }
    263 
    264         return $MsgArray;
     220    //  Does the Error Log now contain anything?
     221    if ($this->error && $this->do_debug >= 1) {
     222      $this->displayErrors();
    265223    }
    266224
    267     function pop_list ($msgNum = "") {
    268         //  If called with an argument, returns that msgs' size in octets
    269         //  No argument returns an associative array of undeleted
    270         //  msg numbers and their sizes in octets
     225    //  Did we connect?
     226    if ($this->pop_conn == false) {
     227      //  It would appear not...
     228      $this->error = array(
     229        'error' => "Failed to connect to server $host on port $port",
     230        'errno' => $errno,
     231        'errstr' => $errstr
     232      );
    271233
    272         if(!isset($this->FP))
    273         {
    274             $this->ERROR = "POP3 pop_list: " . _("No connection to server");
    275             return false;
    276         }
    277         $fp = $this->FP;
    278         $Total = $this->COUNT;
    279         if( (!$Total) or ($Total == -1) )
    280         {
    281             return false;
    282         }
    283         if($Total == 0)
    284         {
    285             return array("0","0");
    286             // return -1;   // mailbox empty
    287         }
     234      if ($this->do_debug >= 1) {
     235        $this->displayErrors();
     236      }
    288237
    289         $this->update_timer();
    290 
    291         if(!empty($msgNum))
    292         {
    293             $cmd = "LIST $msgNum";
    294             fwrite($fp,"$cmd\r\n");
    295             $reply = fgets($fp,$this->BUFFER);
    296             $reply = $this->strip_clf($reply);
    297             if($this->DEBUG) {
    298                 @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
    299             }
    300             if(!$this->is_ok($reply))
    301             {
    302                 $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]";
    303                 return false;
    304             }
    305             list($junk,$num,$size) = preg_split('/\s+/',$reply);
    306             return $size;
    307         }
    308         $cmd = "LIST";
    309         $reply = $this->send_cmd($cmd);
    310         if(!$this->is_ok($reply))
    311         {
    312             $reply = $this->strip_clf($reply);
    313             $this->ERROR = "POP3 pop_list: " . _("Error ") .  "[$reply]";
    314             return false;
    315         }
    316         $MsgArray = array();
    317         $MsgArray[0] = $Total;
    318         for($msgC=1;$msgC <= $Total; $msgC++)
    319         {
    320             if($msgC > $Total) { break; }
    321             $line = fgets($fp,$this->BUFFER);
    322             $line = $this->strip_clf($line);
    323             if(ereg("^\.",$line))
    324             {
    325                 $this->ERROR = "POP3 pop_list: " . _("Premature end of list");
    326                 return false;
    327             }
    328             list($thisMsg,$msgSize) = preg_split('/\s+/',$line);
    329             settype($thisMsg,"integer");
    330             if($thisMsg != $msgC)
    331             {
    332                 $MsgArray[$msgC] = "deleted";
    333             }
    334             else
    335             {
    336                 $MsgArray[$msgC] = $msgSize;
    337             }
    338         }
    339         return $MsgArray;
     238      return false;
    340239    }
    341240
    342     function get ($msgNum) {
    343         //  Retrieve the specified msg number. Returns an array
    344         //  where each line of the msg is an array element.
     241    //  Increase the stream time-out
    345242
    346         if(!isset($this->FP))
    347         {
    348             $this->ERROR = "POP3 get: " . _("No connection to server");
    349             return false;
    350         }
     243    //  Check for PHP 4.3.0 or later
     244    if (version_compare(phpversion(), '5.0.0', 'ge')) {
     245      stream_set_timeout($this->pop_conn, $tval, 0);
     246    } else {
     247      //  Does not work on Windows
     248      if (substr(PHP_OS, 0, 3) !== 'WIN') {
     249        socket_set_timeout($this->pop_conn, $tval, 0);
     250      }
     251    }
    351252
    352         $this->update_timer();
     253    //  Get the POP3 server response
     254    $pop3_response = $this->getResponse();
    353255
    354         $fp = $this->FP;
    355         $buffer = $this->BUFFER;
    356         $cmd = "RETR $msgNum";
    357         $reply = $this->send_cmd($cmd);
     256    //  Check for the +OK
     257    if ($this->checkResponse($pop3_response)) {
     258    //  The connection is established and the POP3 server is talking
     259    $this->connected = true;
     260      return true;
     261    }
    358262
    359         if(!$this->is_ok($reply))
    360         {
    361             $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]";
    362             return false;
    363         }
     263  }
    364264
    365         $count = 0;
    366         $MsgArray = array();
     265  /**
     266   * Login to the POP3 server (does not support APOP yet)
     267   * @access public
     268   * @param string $username
     269   * @param string $password
     270   * @return boolean
     271   */
     272  public function Login ($username = '', $password = '') {
     273    if ($this->connected == false) {
     274      $this->error = 'Not connected to POP3 server';
    367275
    368         $line = fgets($fp,$buffer);
    369         while ( !ereg("^\.\r\n",$line))
    370         {
    371             if ( $line[0] == '.' ) { $line = substr($line,1); }
    372             $MsgArray[$count] = $line;
    373             $count++;
    374             $line = fgets($fp,$buffer);
    375             if(empty($line))    { break; }
    376         }
    377         return $MsgArray;
     276      if ($this->do_debug >= 1) {
     277        $this->displayErrors();
     278      }
    378279    }
    379280
    380     function last ( $type = "count" ) {
    381         //  Returns the highest msg number in the mailbox.
    382         //  returns -1 on error, 0+ on success, if type != count
    383         //  results in a popstat() call (2 element array returned)
    384 
    385         $last = -1;
    386         if(!isset($this->FP))
    387         {
    388             $this->ERROR = "POP3 last: " . _("No connection to server");
    389             return $last;
    390         }
    391 
    392         $reply = $this->send_cmd("STAT");
    393         if(!$this->is_ok($reply))
    394         {
    395             $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]";
    396             return $last;
    397         }
    398 
    399         $Vars = preg_split('/\s+/',$reply);
    400         $count = $Vars[1];
    401         $size = $Vars[2];
    402         settype($count,"integer");
    403         settype($size,"integer");
    404         if($type != "count")
    405         {
    406             return array($count,$size);
    407         }
    408         return $count;
     281    if (empty($username)) {
     282      $username = $this->username;
    409283    }
    410284
    411     function reset () {
    412         //  Resets the status of the remote server. This includes
    413         //  resetting the status of ALL msgs to not be deleted.
    414         //  This method automatically closes the connection to the server.
    415 
    416         if(!isset($this->FP))
    417         {
    418             $this->ERROR = "POP3 reset: " . _("No connection to server");
    419             return false;
    420         }
    421         $reply = $this->send_cmd("RSET");
    422         if(!$this->is_ok($reply))
    423         {
    424             //  The POP3 RSET command -never- gives a -ERR
    425             //  response - if it ever does, something truely
    426             //  wild is going on.
    427 
    428             $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]";
    429             @error_log("POP3 reset: ERROR [$reply]",0);
    430         }
    431         $this->quit();
    432         return true;
     285    if (empty($password)) {
     286      $password = $this->password;
    433287    }
    434288
    435     function send_cmd ( $cmd = "" )
    436     {
    437         //  Sends a user defined command string to the
    438         //  POP server and returns the results. Useful for
    439         //  non-compliant or custom POP servers.
    440         //  Do NOT includ the \r\n as part of your command
    441         //  string - it will be appended automatically.
     289    $pop_username = "USER $username" . $this->CRLF;
     290    $pop_password = "PASS $password" . $this->CRLF;
    442291
    443         //  The return value is a standard fgets() call, which
    444         //  will read up to $this->BUFFER bytes of data, until it
    445         //  encounters a new line, or EOF, whichever happens first.
     292    //  Send the Username
     293    $this->sendString($pop_username);
     294    $pop3_response = $this->getResponse();
    446295
    447         //  This method works best if $cmd responds with only
    448         //  one line of data.
     296    if ($this->checkResponse($pop3_response)) {
     297      //  Send the Password
     298      $this->sendString($pop_password);
     299      $pop3_response = $this->getResponse();
    449300
    450         if(!isset($this->FP))
    451         {
    452             $this->ERROR = "POP3 send_cmd: " . _("No connection to server");
    453             return false;
    454         }
    455 
    456         if(empty($cmd))
    457         {
    458             $this->ERROR = "POP3 send_cmd: " . _("Empty command string");
    459             return "";
    460         }
    461 
    462         $fp = $this->FP;
    463         $buffer = $this->BUFFER;
    464         $this->update_timer();
    465         fwrite($fp,"$cmd\r\n");
    466         $reply = fgets($fp,$buffer);
    467         $reply = $this->strip_clf($reply);
    468         if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
    469         return $reply;
    470     }
    471 
    472     function quit() {
    473         //  Closes the connection to the POP3 server, deleting
    474         //  any msgs marked as deleted.
    475 
    476         if(!isset($this->FP))
    477         {
    478             $this->ERROR = "POP3 quit: " . _("connection does not exist");
    479             return false;
    480         }
    481         $fp = $this->FP;
    482         $cmd = "QUIT";
    483         fwrite($fp,"$cmd\r\n");
    484         $reply = fgets($fp,$this->BUFFER);
    485         $reply = $this->strip_clf($reply);
    486         if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
    487         fclose($fp);
    488         unset($this->FP);
     301      if ($this->checkResponse($pop3_response)) {
    489302        return true;
     303      } else {
     304        return false;
     305      }
     306    } else {
     307      return false;
    490308    }
     309  }
    491310
    492     function popstat () {
    493         //  Returns an array of 2 elements. The number of undeleted
    494         //  msgs in the mailbox, and the size of the mbox in octets.
     311  /**
     312   * Disconnect from the POP3 server
     313   * @access public
     314   */
     315  public function Disconnect () {
     316    $this->sendString('QUIT');
    495317
    496         $PopArray = $this->last("array");
     318    fclose($this->pop_conn);
     319  }
    497320
    498         if($PopArray == -1) { return false; }
     321  /////////////////////////////////////////////////
     322  //  Private Methods
     323  /////////////////////////////////////////////////
    499324
    500         if( (!$PopArray) or (empty($PopArray)) )
    501         {
    502             return false;
    503         }
    504         return $PopArray;
    505     }
     325  /**
     326   * Get the socket response back.
     327   * $size is the maximum number of bytes to retrieve
     328   * @access private
     329   * @param integer $size
     330   * @return string
     331   */
     332  private function getResponse ($size = 128) {
     333    $pop3_response = fgets($this->pop_conn, $size);
    506334
    507     function uidl ($msgNum = "")
    508     {
    509         //  Returns the UIDL of the msg specified. If called with
    510         //  no arguments, returns an associative array where each
    511         //  undeleted msg num is a key, and the msg's uidl is the element
    512         //  Array element 0 will contain the total number of msgs
     335    return $pop3_response;
     336  }
    513337
    514         if(!isset($this->FP)) {
    515             $this->ERROR = "POP3 uidl: " . _("No connection to server");
    516             return false;
    517         }
     338  /**
     339   * Send a string down the open socket connection to the POP3 server
     340   * @access private
     341   * @param string $string
     342   * @return integer
     343   */
     344  private function sendString ($string) {
     345    $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));
    518346
    519         $fp = $this->FP;
    520         $buffer = $this->BUFFER;
     347    return $bytes_sent;
     348  }
    521349
    522         if(!empty($msgNum)) {
    523             $cmd = "UIDL $msgNum";
    524             $reply = $this->send_cmd($cmd);
    525             if(!$this->is_ok($reply))
    526             {
    527                 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
    528                 return false;
    529             }
    530             list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply);
    531             return $myUidl;
    532         } else {
    533             $this->update_timer();
     350  /**
     351   * Checks the POP3 server response for +OK or -ERR
     352   * @access private
     353   * @param string $string
     354   * @return boolean
     355   */
     356  private function checkResponse ($string) {
     357    if (substr($string, 0, 3) !== '+OK') {
     358      $this->error = array(
     359        'error' => "Server reported an error: $string",
     360        'errno' => 0,
     361        'errstr' => ''
     362      );
    534363
    535             $UIDLArray = array();
    536             $Total = $this->COUNT;
    537             $UIDLArray[0] = $Total;
     364      if ($this->do_debug >= 1) {
     365        $this->displayErrors();
     366      }
    538367
    539             if ($Total < 1)
    540             {
    541                 return $UIDLArray;
    542             }
    543             $cmd = "UIDL";
    544             fwrite($fp, "UIDL\r\n");
    545             $reply = fgets($fp, $buffer);
    546             $reply = $this->strip_clf($reply);
    547             if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
    548             if(!$this->is_ok($reply))
    549             {
    550                 $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
    551                 return false;
    552             }
    553 
    554             $line = "";
    555             $count = 1;
    556             $line = fgets($fp,$buffer);
    557             while ( !ereg("^\.\r\n",$line)) {
    558                 if(ereg("^\.\r\n",$line)) {
    559                     break;
    560                 }
    561                 list ($msg,$msgUidl) = preg_split('/\s+/',$line);
    562                 $msgUidl = $this->strip_clf($msgUidl);
    563                 if($count == $msg) {
    564                     $UIDLArray[$msg] = $msgUidl;
    565                 }
    566                 else
    567                 {
    568                     $UIDLArray[$count] = 'deleted';
    569                 }
    570                 $count++;
    571                 $line = fgets($fp,$buffer);
    572             }
    573         }
    574         return $UIDLArray;
     368      return false;
     369    } else {
     370      return true;
    575371    }
    576372
    577     function delete ($msgNum = "") {
    578         //  Flags a specified msg as deleted. The msg will not
    579         //  be deleted until a quit() method is called.
     373  }
    580374
    581         if(!isset($this->FP))
    582         {
    583             $this->ERROR = "POP3 delete: " . _("No connection to server");
    584             return false;
    585         }
    586         if(empty($msgNum))
    587         {
    588             $this->ERROR = "POP3 delete: " . _("No msg number submitted");
    589             return false;
    590         }
    591         $reply = $this->send_cmd("DELE $msgNum");
    592         if(!$this->is_ok($reply))
    593         {
    594             $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]";
    595             return false;
    596         }
    597         return true;
    598     }
     375  /**
     376   * If debug is enabled, display the error message array
     377   * @access private
     378   */
     379  private function displayErrors () {
     380    echo '<pre>';
    599381
    600     //  *********************************************************
    601 
    602     //  The following methods are internal to the class.
    603 
    604     function is_ok ($cmd = "") {
    605         //  Return true or false on +OK or -ERR
    606 
    607         if( empty($cmd) )
    608             return false;
    609         else
    610             return( ereg ("^\+OK", $cmd ) );
     382    foreach ($this->error as $single_error) {
     383      print_r($single_error);
    611384    }
    612385
    613     function strip_clf ($text = "") {
    614         // Strips \r\n from server responses
     386    echo '</pre>';
     387  }
    615388
    616         if(empty($text))
    617             return $text;
    618         else {
    619             $stripped = str_replace("\r",'',$text);
    620             $stripped = str_replace("\n",'',$stripped);
    621             return $stripped;
    622         }
    623     }
     389  /**
     390   * Takes over from PHP for the socket warning handler
     391   * @access private
     392   * @param integer $errno
     393   * @param string $errstr
     394   * @param string $errfile
     395   * @param integer $errline
     396   */
     397  private function catchWarning ($errno, $errstr, $errfile, $errline) {
     398    $this->error[] = array(
     399      'error' => "Connecting to the POP3 server raised a PHP warning: ",
     400      'errno' => $errno,
     401      'errstr' => $errstr
     402    );
     403  }
    624404
    625     function parse_banner ( $server_text ) {
    626         $outside = true;
    627         $banner = "";
    628         $length = strlen($server_text);
    629         for($count =0; $count < $length; $count++)
    630         {
    631             $digit = substr($server_text,$count,1);
    632             if(!empty($digit))             {
    633                 if( (!$outside) && ($digit != '<') && ($digit != '>') )
    634                 {
    635                     $banner .= $digit;
    636                 }
    637                 if ($digit == '<')
    638                 {
    639                     $outside = false;
    640                 }
    641                 if($digit == '>')
    642                 {
    643                     $outside = true;
    644                 }
    645             }
    646         }
    647         $banner = $this->strip_clf($banner);    // Just in case
    648         return "<$banner>";
    649     }
    650 
    651 }   // End class
    652 ?>
     405  //  End of class
     406}
     407?>
     408 No newline at end of file
  • wp-includes/class-smtp.php

     
    22/*~ class.smtp.php
    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| ------------------------------------------------------------------------- |
    1517|   License: Distributed under the Lesser General Public License (LGPL)     |
     
    2325| - Technology Consulting                                                   |
    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
    2943 * commands except TURN which will always return a not implemented
    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  /**
    4557   *  SMTP reply line ending
    4658   *  @var string
    4759   */
    48   var $CRLF = "\r\n";
     60  public $CRLF = "\r\n";
    4961
    5062  /**
    5163   *  Sets whether debugging is turned on
    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  /**
    5769   *  Sets VERP use on/off (default is off)
    5870   *  @var bool
    5971   */
    60   var $do_verp = false;
     72  public $do_verp = false;
    6173
    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   /**#@-*/
     74  /////////////////////////////////////////////////
     75  // PROPERTIES, PRIVATE AND PROTECTED
     76  /////////////////////////////////////////////////
    6977
     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
     81
    7082  /**
    7183   * Initialize the class so that the data is in a known state.
    7284   * @access public
    7385   * @return void
    7486   */
    75   function SMTP() {
     87  public function __construct() {
    7688    $this->smtp_conn = 0;
    7789    $this->error = null;
    7890    $this->helo_rply = null;
     
    8092    $this->do_debug = 0;
    8193  }
    8294
    83   /*************************************************************
    84    *                    CONNECTION FUNCTIONS                  *
    85    ***********************************************************/
     95  /////////////////////////////////////////////////
     96  // CONNECTION FUNCTIONS
     97  /////////////////////////////////////////////////
    8698
    8799  /**
    88100   * Connect to the server specified on the port specified.
     
    97109   * @access public
    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;
    111121    }
     
    114124      $port = $this->SMTP_PORT;
    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",
    126136                           "errno" => $errno,
    127137                           "errstr" => $errstr);
    128138      if($this->do_debug >= 1) {
    129         echo "SMTP -> ERROR: " . $this->error["error"] .
    130                  ": $errstr ($errno)" . $this->CRLF;
     139        echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
    131140      }
    132141      return false;
    133142    }
    134143
    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
     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);
     152    if($this->do_debug >= 2) {
     153      echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
     154    }
    147155
     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
    148181    if($this->do_debug >= 2) {
    149       echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
     182      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
    150183    }
    151184
     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;
     199    }
     200
    152201    return true;
    153202  }
    154203
     
    158207   * @access public
    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);
    164213
     
    171220              "smtp_code" => $code,
    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;
    178226    }
     
    189237              "smtp_code" => $code,
    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;
    196243    }
     
    207254              "smtp_code" => $code,
    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;
    214260    }
     
    218264
    219265  /**
    220266   * Returns true if connected to a server otherwise false
    221    * @access private
     267   * @access public
    222268   * @return bool
    223269   */
    224   function Connected() {
     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;
    240284  }
     
    246290   * @access public
    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;
    256300    }
    257301  }
    258302
    259   /***************************************************************
    260    *                        SMTP COMMANDS                       *
    261    *************************************************************/
     303  /////////////////////////////////////////////////
     304  // SMTP COMMANDS
     305  /////////////////////////////////////////////////
    262306
    263307  /**
    264308   * Issues a data command and sends the msg_data to the server
    265309   * finializing the mail transaction. $msg_data is the message
    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>
    271315   *
     
    279323   * @access public
    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()) {
    286330      $this->error = array(
     
    294338    $code = substr($rply,0,3);
    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
    300344    if($code != 354) {
     
    303347              "smtp_code" => $code,
    304348              "smtp_msg" => substr($rply,4));
    305349      if($this->do_debug >= 1) {
    306         echo "SMTP -> ERROR: " . $this->error["error"] .
    307                  ": " . $rply . $this->CRLF;
     350        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    308351      }
    309352      return false;
    310353    }
    311354
    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.
     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     */
    321365
    322     # normalize the line breaks so we know the explode works
     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;
    336382    if(!empty($field) && !strstr($field," ")) {
    337383      $in_headers = true;
    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)) {
    343389      $lines_out = null;
    344390      if($line == "" && $in_headers) {
    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;
    364412        }
    365413      }
    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)
    371419        {
     
    377425      }
    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
    384431    $rply = $this->get_lines();
    385432    $code = substr($rply,0,3);
    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
    391438    if($code != 250) {
     
    394441              "smtp_code" => $code,
    395442              "smtp_msg" => substr($rply,4));
    396443      if($this->do_debug >= 1) {
    397         echo "SMTP -> ERROR: " . $this->error["error"] .
    398                  ": " . $rply . $this->CRLF;
     444        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    399445      }
    400446      return false;
    401447    }
     
    403449  }
    404450
    405451  /**
    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;
    458   }
    459 
    460   /**
    461452   * Sends the HELO command to the smtp server.
    462453   * This makes sure that we and the server are in
    463454   * the same known state.
     
    469460   * @access public
    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()) {
    476467      $this->error = array(
     
    478469      return false;
    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
    496485    return true;
     
    501490   * @access private
    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
    507496    $rply = $this->get_lines();
    508497    $code = substr($rply,0,3);
    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
    514503    if($code != 250) {
     
    517506              "smtp_code" => $code,
    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;
    524512    }
     
    529517  }
    530518
    531519  /**
    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;
    582   }
    583 
    584   /**
    585520   * Starts a mail transaction from the email address specified in
    586521   * $from. Returns true if successful or false otherwise. If True
    587522   * the mail transaction is started and then one or more Recipient
     
    595530   * @access public
    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()) {
    602537      $this->error = array(
     
    611546    $code = substr($rply,0,3);
    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
    617552    if($code != 250) {
     
    620555              "smtp_code" => $code,
    621556              "smtp_msg" => substr($rply,4));
    622557      if($this->do_debug >= 1) {
    623         echo "SMTP -> ERROR: " . $this->error["error"] .
    624                  ": " . $rply . $this->CRLF;
     558        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    625559      }
    626560      return false;
    627561    }
     
    629563  }
    630564
    631565  /**
    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;
    667       }
    668       return false;
    669     }
    670     return true;
    671   }
    672 
    673   /**
    674566   * Sends the quit command to the server and then closes the socket
    675567   * if there is no error or the $close_on_error argument is true.
    676568   *
     
    681573   * @access public
    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()) {
    688580      $this->error = array(
     
    690582      return false;
    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
    703595    $rval = true;
     
    705597
    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,
    711603                 "smtp_rply" => substr($byemsg,4));
    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    }
    718609
     
    735626   * @access public
    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()) {
    742633      $this->error = array(
     
    750641    $code = substr($rply,0,3);
    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
    756647    if($code != 250 && $code != 251) {
     
    759650              "smtp_code" => $code,
    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;
    766656    }
     
    779669   * @access public
    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()) {
    786676      $this->error = array(
     
    794684    $code = substr($rply,0,3);
    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
    800690    if($code != 250) {
     
    803693              "smtp_code" => $code,
    804694              "smtp_msg" => substr($rply,4));
    805695      if($this->do_debug >= 1) {
    806         echo "SMTP -> ERROR: " . $this->error["error"] .
    807                  ": " . $rply . $this->CRLF;
     696        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    808697      }
    809698      return false;
    810699    }
     
    818707   * the mail transaction is started and then one or more Recipient
    819708   * commands may be called followed by a Data command. This command
    820709   * 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     }
    860     return true;
    861   }
    862 
    863   /**
    864    * Starts a mail transaction from the email address specified in
    865    * $from. Returns true if successful or false otherwise. If True
    866    * the mail transaction is started and then one or more Recipient
    867    * commands may be called followed by a Data command. This command
    868    * will send the message to the users terminal if they are logged
    869710   * in and send them an email.
    870711   *
    871712   * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
     
    876717   * @access public
    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()) {
    883724      $this->error = array(
     
    891732    $code = substr($rply,0,3);
    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
    897738    if($code != 250) {
     
    900741              "smtp_code" => $code,
    901742              "smtp_msg" => substr($rply,4));
    902743      if($this->do_debug >= 1) {
    903         echo "SMTP -> ERROR: " . $this->error["error"] .
    904                  ": " . $rply . $this->CRLF;
     744        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
    905745      }
    906746      return false;
    907747    }
     
    909749  }
    910750
    911751  /**
    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;
    953       }
    954       return false;
    955     }
    956     return true;
    957   }
    958 
    959   /**
    960752   * This is an optional command for SMTP that this class does not
    961753   * support. This method is here to make the RFC821 Definition
    962754   * complete for this class and __may__ be implimented in the future
     
    969761   * @access public
    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;
    979771  }
    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;
     774  * Get the current error
     775  * @access public
     776  * @return array
     777  */
     778  public function getError() {
     779    return $this->error;
    1024780  }
    1025781
    1026   /*******************************************************************
    1027    *                       INTERNAL FUNCTIONS                       *
    1028    ******************************************************************/
     782  /////////////////////////////////////////////////
     783  // INTERNAL FUNCTIONS
     784  /////////////////////////////////////////////////
    1029785
    1030786  /**
    1031787   * Read in as many lines as possible
     
    1036792   * @access private
    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;
     804        echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
    1051805      }
    1052       # if the 4th character is a space then we are done reading
    1053       # so just break the loop
     806      // if 4th character is a space, we are done reading, break the loop
    1054807      if(substr($str,3,1) == " ") { break; }
    1055808    }
    1056809    return $data;
     
    1058811
    1059812}
    1060813
    1061 
    1062  ?>
     814?>
     815 No newline at end of file