Make WordPress Core


Ignore:
Timestamp:
08/28/2008 08:26:36 PM (16 years ago)
Author:
ryan
Message:

Update phpMailer to 2.0.2. Props mattyrob. fixes #7474

File:
1 edited

Legend:

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

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