web/wp-includes/class-phpmailer.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
     1 <?php
     1 <?php
     2 /*~ class.phpmailer.php
     2 /*~ class.phpmailer.php
     3 .---------------------------------------------------------------------------.
     3 .---------------------------------------------------------------------------.
     4 |  Software: PHPMailer - PHP email class                                    |
     4 |  Software: PHPMailer - PHP email class                                    |
     5 |   Version: 2.0.4                                                          |
     5 |   Version: 5.2.1                                                          |
     6 |   Contact: via sourceforge.net support pages (also www.codeworxtech.com)  |
     6 |      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
     7 |      Info: http://phpmailer.sourceforge.net                               |
       
     8 |   Support: http://sourceforge.net/projects/phpmailer/                     |
       
     9 | ------------------------------------------------------------------------- |
     7 | ------------------------------------------------------------------------- |
    10 |    Author: Andy Prevost (project admininistrator)                         |
     8 |     Admin: Jim Jagielski (project admininistrator)                        |
    11 |    Author: Brent R. Matzelle (original founder)                           |
     9 |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
    12 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved.               |
    10 |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
       
    11 |          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
       
    12 |   Founder: Brent R. Matzelle (original founder)                           |
       
    13 | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved.              |
       
    14 | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
    13 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
    15 | Copyright (c) 2001-2003, Brent R. Matzelle                                |
    14 | ------------------------------------------------------------------------- |
    16 | ------------------------------------------------------------------------- |
    15 |   License: Distributed under the Lesser General Public License (LGPL)     |
    17 |   License: Distributed under the Lesser General Public License (LGPL)     |
    16 |            http://www.gnu.org/copyleft/lesser.html                        |
    18 |            http://www.gnu.org/copyleft/lesser.html                        |
    17 | This program is distributed in the hope that it will be useful - WITHOUT  |
    19 | This program is distributed in the hope that it will be useful - WITHOUT  |
    18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
    20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
    19 | FITNESS FOR A PARTICULAR PURPOSE.                                         |
    21 | 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 '---------------------------------------------------------------------------'
    22 '---------------------------------------------------------------------------'
    26  */
    23 */
       
    24 
    27 /**
    25 /**
    28  * PHPMailer - PHP email transport class
    26  * PHPMailer - PHP email transport class
       
    27  * NOTE: Requires PHP version 5 or later
    29  * @package PHPMailer
    28  * @package PHPMailer
    30  * @author Andy Prevost
    29  * @author Andy Prevost
       
    30  * @author Marcus Bointon
       
    31  * @author Jim Jagielski
       
    32  * @copyright 2010 - 2012 Jim Jagielski
    31  * @copyright 2004 - 2009 Andy Prevost
    33  * @copyright 2004 - 2009 Andy Prevost
       
    34  * @version $Id: class.phpmailer.php 450 2010-06-23 16:46:33Z coolbru $
       
    35  * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
    32  */
    36  */
       
    37 
       
    38 if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
    33 
    39 
    34 class PHPMailer {
    40 class PHPMailer {
    35 
    41 
    36   /////////////////////////////////////////////////
    42   /////////////////////////////////////////////////
    37   // PROPERTIES, PUBLIC
    43   // PROPERTIES, PUBLIC
    39 
    45 
    40   /**
    46   /**
    41    * Email priority (1 = High, 3 = Normal, 5 = low).
    47    * Email priority (1 = High, 3 = Normal, 5 = low).
    42    * @var int
    48    * @var int
    43    */
    49    */
    44   var $Priority          = 3;
    50   public $Priority          = 3;
    45 
    51 
    46   /**
    52   /**
    47    * Sets the CharSet of the message.
    53    * Sets the CharSet of the message.
    48    * @var string
    54    * @var string
    49    */
    55    */
    50   var $CharSet           = 'iso-8859-1';
    56   public $CharSet           = 'iso-8859-1';
    51 
    57 
    52   /**
    58   /**
    53    * Sets the Content-type of the message.
    59    * Sets the Content-type of the message.
    54    * @var string
    60    * @var string
    55    */
    61    */
    56   var $ContentType        = 'text/plain';
    62   public $ContentType       = 'text/plain';
    57 
    63 
    58   /**
    64   /**
    59    * Sets the Encoding of the message. Options for this are "8bit",
    65    * Sets the Encoding of the message. Options for this are
    60    * "7bit", "binary", "base64", and "quoted-printable".
    66    *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
    61    * @var string
    67    * @var string
    62    */
    68    */
    63   var $Encoding          = '8bit';
    69   public $Encoding          = '8bit';
    64 
    70 
    65   /**
    71   /**
    66    * Holds the most recent mailer error message.
    72    * Holds the most recent mailer error message.
    67    * @var string
    73    * @var string
    68    */
    74    */
    69   var $ErrorInfo         = '';
    75   public $ErrorInfo         = '';
    70 
    76 
    71   /**
    77   /**
    72    * Sets the From email address for the message.
    78    * Sets the From email address for the message.
    73    * @var string
    79    * @var string
    74    */
    80    */
    75   var $From              = 'root@localhost';
    81   public $From              = 'root@localhost';
    76 
    82 
    77   /**
    83   /**
    78    * Sets the From name of the message.
    84    * Sets the From name of the message.
    79    * @var string
    85    * @var string
    80    */
    86    */
    81   var $FromName          = 'Root User';
    87   public $FromName          = 'Root User';
    82 
    88 
    83   /**
    89   /**
    84    * Sets the Sender email (Return-Path) of the message.  If not empty,
    90    * 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.
    91    * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
    86    * @var string
    92    * @var string
    87    */
    93    */
    88   var $Sender            = '';
    94   public $Sender            = '';
    89 
    95 
    90   /**
    96   /**
    91    * Sets the Subject of the message.
    97    * Sets the Subject of the message.
    92    * @var string
    98    * @var string
    93    */
    99    */
    94   var $Subject           = '';
   100   public $Subject           = '';
    95 
   101 
    96   /**
   102   /**
    97    * Sets the Body of the message.  This can be either an HTML or text body.
   103    * Sets the Body of the message.  This can be either an HTML or text body.
    98    * If HTML then run IsHTML(true).
   104    * If HTML then run IsHTML(true).
    99    * @var string
   105    * @var string
   100    */
   106    */
   101   var $Body              = '';
   107   public $Body              = '';
   102 
   108 
   103   /**
   109   /**
   104    * Sets the text-only body of the message.  This automatically sets the
   110    * Sets the text-only body of the message.  This automatically sets the
   105    * email to multipart/alternative.  This body can be read by mail
   111    * email to multipart/alternative.  This body can be read by mail
   106    * clients that do not have HTML email capability such as mutt. Clients
   112    * clients that do not have HTML email capability such as mutt. Clients
   107    * that can read HTML will view the normal Body.
   113    * that can read HTML will view the normal Body.
   108    * @var string
   114    * @var string
   109    */
   115    */
   110   var $AltBody           = '';
   116   public $AltBody           = '';
       
   117 
       
   118   /**
       
   119    * Stores the complete compiled MIME message body.
       
   120    * @var string
       
   121    * @access protected
       
   122    */
       
   123   protected $MIMEBody       = '';
       
   124 
       
   125   /**
       
   126    * Stores the complete compiled MIME message headers.
       
   127    * @var string
       
   128    * @access protected
       
   129    */
       
   130   protected $MIMEHeader     = '';
       
   131 
       
   132   /**
       
   133    * Stores the complete sent MIME message (Body and Headers)
       
   134    * @var string
       
   135    * @access protected
       
   136   */
       
   137   protected $SentMIMEMessage     = '';
   111 
   138 
   112   /**
   139   /**
   113    * Sets word wrapping on the body of the message to a given number of
   140    * Sets word wrapping on the body of the message to a given number of
   114    * characters.
   141    * characters.
   115    * @var int
   142    * @var int
   116    */
   143    */
   117   var $WordWrap          = 0;
   144   public $WordWrap          = 0;
   118 
   145 
   119   /**
   146   /**
   120    * Method to send mail: ("mail", "sendmail", or "smtp").
   147    * Method to send mail: ("mail", "sendmail", or "smtp").
   121    * @var string
   148    * @var string
   122    */
   149    */
   123   var $Mailer            = 'mail';
   150   public $Mailer            = 'mail';
   124 
   151 
   125   /**
   152   /**
   126    * Sets the path of the sendmail program.
   153    * Sets the path of the sendmail program.
   127    * @var string
   154    * @var string
   128    */
   155    */
   129   var $Sendmail          = '/usr/sbin/sendmail';
   156   public $Sendmail          = '/usr/sbin/sendmail';
   130 
   157 
   131   /**
   158   /**
   132    * Path to PHPMailer plugins.  This is now only useful if the SMTP class
   159    * Path to PHPMailer plugins.  Useful if the SMTP class
   133    * is in a different directory than the PHP include path.
   160    * is in a different directory than the PHP include path.
   134    * @var string
   161    * @var string
   135    */
   162    */
   136   var $PluginDir         = '';
   163   public $PluginDir         = '';
   137 
       
   138   /**
       
   139    * Holds PHPMailer version.
       
   140    * @var string
       
   141    */
       
   142   var $Version           = "2.0.4";
       
   143 
   164 
   144   /**
   165   /**
   145    * Sets the email address that a reading confirmation will be sent.
   166    * Sets the email address that a reading confirmation will be sent.
   146    * @var string
   167    * @var string
   147    */
   168    */
   148   var $ConfirmReadingTo  = '';
   169   public $ConfirmReadingTo  = '';
   149 
   170 
   150   /**
   171   /**
   151    * Sets the hostname to use in Message-Id and Received headers
   172    * Sets the hostname to use in Message-Id and Received headers
   152    * and as default HELO string. If empty, the value returned
   173    * and as default HELO string. If empty, the value returned
   153    * by SERVER_NAME is used or 'localhost.localdomain'.
   174    * by SERVER_NAME is used or 'localhost.localdomain'.
   154    * @var string
   175    * @var string
   155    */
   176    */
   156   var $Hostname          = '';
   177   public $Hostname          = '';
   157 
   178 
   158   /**
   179   /**
   159    * Sets the message ID to be used in the Message-Id header.
   180    * Sets the message ID to be used in the Message-Id header.
   160    * If empty, a unique id will be generated.
   181    * If empty, a unique id will be generated.
   161    * @var string
   182    * @var string
   162    */
   183    */
   163   var $MessageID         = '';
   184   public $MessageID         = '';
   164 
   185 
   165   /////////////////////////////////////////////////
   186   /////////////////////////////////////////////////
   166   // PROPERTIES FOR SMTP
   187   // PROPERTIES FOR SMTP
   167   /////////////////////////////////////////////////
   188   /////////////////////////////////////////////////
   168 
   189 
   172    * for each host by using this format: [hostname:port]
   193    * for each host by using this format: [hostname:port]
   173    * (e.g. "smtp1.example.com:25;smtp2.example.com").
   194    * (e.g. "smtp1.example.com:25;smtp2.example.com").
   174    * Hosts will be tried in order.
   195    * Hosts will be tried in order.
   175    * @var string
   196    * @var string
   176    */
   197    */
   177   var $Host        = 'localhost';
   198   public $Host          = 'localhost';
   178 
   199 
   179   /**
   200   /**
   180    * Sets the default SMTP server port.
   201    * Sets the default SMTP server port.
   181    * @var int
   202    * @var int
   182    */
   203    */
   183   var $Port        = 25;
   204   public $Port          = 25;
   184 
   205 
   185   /**
   206   /**
   186    * Sets the SMTP HELO of the message (Default is $Hostname).
   207    * Sets the SMTP HELO of the message (Default is $Hostname).
   187    * @var string
   208    * @var string
   188    */
   209    */
   189   var $Helo        = '';
   210   public $Helo          = '';
   190 
   211 
   191   /**
   212   /**
   192    * Sets connection prefix.
   213    * Sets connection prefix.
   193    * Options are "", "ssl" or "tls"
   214    * Options are "", "ssl" or "tls"
   194    * @var string
   215    * @var string
   195    */
   216    */
   196   var $SMTPSecure = "";
   217   public $SMTPSecure    = '';
   197 
   218 
   198   /**
   219   /**
   199    * Sets SMTP authentication. Utilizes the Username and Password variables.
   220    * Sets SMTP authentication. Utilizes the Username and Password variables.
   200    * @var bool
   221    * @var bool
   201    */
   222    */
   202   var $SMTPAuth     = false;
   223   public $SMTPAuth      = false;
   203 
   224 
   204   /**
   225   /**
   205    * Sets SMTP username.
   226    * Sets SMTP username.
   206    * @var string
   227    * @var string
   207    */
   228    */
   208   var $Username     = '';
   229   public $Username      = '';
   209 
   230 
   210   /**
   231   /**
   211    * Sets SMTP password.
   232    * Sets SMTP password.
   212    * @var string
   233    * @var string
   213    */
   234    */
   214   var $Password     = '';
   235   public $Password      = '';
   215 
   236 
   216   /**
   237   /**
   217    * Sets the SMTP server timeout in seconds. This function will not
   238    * Sets the SMTP server timeout in seconds.
   218    * work with the win32 version.
   239    * This function will not work with the win32 version.
   219    * @var int
   240    * @var int
   220    */
   241    */
   221   var $Timeout      = 10;
   242   public $Timeout       = 10;
   222 
   243 
   223   /**
   244   /**
   224    * Sets SMTP class debugging on or off.
   245    * Sets SMTP class debugging on or off.
   225    * @var bool
   246    * @var bool
   226    */
   247    */
   227   var $SMTPDebug    = false;
   248   public $SMTPDebug     = false;
   228 
   249 
   229   /**
   250   /**
   230    * Prevents the SMTP connection from being closed after each mail
   251    * Prevents the SMTP connection from being closed after each mail
   231    * sending.  If this is set to true then to close the connection
   252    * sending.  If this is set to true then to close the connection
   232    * requires an explicit call to SmtpClose().
   253    * requires an explicit call to SmtpClose().
   233    * @var bool
   254    * @var bool
   234    */
   255    */
   235   var $SMTPKeepAlive = false;
   256   public $SMTPKeepAlive = false;
   236 
   257 
   237   /**
   258   /**
   238    * Provides the ability to have the TO field process individual
   259    * Provides the ability to have the TO field process individual
   239    * emails, instead of sending to entire TO addresses
   260    * emails, instead of sending to entire TO addresses
   240    * @var bool
   261    * @var bool
   241    */
   262    */
   242   var $SingleTo = false;
   263   public $SingleTo      = false;
       
   264 
       
   265    /**
       
   266    * If SingleTo is true, this provides the array to hold the email addresses
       
   267    * @var bool
       
   268    */
       
   269   public $SingleToArray = array();
       
   270 
       
   271  /**
       
   272    * Provides the ability to change the line ending
       
   273    * @var string
       
   274    */
       
   275   public $LE              = "\n";
       
   276 
       
   277   /**
       
   278    * Used with DKIM DNS Resource Record
       
   279    * @var string
       
   280    */
       
   281   public $DKIM_selector   = 'phpmailer';
       
   282 
       
   283   /**
       
   284    * Used with DKIM DNS Resource Record
       
   285    * optional, in format of email address 'you@yourdomain.com'
       
   286    * @var string
       
   287    */
       
   288   public $DKIM_identity   = '';
       
   289 
       
   290   /**
       
   291    * Used with DKIM DNS Resource Record
       
   292    * @var string
       
   293    */
       
   294   public $DKIM_passphrase   = '';
       
   295 
       
   296   /**
       
   297    * Used with DKIM DNS Resource Record
       
   298    * optional, in format of email address 'you@yourdomain.com'
       
   299    * @var string
       
   300    */
       
   301   public $DKIM_domain     = '';
       
   302 
       
   303   /**
       
   304    * Used with DKIM DNS Resource Record
       
   305    * optional, in format of email address 'you@yourdomain.com'
       
   306    * @var string
       
   307    */
       
   308   public $DKIM_private    = '';
       
   309 
       
   310   /**
       
   311    * Callback Action function name
       
   312    * the function that handles the result of the send email action. Parameters:
       
   313    *   bool    $result        result of the send action
       
   314    *   string  $to            email address of the recipient
       
   315    *   string  $cc            cc email addresses
       
   316    *   string  $bcc           bcc email addresses
       
   317    *   string  $subject       the subject
       
   318    *   string  $body          the email body
       
   319    * @var string
       
   320    */
       
   321   public $action_function = ''; //'callbackAction';
       
   322 
       
   323   /**
       
   324    * Sets the PHPMailer Version number
       
   325    * @var string
       
   326    */
       
   327   public $Version         = '5.2.1';
       
   328 
       
   329   /**
       
   330    * What to use in the X-Mailer header
       
   331    * @var string
       
   332    */
       
   333   public $XMailer         = '';
   243 
   334 
   244   /////////////////////////////////////////////////
   335   /////////////////////////////////////////////////
   245   // PROPERTIES, PRIVATE
   336   // PROPERTIES, PRIVATE AND PROTECTED
   246   /////////////////////////////////////////////////
   337   /////////////////////////////////////////////////
   247 
   338 
   248   var $smtp            = NULL;
   339   protected   $smtp           = NULL;
   249   var $to              = array();
   340   protected   $to             = array();
   250   var $cc              = array();
   341   protected   $cc             = array();
   251   var $bcc             = array();
   342   protected   $bcc            = array();
   252   var $ReplyTo         = array();
   343   protected   $ReplyTo        = array();
   253   var $attachment      = array();
   344   protected   $all_recipients = array();
   254   var $CustomHeader    = array();
   345   protected   $attachment     = array();
   255   var $message_type    = '';
   346   protected   $CustomHeader   = array();
   256   var $boundary        = array();
   347   protected   $message_type   = '';
   257   var $language        = array();
   348   protected   $boundary       = array();
   258   var $error_count     = 0;
   349   protected   $language       = array();
   259   var $LE              = "\n";
   350   protected   $error_count    = 0;
   260   var $sign_cert_file  = "";
   351   protected   $sign_cert_file = '';
   261   var $sign_key_file   = "";
   352   protected   $sign_key_file  = '';
   262   var $sign_key_pass   = "";
   353   protected   $sign_key_pass  = '';
       
   354   protected   $exceptions     = false;
       
   355 
       
   356   /////////////////////////////////////////////////
       
   357   // CONSTANTS
       
   358   /////////////////////////////////////////////////
       
   359 
       
   360   const STOP_MESSAGE  = 0; // message only, continue processing
       
   361   const STOP_CONTINUE = 1; // message?, likely ok to continue processing
       
   362   const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
   263 
   363 
   264   /////////////////////////////////////////////////
   364   /////////////////////////////////////////////////
   265   // METHODS, VARIABLES
   365   // METHODS, VARIABLES
   266   /////////////////////////////////////////////////
   366   /////////////////////////////////////////////////
   267 
   367 
   268   /**
   368   /**
       
   369    * Constructor
       
   370    * @param boolean $exceptions Should we throw external exceptions?
       
   371    */
       
   372   public function __construct($exceptions = false) {
       
   373     $this->exceptions = ($exceptions == true);
       
   374   }
       
   375 
       
   376   /**
   269    * Sets message type to HTML.
   377    * Sets message type to HTML.
   270    * @param bool $bool
   378    * @param bool $ishtml
   271    * @return void
   379    * @return void
   272    */
   380    */
   273   function IsHTML($bool) {
   381   public function IsHTML($ishtml = true) {
   274     if($bool == true) {
   382     if ($ishtml) {
   275       $this->ContentType = 'text/html';
   383       $this->ContentType = 'text/html';
   276     } else {
   384     } else {
   277       $this->ContentType = 'text/plain';
   385       $this->ContentType = 'text/plain';
   278     }
   386     }
   279   }
   387   }
   280 
   388 
   281   /**
   389   /**
   282    * Sets Mailer to send message using SMTP.
   390    * Sets Mailer to send message using SMTP.
   283    * @return void
   391    * @return void
   284    */
   392    */
   285   function IsSMTP() {
   393   public function IsSMTP() {
   286     $this->Mailer = 'smtp';
   394     $this->Mailer = 'smtp';
   287   }
   395   }
   288 
   396 
   289   /**
   397   /**
   290    * Sets Mailer to send message using PHP mail() function.
   398    * Sets Mailer to send message using PHP mail() function.
   291    * @return void
   399    * @return void
   292    */
   400    */
   293   function IsMail() {
   401   public function IsMail() {
   294     $this->Mailer = 'mail';
   402     $this->Mailer = 'mail';
   295   }
   403   }
   296 
   404 
   297   /**
   405   /**
   298    * Sets Mailer to send message using the $Sendmail program.
   406    * Sets Mailer to send message using the $Sendmail program.
   299    * @return void
   407    * @return void
   300    */
   408    */
   301   function IsSendmail() {
   409   public function IsSendmail() {
       
   410     if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
       
   411       $this->Sendmail = '/var/qmail/bin/sendmail';
       
   412     }
   302     $this->Mailer = 'sendmail';
   413     $this->Mailer = 'sendmail';
   303   }
   414   }
   304 
   415 
   305   /**
   416   /**
   306    * Sets Mailer to send message using the qmail MTA.
   417    * Sets Mailer to send message using the qmail MTA.
   307    * @return void
   418    * @return void
   308    */
   419    */
   309   function IsQmail() {
   420   public function IsQmail() {
   310     $this->Sendmail = '/var/qmail/bin/sendmail';
   421     if (stristr(ini_get('sendmail_path'), 'qmail')) {
       
   422       $this->Sendmail = '/var/qmail/bin/sendmail';
       
   423     }
   311     $this->Mailer = 'sendmail';
   424     $this->Mailer = 'sendmail';
   312   }
   425   }
   313 
   426 
   314   /////////////////////////////////////////////////
   427   /////////////////////////////////////////////////
   315   // METHODS, RECIPIENTS
   428   // METHODS, RECIPIENTS
   317 
   430 
   318   /**
   431   /**
   319    * Adds a "To" address.
   432    * Adds a "To" address.
   320    * @param string $address
   433    * @param string $address
   321    * @param string $name
   434    * @param string $name
   322    * @return void
   435    * @return boolean true on success, false if address already used
   323    */
   436    */
   324   function AddAddress($address, $name = '') {
   437   public function AddAddress($address, $name = '') {
   325     $cur = count($this->to);
   438     return $this->AddAnAddress('to', $address, $name);
   326     $this->to[$cur][0] = trim($address);
   439   }
   327     $this->to[$cur][1] = $name;
   440 
   328   }
   441   /**
   329 
   442    * Adds a "Cc" address.
   330   /**
   443    * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
   331    * Adds a "Cc" address. Note: this function works
       
   332    * with the SMTP mailer on win32, not with the "mail"
       
   333    * mailer.
       
   334    * @param string $address
   444    * @param string $address
   335    * @param string $name
   445    * @param string $name
   336    * @return void
   446    * @return boolean true on success, false if address already used
   337    */
   447    */
   338   function AddCC($address, $name = '') {
   448   public function AddCC($address, $name = '') {
   339     $cur = count($this->cc);
   449     return $this->AddAnAddress('cc', $address, $name);
   340     $this->cc[$cur][0] = trim($address);
   450   }
   341     $this->cc[$cur][1] = $name;
   451 
   342   }
   452   /**
   343 
   453    * Adds a "Bcc" address.
   344   /**
   454    * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
   345    * Adds a "Bcc" address. Note: this function works
       
   346    * with the SMTP mailer on win32, not with the "mail"
       
   347    * mailer.
       
   348    * @param string $address
   455    * @param string $address
   349    * @param string $name
   456    * @param string $name
   350    * @return void
   457    * @return boolean true on success, false if address already used
   351    */
   458    */
   352   function AddBCC($address, $name = '') {
   459   public function AddBCC($address, $name = '') {
   353     $cur = count($this->bcc);
   460     return $this->AddAnAddress('bcc', $address, $name);
   354     $this->bcc[$cur][0] = trim($address);
   461   }
   355     $this->bcc[$cur][1] = $name;
   462 
   356   }
   463   /**
   357 
   464    * Adds a "Reply-to" address.
   358   /**
       
   359    * Adds a "Reply-To" address.
       
   360    * @param string $address
   465    * @param string $address
   361    * @param string $name
   466    * @param string $name
   362    * @return void
   467    * @return boolean
   363    */
   468    */
   364   function AddReplyTo($address, $name = '') {
   469   public function AddReplyTo($address, $name = '') {
   365     $cur = count($this->ReplyTo);
   470     return $this->AddAnAddress('Reply-To', $address, $name);
   366     $this->ReplyTo[$cur][0] = trim($address);
   471   }
   367     $this->ReplyTo[$cur][1] = $name;
   472 
       
   473   /**
       
   474    * Adds an address to one of the recipient arrays
       
   475    * Addresses that have been added already return false, but do not throw exceptions
       
   476    * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
       
   477    * @param string $address The email address to send to
       
   478    * @param string $name
       
   479    * @return boolean true on success, false if address already used or invalid in some way
       
   480    * @access protected
       
   481    */
       
   482   protected function AddAnAddress($kind, $address, $name = '') {
       
   483     if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
       
   484       $this->SetError($this->Lang('Invalid recipient array').': '.$kind);
       
   485       if ($this->exceptions) {
       
   486         throw new phpmailerException('Invalid recipient array: ' . $kind);
       
   487       }
       
   488 	  if ($this->SMTPDebug) {
       
   489         echo $this->Lang('Invalid recipient array').': '.$kind;
       
   490       }
       
   491       return false;
       
   492     }
       
   493     $address = trim($address);
       
   494     $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
       
   495     if (!self::ValidateAddress($address)) {
       
   496       $this->SetError($this->Lang('invalid_address').': '. $address);
       
   497       if ($this->exceptions) {
       
   498         throw new phpmailerException($this->Lang('invalid_address').': '.$address);
       
   499       }
       
   500 	  if ($this->SMTPDebug) {
       
   501         echo $this->Lang('invalid_address').': '.$address;
       
   502       }
       
   503       return false;
       
   504     }
       
   505     if ($kind != 'Reply-To') {
       
   506       if (!isset($this->all_recipients[strtolower($address)])) {
       
   507         array_push($this->$kind, array($address, $name));
       
   508         $this->all_recipients[strtolower($address)] = true;
       
   509         return true;
       
   510       }
       
   511     } else {
       
   512       if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
       
   513         $this->ReplyTo[strtolower($address)] = array($address, $name);
       
   514       return true;
       
   515     }
       
   516   }
       
   517   return false;
       
   518 }
       
   519 
       
   520 /**
       
   521  * Set the From and FromName properties
       
   522  * @param string $address
       
   523  * @param string $name
       
   524  * @return boolean
       
   525  */
       
   526   public function SetFrom($address, $name = '', $auto = 1) {
       
   527     $address = trim($address);
       
   528     $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
       
   529     if (!self::ValidateAddress($address)) {
       
   530       $this->SetError($this->Lang('invalid_address').': '. $address);
       
   531       if ($this->exceptions) {
       
   532         throw new phpmailerException($this->Lang('invalid_address').': '.$address);
       
   533       }
       
   534 	  if ($this->SMTPDebug) {
       
   535         echo $this->Lang('invalid_address').': '.$address;
       
   536       }
       
   537       return false;
       
   538     }
       
   539     $this->From = $address;
       
   540     $this->FromName = $name;
       
   541     if ($auto) {
       
   542       if (empty($this->ReplyTo)) {
       
   543         $this->AddAnAddress('Reply-To', $address, $name);
       
   544       }
       
   545       if (empty($this->Sender)) {
       
   546         $this->Sender = $address;
       
   547       }
       
   548     }
       
   549     return true;
       
   550   }
       
   551 
       
   552   /**
       
   553    * Check that a string looks roughly like an email address should
       
   554    * Static so it can be used without instantiation
       
   555    * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
       
   556    * Conforms approximately to RFC2822
       
   557    * @link http://www.hexillion.com/samples/#Regex Original pattern found here
       
   558    * @param string $address The email address to check
       
   559    * @return boolean
       
   560    * @static
       
   561    * @access public
       
   562    */
       
   563   public static function ValidateAddress($address) {
       
   564     if (function_exists('filter_var')) { //Introduced in PHP 5.2
       
   565       if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
       
   566         return false;
       
   567       } else {
       
   568         return true;
       
   569       }
       
   570     } else {
       
   571       return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
       
   572     }
   368   }
   573   }
   369 
   574 
   370   /////////////////////////////////////////////////
   575   /////////////////////////////////////////////////
   371   // METHODS, MAIL SENDING
   576   // METHODS, MAIL SENDING
   372   /////////////////////////////////////////////////
   577   /////////////////////////////////////////////////
   375    * Creates message and assigns Mailer. If the message is
   580    * Creates message and assigns Mailer. If the message is
   376    * not sent successfully then it returns false.  Use the ErrorInfo
   581    * not sent successfully then it returns false.  Use the ErrorInfo
   377    * variable to view description of the error.
   582    * variable to view description of the error.
   378    * @return bool
   583    * @return bool
   379    */
   584    */
   380   function Send() {
   585   public function Send() {
   381     $header = '';
   586     try {
   382     $body = '';
   587       if(!$this->PreSend()) return false;
   383     $result = true;
   588       return $this->PostSend();
   384 
   589     } catch (phpmailerException $e) {
   385     if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
   590 	  $this->SentMIMEMessage = '';
   386       $this->SetError($this->Lang('provide_address'));
   591       $this->SetError($e->getMessage());
       
   592       if ($this->exceptions) {
       
   593         throw $e;
       
   594       }
   387       return false;
   595       return false;
   388     }
   596     }
   389 
   597   }
   390     /* Set whether the message is multipart/alternative */
   598 
   391     if(!empty($this->AltBody)) {
   599   protected function PreSend() {
   392       $this->ContentType = 'multipart/alternative';
   600     try {
   393     }
   601 	  $mailHeader = "";
   394 
   602       if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
   395     $this->error_count = 0; // reset errors
   603         throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
   396     $this->SetMessageType();
   604       }
   397     $header .= $this->CreateHeader();
   605 
   398     $body = $this->CreateBody();
   606       // Set whether the message is multipart/alternative
   399 
   607       if(!empty($this->AltBody)) {
   400     if($body == '') {
   608         $this->ContentType = 'multipart/alternative';
       
   609       }
       
   610 
       
   611       $this->error_count = 0; // reset errors
       
   612       $this->SetMessageType();
       
   613       //Refuse to send an empty message
       
   614       if (empty($this->Body)) {
       
   615         throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
       
   616       }
       
   617 
       
   618       $this->MIMEHeader = $this->CreateHeader();
       
   619       $this->MIMEBody = $this->CreateBody();
       
   620 
       
   621       // To capture the complete message when using mail(), create
       
   622 	  // an extra header list which CreateHeader() doesn't fold in
       
   623       if ($this->Mailer == 'mail') {
       
   624         if (count($this->to) > 0) {
       
   625           $mailHeader .= $this->AddrAppend("To", $this->to);
       
   626         } else {
       
   627           $mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;");
       
   628         }
       
   629         $mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject))));
       
   630         // if(count($this->cc) > 0) {
       
   631             // $mailHeader .= $this->AddrAppend("Cc", $this->cc);
       
   632         // }
       
   633       }
       
   634 
       
   635       // digitally sign with DKIM if enabled
       
   636       if ($this->DKIM_domain && $this->DKIM_private) {
       
   637         $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
       
   638         $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
       
   639       }
       
   640 
       
   641       $this->SentMIMEMessage = sprintf("%s%s\r\n\r\n%s",$this->MIMEHeader,$mailHeader,$this->MIMEBody);
       
   642       return true;
       
   643 
       
   644     } catch (phpmailerException $e) {
       
   645       $this->SetError($e->getMessage());
       
   646       if ($this->exceptions) {
       
   647         throw $e;
       
   648       }
   401       return false;
   649       return false;
   402     }
   650     }
   403 
   651   }
   404     /* Choose the mailer */
   652 
   405     switch($this->Mailer) {
   653   protected function PostSend() {
   406       case 'sendmail':
   654     try {
   407         $result = $this->SendmailSend($header, $body);
   655       // Choose the mailer and send through it
   408         break;
   656       switch($this->Mailer) {
   409       case 'smtp':
   657         case 'sendmail':
   410         $result = $this->SmtpSend($header, $body);
   658           return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
   411         break;
   659         case 'smtp':
   412       case 'mail':
   660           return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
   413         $result = $this->MailSend($header, $body);
   661         case 'mail':
   414         break;
   662           return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
   415       default:
   663         default:
   416         $result = $this->MailSend($header, $body);
   664           return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
   417         break;
   665       }
   418         //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));
   666 
   419         //$result = false;
   667     } catch (phpmailerException $e) {
   420         //break;
   668       $this->SetError($e->getMessage());
   421     }
   669       if ($this->exceptions) {
   422 
   670         throw $e;
   423     return $result;
   671       }
       
   672 	  if ($this->SMTPDebug) {
       
   673         echo $e->getMessage()."\n";
       
   674       }
       
   675       return false;
       
   676     }
   424   }
   677   }
   425 
   678 
   426   /**
   679   /**
   427    * Sends mail using the $Sendmail program.
   680    * Sends mail using the $Sendmail program.
   428    * @access private
   681    * @param string $header The message headers
       
   682    * @param string $body The message body
       
   683    * @access protected
   429    * @return bool
   684    * @return bool
   430    */
   685    */
   431   function SendmailSend($header, $body) {
   686   protected function SendmailSend($header, $body) {
   432     if ($this->Sender != '') {
   687     if ($this->Sender != '') {
   433       $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
   688       $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
   434     } else {
   689     } else {
   435       $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
   690       $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
   436     }
   691     }
   437 
   692     if ($this->SingleTo === true) {
   438     if(!@$mail = popen($sendmail, 'w')) {
   693       foreach ($this->SingleToArray as $key => $val) {
   439       $this->SetError($this->Lang('execute') . $this->Sendmail);
   694         if(!@$mail = popen($sendmail, 'w')) {
   440       return false;
   695           throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
   441     }
   696         }
   442 
   697         fputs($mail, "To: " . $val . "\n");
   443     fputs($mail, $header);
   698         fputs($mail, $header);
   444     fputs($mail, $body);
   699         fputs($mail, $body);
   445 
   700         $result = pclose($mail);
   446     $result = pclose($mail);
   701         // implement call back function if it exists
   447     if (version_compare(phpversion(), '4.2.3') == -1) {
   702         $isSent = ($result == 0) ? 1 : 0;
   448       $result = $result >> 8 & 0xFF;
   703         $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
   449     }
   704         if($result != 0) {
   450     if($result != 0) {
   705           throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
   451       $this->SetError($this->Lang('execute') . $this->Sendmail);
   706         }
   452       return false;
   707       }
       
   708     } else {
       
   709       if(!@$mail = popen($sendmail, 'w')) {
       
   710         throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
       
   711       }
       
   712       fputs($mail, $header);
       
   713       fputs($mail, $body);
       
   714       $result = pclose($mail);
       
   715       // implement call back function if it exists
       
   716       $isSent = ($result == 0) ? 1 : 0;
       
   717       $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
       
   718       if($result != 0) {
       
   719         throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
       
   720       }
   453     }
   721     }
   454     return true;
   722     return true;
   455   }
   723   }
   456 
   724 
   457   /**
   725   /**
   458    * Sends mail using the PHP mail() function.
   726    * Sends mail using the PHP mail() function.
   459    * @access private
   727    * @param string $header The message headers
       
   728    * @param string $body The message body
       
   729    * @access protected
   460    * @return bool
   730    * @return bool
   461    */
   731    */
   462   function MailSend($header, $body) {
   732   protected function MailSend($header, $body) {
   463 
   733     $toArr = array();
   464     $to = '';
   734     foreach($this->to as $t) {
   465     for($i = 0; $i < count($this->to); $i++) {
   735       $toArr[] = $this->AddrFormat($t);
   466       if($i != 0) { $to .= ', '; }
   736     }
   467       $to .= $this->AddrFormat($this->to[$i]);
   737     $to = implode(', ', $toArr);
   468     }
   738 
   469 
   739     if (empty($this->Sender)) {
   470     $toArr = split(',', $to);
   740       $params = "-oi ";
   471 
   741     } else {
   472     $params = sprintf("-oi -f %s", $this->Sender);
   742       $params = sprintf("-oi -f %s", $this->Sender);
   473     if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) {
   743     }
       
   744     if ($this->Sender != '' and !ini_get('safe_mode')) {
   474       $old_from = ini_get('sendmail_from');
   745       $old_from = ini_get('sendmail_from');
   475       ini_set('sendmail_from', $this->Sender);
   746       ini_set('sendmail_from', $this->Sender);
   476       if ($this->SingleTo === true && count($toArr) > 1) {
   747       if ($this->SingleTo === true && count($toArr) > 1) {
   477         foreach ($toArr as $key => $val) {
   748         foreach ($toArr as $key => $val) {
   478           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
   749           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
       
   750           // implement call back function if it exists
       
   751           $isSent = ($rt == 1) ? 1 : 0;
       
   752           $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
   479         }
   753         }
   480       } else {
   754       } else {
   481         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
   755         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
       
   756         // implement call back function if it exists
       
   757         $isSent = ($rt == 1) ? 1 : 0;
       
   758         $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
   482       }
   759       }
   483     } else {
   760     } else {
   484       if ($this->SingleTo === true && count($toArr) > 1) {
   761       if ($this->SingleTo === true && count($toArr) > 1) {
   485         foreach ($toArr as $key => $val) {
   762         foreach ($toArr as $key => $val) {
   486           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
   763           $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
       
   764           // implement call back function if it exists
       
   765           $isSent = ($rt == 1) ? 1 : 0;
       
   766           $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
   487         }
   767         }
   488       } else {
   768       } else {
   489         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
   769         $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
   490       }
   770         // implement call back function if it exists
   491     }
   771         $isSent = ($rt == 1) ? 1 : 0;
   492 
   772         $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
       
   773       }
       
   774     }
   493     if (isset($old_from)) {
   775     if (isset($old_from)) {
   494       ini_set('sendmail_from', $old_from);
   776       ini_set('sendmail_from', $old_from);
   495     }
   777     }
   496 
       
   497     if(!$rt) {
   778     if(!$rt) {
   498       $this->SetError($this->Lang('instantiate'));
   779       throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
   499       return false;
   780     }
   500     }
       
   501 
       
   502     return true;
   781     return true;
   503   }
   782   }
   504 
   783 
   505   /**
   784   /**
   506    * Sends mail via SMTP using PhpSMTP (Author:
   785    * Sends mail via SMTP using PhpSMTP
   507    * Chris Ryan).  Returns bool.  Returns false if there is a
   786    * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
   508    * bad MAIL FROM, RCPT, or DATA input.
   787    * @param string $header The message headers
   509    * @access private
   788    * @param string $body The message body
       
   789    * @uses SMTP
       
   790    * @access protected
   510    * @return bool
   791    * @return bool
   511    */
   792    */
   512   function SmtpSend($header, $body) {
   793   protected function SmtpSend($header, $body) {
   513     include_once($this->PluginDir . 'class-smtp.php');
   794     require_once $this->PluginDir . 'class-smtp.php';
   514     $error = '';
       
   515     $bad_rcpt = array();
   795     $bad_rcpt = array();
   516 
   796 
   517     if(!$this->SmtpConnect()) {
   797     if(!$this->SmtpConnect()) {
   518       return false;
   798       throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
   519     }
   799     }
   520 
       
   521     $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
   800     $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
   522     if(!$this->smtp->Mail($smtp_from)) {
   801     if(!$this->smtp->Mail($smtp_from)) {
   523       $error = $this->Lang('from_failed') . $smtp_from;
   802       throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
   524       $this->SetError($error);
   803     }
   525       $this->smtp->Reset();
   804 
   526       return false;
   805     // Attempt to send attach all recipients
   527     }
   806     foreach($this->to as $to) {
   528 
   807       if (!$this->smtp->Recipient($to[0])) {
   529     /* Attempt to send attach all recipients */
   808         $bad_rcpt[] = $to[0];
   530     for($i = 0; $i < count($this->to); $i++) {
   809         // implement call back function if it exists
   531       if(!$this->smtp->Recipient($this->to[$i][0])) {
   810         $isSent = 0;
   532         $bad_rcpt[] = $this->to[$i][0];
   811         $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
   533       }
   812       } else {
   534     }
   813         // implement call back function if it exists
   535     for($i = 0; $i < count($this->cc); $i++) {
   814         $isSent = 1;
   536       if(!$this->smtp->Recipient($this->cc[$i][0])) {
   815         $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
   537         $bad_rcpt[] = $this->cc[$i][0];
   816       }
   538       }
   817     }
   539     }
   818     foreach($this->cc as $cc) {
   540     for($i = 0; $i < count($this->bcc); $i++) {
   819       if (!$this->smtp->Recipient($cc[0])) {
   541       if(!$this->smtp->Recipient($this->bcc[$i][0])) {
   820         $bad_rcpt[] = $cc[0];
   542         $bad_rcpt[] = $this->bcc[$i][0];
   821         // implement call back function if it exists
   543       }
   822         $isSent = 0;
   544     }
   823         $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
   545 
   824       } else {
   546     if(count($bad_rcpt) > 0) { // Create error message
   825         // implement call back function if it exists
   547       for($i = 0; $i < count($bad_rcpt); $i++) {
   826         $isSent = 1;
   548         if($i != 0) {
   827         $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
   549           $error .= ', ';
   828       }
   550         }
   829     }
   551         $error .= $bad_rcpt[$i];
   830     foreach($this->bcc as $bcc) {
   552       }
   831       if (!$this->smtp->Recipient($bcc[0])) {
   553       $error = $this->Lang('recipients_failed') . $error;
   832         $bad_rcpt[] = $bcc[0];
   554       $this->SetError($error);
   833         // implement call back function if it exists
   555       $this->smtp->Reset();
   834         $isSent = 0;
   556       return false;
   835         $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
   557     }
   836       } else {
   558 
   837         // implement call back function if it exists
       
   838         $isSent = 1;
       
   839         $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
       
   840       }
       
   841     }
       
   842 
       
   843 
       
   844     if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
       
   845       $badaddresses = implode(', ', $bad_rcpt);
       
   846       throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
       
   847     }
   559     if(!$this->smtp->Data($header . $body)) {
   848     if(!$this->smtp->Data($header . $body)) {
   560       $this->SetError($this->Lang('data_not_accepted'));
   849       throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
   561       $this->smtp->Reset();
       
   562       return false;
       
   563     }
   850     }
   564     if($this->SMTPKeepAlive == true) {
   851     if($this->SMTPKeepAlive == true) {
   565       $this->smtp->Reset();
   852       $this->smtp->Reset();
   566     } else {
   853     }
   567       $this->SmtpClose();
       
   568     }
       
   569 
       
   570     return true;
   854     return true;
   571   }
   855   }
   572 
   856 
   573   /**
   857   /**
   574    * Initiates a connection to an SMTP server.  Returns false if the
   858    * Initiates a connection to an SMTP server.
   575    * operation failed.
   859    * Returns false if the operation failed.
   576    * @access private
   860    * @uses SMTP
       
   861    * @access public
   577    * @return bool
   862    * @return bool
   578    */
   863    */
   579   function SmtpConnect() {
   864   public function SmtpConnect() {
   580     if($this->smtp == NULL) {
   865     if(is_null($this->smtp)) {
   581       $this->smtp = new SMTP();
   866       $this->smtp = new SMTP();
   582     }
   867     }
   583 
   868 
   584     $this->smtp->do_debug = $this->SMTPDebug;
   869     $this->smtp->do_debug = $this->SMTPDebug;
   585     $hosts = explode(';', $this->Host);
   870     $hosts = explode(';', $this->Host);
   586     $index = 0;
   871     $index = 0;
   587     $connection = ($this->smtp->Connected());
   872     $connection = $this->smtp->Connected();
   588 
   873 
   589     /* Retry while there is no connection */
   874     // Retry while there is no connection
   590     while($index < count($hosts) && $connection == false) {
   875     try {
   591       $hostinfo = array();
   876       while($index < count($hosts) && !$connection) {
   592       if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) {
   877         $hostinfo = array();
   593         $host = $hostinfo[1];
   878         if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
   594         $port = $hostinfo[2];
   879           $host = $hostinfo[1];
   595       } else {
   880           $port = $hostinfo[2];
   596         $host = $hosts[$index];
       
   597         $port = $this->Port;
       
   598       }
       
   599 
       
   600       if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) {
       
   601         if ($this->Helo != '') {
       
   602           $this->smtp->Hello($this->Helo);
       
   603         } else {
   881         } else {
   604           $this->smtp->Hello($this->ServerHostname());
   882           $host = $hosts[$index];
       
   883           $port = $this->Port;
   605         }
   884         }
   606 
   885 
   607         $connection = true;
   886         $tls = ($this->SMTPSecure == 'tls');
   608         if($this->SMTPAuth) {
   887         $ssl = ($this->SMTPSecure == 'ssl');
   609           if(!$this->smtp->Authenticate($this->Username, $this->Password)) {
   888 
   610             $this->SetError($this->Lang('authenticate'));
   889         if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
   611             $this->smtp->Reset();
   890 
   612             $connection = false;
   891           $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
       
   892           $this->smtp->Hello($hello);
       
   893 
       
   894           if ($tls) {
       
   895             if (!$this->smtp->StartTLS()) {
       
   896               throw new phpmailerException($this->Lang('tls'));
       
   897             }
       
   898 
       
   899             //We must resend HELO after tls negotiation
       
   900             $this->smtp->Hello($hello);
       
   901           }
       
   902 
       
   903           $connection = true;
       
   904           if ($this->SMTPAuth) {
       
   905             if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
       
   906               throw new phpmailerException($this->Lang('authenticate'));
       
   907             }
   613           }
   908           }
   614         }
   909         }
   615       }
   910         $index++;
   616       $index++;
   911         if (!$connection) {
   617     }
   912           throw new phpmailerException($this->Lang('connect_host'));
   618     if(!$connection) {
   913         }
   619       $this->SetError($this->Lang('connect_host'));
   914       }
   620     }
   915     } catch (phpmailerException $e) {
   621 
   916       $this->smtp->Reset();
   622     return $connection;
   917 	  if ($this->exceptions) {
       
   918         throw $e;
       
   919       }
       
   920     }
       
   921     return true;
   623   }
   922   }
   624 
   923 
   625   /**
   924   /**
   626    * Closes the active SMTP session if one exists.
   925    * Closes the active SMTP session if one exists.
   627    * @return void
   926    * @return void
   628    */
   927    */
   629   function SmtpClose() {
   928   public function SmtpClose() {
   630     if($this->smtp != NULL) {
   929     if(!is_null($this->smtp)) {
   631       if($this->smtp->Connected()) {
   930       if($this->smtp->Connected()) {
   632         $this->smtp->Quit();
   931         $this->smtp->Quit();
   633         $this->smtp->Close();
   932         $this->smtp->Close();
   634       }
   933       }
   635     }
   934     }
   636   }
   935   }
   637 
   936 
   638   /**
   937   /**
   639    * Sets the language for all class error messages.  Returns false
   938   * Sets the language for all class error messages.
   640    * if it cannot load the language file.  The default language type
   939   * Returns false if it cannot load the language file.  The default language is English.
   641    * is English.
   940   * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
   642    * @param string $lang_type Type of language (e.g. Portuguese: "br")
   941   * @param string $lang_path Path to the language file directory
   643    * @param string $lang_path Path to the language file directory
   942   * @access public
   644    * @access public
   943   */
   645    * @return bool
   944   function SetLanguage($langcode = 'en', $lang_path = 'language/') {
   646    */
   945     //Define full set of translatable strings
   647   function SetLanguage($lang_type, $lang_path = 'language/') {
   946     $PHPMAILER_LANG = array(
   648     if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) {
   947       'provide_address' => 'You must provide at least one recipient email address.',
   649       include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
   948       'mailer_not_supported' => ' mailer is not supported.',
   650     } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) {
   949       'execute' => 'Could not execute: ',
   651       include($lang_path.'phpmailer.lang-en.php');
   950       'instantiate' => 'Could not instantiate mail function.',
   652     } else {
   951       'authenticate' => 'SMTP Error: Could not authenticate.',
   653       $PHPMAILER_LANG = array();
   952       'from_failed' => 'The following From address failed: ',
   654       $PHPMAILER_LANG["provide_address"]      = 'You must provide at least one ' .
   953       'recipients_failed' => 'SMTP Error: The following recipients failed: ',
   655       $PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.';
   954       'data_not_accepted' => 'SMTP Error: Data not accepted.',
   656       $PHPMAILER_LANG["execute"]              = 'Could not execute: ';
   955       'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
   657       $PHPMAILER_LANG["instantiate"]          = 'Could not instantiate mail function.';
   956       'file_access' => 'Could not access file: ',
   658       $PHPMAILER_LANG["authenticate"]         = 'SMTP Error: Could not authenticate.';
   957       'file_open' => 'File Error: Could not open file: ',
   659       $PHPMAILER_LANG["from_failed"]          = 'The following From address failed: ';
   958       'encoding' => 'Unknown encoding: ',
   660       $PHPMAILER_LANG["recipients_failed"]    = 'SMTP Error: The following ' .
   959       'signing' => 'Signing Error: ',
   661       $PHPMAILER_LANG["data_not_accepted"]    = 'SMTP Error: Data not accepted.';
   960       'smtp_error' => 'SMTP server error: ',
   662       $PHPMAILER_LANG["connect_host"]         = 'SMTP Error: Could not connect to SMTP host.';
   961       'empty_message' => 'Message body empty',
   663       $PHPMAILER_LANG["file_access"]          = 'Could not access file: ';
   962       'invalid_address' => 'Invalid address',
   664       $PHPMAILER_LANG["file_open"]            = 'File Error: Could not open file: ';
   963       'variable_set' => 'Cannot set or reset variable: '
   665       $PHPMAILER_LANG["encoding"]             = 'Unknown encoding: ';
   964     );
   666       $PHPMAILER_LANG["signing"]              = 'Signing Error: ';
   965     //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
       
   966     $l = true;
       
   967     if ($langcode != 'en') { //There is no English translation file
       
   968       $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
   667     }
   969     }
   668     $this->language = $PHPMAILER_LANG;
   970     $this->language = $PHPMAILER_LANG;
   669 
   971     return ($l == true); //Returns false if language not found
   670     return true;
   972   }
       
   973 
       
   974   /**
       
   975   * Return the current array of language strings
       
   976   * @return array
       
   977   */
       
   978   public function GetTranslations() {
       
   979     return $this->language;
   671   }
   980   }
   672 
   981 
   673   /////////////////////////////////////////////////
   982   /////////////////////////////////////////////////
   674   // METHODS, MESSAGE CREATION
   983   // METHODS, MESSAGE CREATION
   675   /////////////////////////////////////////////////
   984   /////////////////////////////////////////////////
   676 
   985 
   677   /**
   986   /**
   678    * Creates recipient headers.
   987    * Creates recipient headers.
   679    * @access private
   988    * @access public
   680    * @return string
   989    * @return string
   681    */
   990    */
   682   function AddrAppend($type, $addr) {
   991   public function AddrAppend($type, $addr) {
   683     $addr_str = $type . ': ';
   992     $addr_str = $type . ': ';
   684     $addr_str .= $this->AddrFormat($addr[0]);
   993     $addresses = array();
   685     if(count($addr) > 1) {
   994     foreach ($addr as $a) {
   686       for($i = 1; $i < count($addr); $i++) {
   995       $addresses[] = $this->AddrFormat($a);
   687         $addr_str .= ', ' . $this->AddrFormat($addr[$i]);
   996     }
   688       }
   997     $addr_str .= implode(', ', $addresses);
   689     }
       
   690     $addr_str .= $this->LE;
   998     $addr_str .= $this->LE;
   691 
   999 
   692     return $addr_str;
  1000     return $addr_str;
   693   }
  1001   }
   694 
  1002 
   695   /**
  1003   /**
   696    * Formats an address correctly.
  1004    * Formats an address correctly.
   697    * @access private
  1005    * @access public
   698    * @return string
  1006    * @return string
   699    */
  1007    */
   700   function AddrFormat($addr) {
  1008   public function AddrFormat($addr) {
   701     if(empty($addr[1])) {
  1009     if (empty($addr[1])) {
   702       $formatted = $this->SecureHeader($addr[0]);
  1010       return $this->SecureHeader($addr[0]);
   703     } else {
  1011     } else {
   704       $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
  1012       return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
   705     }
  1013     }
   706 
       
   707     return $formatted;
       
   708   }
  1014   }
   709 
  1015 
   710   /**
  1016   /**
   711    * Wraps message for use with mailers that do not
  1017    * Wraps message for use with mailers that do not
   712    * automatically perform wrapping and for quoted-printable.
  1018    * automatically perform wrapping and for quoted-printable.
   713    * Original written by philippe.
  1019    * Original written by philippe.
   714    * @access private
  1020    * @param string $message The message to wrap
       
  1021    * @param integer $length The line length to wrap to
       
  1022    * @param boolean $qp_mode Whether to run in Quoted-Printable mode
       
  1023    * @access public
   715    * @return string
  1024    * @return string
   716    */
  1025    */
   717   function WrapText($message, $length, $qp_mode = false) {
  1026   public function WrapText($message, $length, $qp_mode = false) {
   718     $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
  1027     $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
   719     // If utf-8 encoding is used, we will need to make sure we don't
  1028     // If utf-8 encoding is used, we will need to make sure we don't
   720     // split multibyte characters when we wrap
  1029     // split multibyte characters when we wrap
   721     $is_utf8 = (strtolower($this->CharSet) == "utf-8");
  1030     $is_utf8 = (strtolower($this->CharSet) == "utf-8");
   722 
  1031 
   725       $message = substr($message, 0, -1);
  1034       $message = substr($message, 0, -1);
   726     }
  1035     }
   727 
  1036 
   728     $line = explode($this->LE, $message);
  1037     $line = explode($this->LE, $message);
   729     $message = '';
  1038     $message = '';
   730     for ($i=0 ;$i < count($line); $i++) {
  1039     for ($i = 0 ;$i < count($line); $i++) {
   731       $line_part = explode(' ', $line[$i]);
  1040       $line_part = explode(' ', $line[$i]);
   732       $buf = '';
  1041       $buf = '';
   733       for ($e = 0; $e<count($line_part); $e++) {
  1042       for ($e = 0; $e<count($line_part); $e++) {
   734         $word = $line_part[$e];
  1043         $word = $line_part[$e];
   735         if ($qp_mode and (strlen($word) > $length)) {
  1044         if ($qp_mode and (strlen($word) > $length)) {
   789 
  1098 
   790   /**
  1099   /**
   791    * Finds last character boundary prior to maxLength in a utf-8
  1100    * Finds last character boundary prior to maxLength in a utf-8
   792    * quoted (printable) encoded string.
  1101    * quoted (printable) encoded string.
   793    * Original written by Colin Brown.
  1102    * Original written by Colin Brown.
   794    * @access private
  1103    * @access public
   795    * @param string $encodedText utf-8 QP text
  1104    * @param string $encodedText utf-8 QP text
   796    * @param int    $maxLength   find last character boundary prior to this length
  1105    * @param int    $maxLength   find last character boundary prior to this length
   797    * @return int
  1106    * @return int
   798    */
  1107    */
   799   function UTF8CharBoundary($encodedText, $maxLength) {
  1108   public function UTF8CharBoundary($encodedText, $maxLength) {
   800     $foundSplitPos = false;
  1109     $foundSplitPos = false;
   801     $lookBack = 3;
  1110     $lookBack = 3;
   802     while (!$foundSplitPos) {
  1111     while (!$foundSplitPos) {
   803       $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
  1112       $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
   804       $encodedCharPos = strpos($lastChunk, "=");
  1113       $encodedCharPos = strpos($lastChunk, "=");
   826       }
  1135       }
   827     }
  1136     }
   828     return $maxLength;
  1137     return $maxLength;
   829   }
  1138   }
   830 
  1139 
       
  1140 
   831   /**
  1141   /**
   832    * Set the body wrapping.
  1142    * Set the body wrapping.
   833    * @access private
  1143    * @access public
   834    * @return void
  1144    * @return void
   835    */
  1145    */
   836   function SetWordWrap() {
  1146   public function SetWordWrap() {
   837     if($this->WordWrap < 1) {
  1147     if($this->WordWrap < 1) {
   838       return;
  1148       return;
   839     }
  1149     }
   840 
  1150 
   841     switch($this->message_type) {
  1151     switch($this->message_type) {
   842       case 'alt':
  1152       case 'alt':
   843         /* fall through */
  1153       case 'alt_inline':
   844       case 'alt_attachments':
  1154       case 'alt_attach':
       
  1155       case 'alt_inline_attach':
   845         $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
  1156         $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
   846         break;
  1157         break;
   847       default:
  1158       default:
   848         $this->Body = $this->WrapText($this->Body, $this->WordWrap);
  1159         $this->Body = $this->WrapText($this->Body, $this->WordWrap);
   849         break;
  1160         break;
   850     }
  1161     }
   851   }
  1162   }
   852 
  1163 
   853   /**
  1164   /**
   854    * Assembles message header.
  1165    * Assembles message header.
   855    * @access private
  1166    * @access public
   856    * @return string
  1167    * @return string The assembled header
   857    */
  1168    */
   858   function CreateHeader() {
  1169   public function CreateHeader() {
   859     $result = '';
  1170     $result = '';
   860 
  1171 
   861     /* Set the boundaries */
  1172     // Set the boundaries
   862     $uniq_id = md5(uniqid(time()));
  1173     $uniq_id = md5(uniqid(time()));
   863     $this->boundary[1] = 'b1_' . $uniq_id;
  1174     $this->boundary[1] = 'b1_' . $uniq_id;
   864     $this->boundary[2] = 'b2_' . $uniq_id;
  1175     $this->boundary[2] = 'b2_' . $uniq_id;
   865 
  1176     $this->boundary[3] = 'b3_' . $uniq_id;
   866     $result .= $this->HeaderLine('Date', $this->RFCDate());
  1177 
       
  1178     $result .= $this->HeaderLine('Date', self::RFCDate());
   867     if($this->Sender == '') {
  1179     if($this->Sender == '') {
   868       $result .= $this->HeaderLine('Return-Path', trim($this->From));
  1180       $result .= $this->HeaderLine('Return-Path', trim($this->From));
   869     } else {
  1181     } else {
   870       $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
  1182       $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
   871     }
  1183     }
   872 
  1184 
   873     /* To be created automatically by mail() */
  1185     // To be created automatically by mail()
   874     if($this->Mailer != 'mail') {
  1186     if($this->Mailer != 'mail') {
   875       if(count($this->to) > 0) {
  1187       if ($this->SingleTo === true) {
   876         $result .= $this->AddrAppend('To', $this->to);
  1188         foreach($this->to as $t) {
   877       } elseif (count($this->cc) == 0) {
  1189           $this->SingleToArray[] = $this->AddrFormat($t);
   878         $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
  1190         }
   879       }
  1191       } else {
   880     }
  1192         if(count($this->to) > 0) {
       
  1193           $result .= $this->AddrAppend('To', $this->to);
       
  1194         } elseif (count($this->cc) == 0) {
       
  1195           $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
       
  1196         }
       
  1197       }
       
  1198 	}
   881 
  1199 
   882     $from = array();
  1200     $from = array();
   883     $from[0][0] = trim($this->From);
  1201     $from[0][0] = trim($this->From);
   884     $from[0][1] = $this->FromName;
  1202     $from[0][1] = $this->FromName;
   885     $result .= $this->AddrAppend('From', $from);
  1203     $result .= $this->AddrAppend('From', $from);
   886 
  1204 
   887     /* sendmail and mail() extract Cc from the header before sending */
  1205     // sendmail and mail() extract Cc from the header before sending
   888     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
  1206     if(count($this->cc) > 0) {
   889       $result .= $this->AddrAppend('Cc', $this->cc);
  1207       $result .= $this->AddrAppend('Cc', $this->cc);
   890     }
  1208     }
   891 
  1209 
   892     /* sendmail and mail() extract Bcc from the header before sending */
  1210     // sendmail and mail() extract Bcc from the header before sending
   893     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
  1211     if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
   894       $result .= $this->AddrAppend('Bcc', $this->bcc);
  1212       $result .= $this->AddrAppend('Bcc', $this->bcc);
   895     }
  1213     }
   896 
  1214 
   897     if(count($this->ReplyTo) > 0) {
  1215     if(count($this->ReplyTo) > 0) {
   898       $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
  1216       $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
   899     }
  1217     }
   900 
  1218 
   901     /* mail() sets the subject itself */
  1219     // mail() sets the subject itself
   902     if($this->Mailer != 'mail') {
  1220     if($this->Mailer != 'mail') {
   903       $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
  1221       $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
   904     }
  1222     }
   905 
  1223 
   906     if($this->MessageID != '') {
  1224     if($this->MessageID != '') {
   907       $result .= $this->HeaderLine('Message-ID',$this->MessageID);
  1225       $result .= $this->HeaderLine('Message-ID', $this->MessageID);
   908     } else {
  1226     } else {
   909       $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
  1227       $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
   910     }
  1228     }
   911     $result .= $this->HeaderLine('X-Priority', $this->Priority);
  1229     $result .= $this->HeaderLine('X-Priority', $this->Priority);
   912     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']');
  1230     if($this->XMailer) {
       
  1231       $result .= $this->HeaderLine('X-Mailer', $this->XMailer);
       
  1232     } else {
       
  1233       $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)');
       
  1234     }
   913 
  1235 
   914     if($this->ConfirmReadingTo != '') {
  1236     if($this->ConfirmReadingTo != '') {
   915       $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
  1237       $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
   916     }
  1238     }
   917 
  1239 
   927     return $result;
  1249     return $result;
   928   }
  1250   }
   929 
  1251 
   930   /**
  1252   /**
   931    * Returns the message MIME.
  1253    * Returns the message MIME.
   932    * @access private
  1254    * @access public
   933    * @return string
  1255    * @return string
   934    */
  1256    */
   935   function GetMailMIME() {
  1257   public function GetMailMIME() {
   936     $result = '';
  1258     $result = '';
   937     switch($this->message_type) {
  1259     switch($this->message_type) {
   938       case 'plain':
  1260       case 'plain':
   939         $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
  1261         $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
   940         $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
  1262         $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset="'.$this->CharSet.'"');
   941         break;
  1263         break;
   942       case 'attachments':
  1264       case 'inline':
   943         /* fall through */
  1265         $result .= $this->HeaderLine('Content-Type', 'multipart/related;');
   944       case 'alt_attachments':
  1266         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
   945         if($this->InlineImageExists()){
  1267         break;
   946           $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
  1268       case 'attach':
   947         } else {
  1269       case 'inline_attach':
   948           $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
  1270       case 'alt_attach':
   949           $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
  1271       case 'alt_inline_attach':
   950         }
  1272         $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
       
  1273         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
   951         break;
  1274         break;
   952       case 'alt':
  1275       case 'alt':
       
  1276       case 'alt_inline':
   953         $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
  1277         $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
   954         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
  1278         $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
   955         break;
  1279         break;
   956     }
  1280     }
   957 
  1281 
   961 
  1285 
   962     return $result;
  1286     return $result;
   963   }
  1287   }
   964 
  1288 
   965   /**
  1289   /**
       
  1290    * Returns the MIME message (headers and body). Only really valid post PreSend().
       
  1291    * @access public
       
  1292    * @return string
       
  1293    */
       
  1294   public function GetSentMIMEMessage() {
       
  1295     return $this->SentMIMEMessage;
       
  1296   }
       
  1297 
       
  1298 
       
  1299   /**
   966    * Assembles the message body.  Returns an empty string on failure.
  1300    * Assembles the message body.  Returns an empty string on failure.
   967    * @access private
  1301    * @access public
       
  1302    * @return string The assembled message body
       
  1303    */
       
  1304   public function CreateBody() {
       
  1305     $body = '';
       
  1306 
       
  1307     if ($this->sign_key_file) {
       
  1308       $body .= $this->GetMailMIME();
       
  1309     }
       
  1310 
       
  1311     $this->SetWordWrap();
       
  1312 
       
  1313     switch($this->message_type) {
       
  1314       case 'plain':
       
  1315         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1316         break;
       
  1317       case 'inline':
       
  1318         $body .= $this->GetBoundary($this->boundary[1], '', '', '');
       
  1319         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1320         $body .= $this->LE.$this->LE;
       
  1321         $body .= $this->AttachAll("inline", $this->boundary[1]);
       
  1322         break;
       
  1323       case 'attach':
       
  1324         $body .= $this->GetBoundary($this->boundary[1], '', '', '');
       
  1325         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1326         $body .= $this->LE.$this->LE;
       
  1327         $body .= $this->AttachAll("attachment", $this->boundary[1]);
       
  1328         break;
       
  1329       case 'inline_attach':
       
  1330         $body .= $this->TextLine("--" . $this->boundary[1]);
       
  1331         $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
       
  1332         $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
       
  1333         $body .= $this->LE;
       
  1334         $body .= $this->GetBoundary($this->boundary[2], '', '', '');
       
  1335         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1336         $body .= $this->LE.$this->LE;
       
  1337         $body .= $this->AttachAll("inline", $this->boundary[2]);
       
  1338         $body .= $this->LE;
       
  1339         $body .= $this->AttachAll("attachment", $this->boundary[1]);
       
  1340         break;
       
  1341       case 'alt':
       
  1342         $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
       
  1343         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
       
  1344         $body .= $this->LE.$this->LE;
       
  1345         $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
       
  1346         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1347         $body .= $this->LE.$this->LE;
       
  1348         $body .= $this->EndBoundary($this->boundary[1]);
       
  1349         break;
       
  1350       case 'alt_inline':
       
  1351         $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
       
  1352         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
       
  1353         $body .= $this->LE.$this->LE;
       
  1354         $body .= $this->TextLine("--" . $this->boundary[1]);
       
  1355         $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
       
  1356         $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
       
  1357         $body .= $this->LE;
       
  1358         $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
       
  1359         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1360         $body .= $this->LE.$this->LE;
       
  1361         $body .= $this->AttachAll("inline", $this->boundary[2]);
       
  1362         $body .= $this->LE;
       
  1363         $body .= $this->EndBoundary($this->boundary[1]);
       
  1364         break;
       
  1365       case 'alt_attach':
       
  1366         $body .= $this->TextLine("--" . $this->boundary[1]);
       
  1367         $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
       
  1368         $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
       
  1369         $body .= $this->LE;
       
  1370         $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
       
  1371         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
       
  1372         $body .= $this->LE.$this->LE;
       
  1373         $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
       
  1374         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1375         $body .= $this->LE.$this->LE;
       
  1376         $body .= $this->EndBoundary($this->boundary[2]);
       
  1377         $body .= $this->LE;
       
  1378         $body .= $this->AttachAll("attachment", $this->boundary[1]);
       
  1379         break;
       
  1380       case 'alt_inline_attach':
       
  1381         $body .= $this->TextLine("--" . $this->boundary[1]);
       
  1382         $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
       
  1383         $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
       
  1384         $body .= $this->LE;
       
  1385         $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
       
  1386         $body .= $this->EncodeString($this->AltBody, $this->Encoding);
       
  1387         $body .= $this->LE.$this->LE;
       
  1388         $body .= $this->TextLine("--" . $this->boundary[2]);
       
  1389         $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
       
  1390         $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"');
       
  1391         $body .= $this->LE;
       
  1392         $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
       
  1393         $body .= $this->EncodeString($this->Body, $this->Encoding);
       
  1394         $body .= $this->LE.$this->LE;
       
  1395         $body .= $this->AttachAll("inline", $this->boundary[3]);
       
  1396         $body .= $this->LE;
       
  1397         $body .= $this->EndBoundary($this->boundary[2]);
       
  1398         $body .= $this->LE;
       
  1399         $body .= $this->AttachAll("attachment", $this->boundary[1]);
       
  1400         break;
       
  1401     }
       
  1402 
       
  1403     if ($this->IsError()) {
       
  1404       $body = '';
       
  1405     } elseif ($this->sign_key_file) {
       
  1406       try {
       
  1407         $file = tempnam('', 'mail');
       
  1408         file_put_contents($file, $body); //TODO check this worked
       
  1409         $signed = tempnam("", "signed");
       
  1410         if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
       
  1411           @unlink($file);
       
  1412           $body = file_get_contents($signed);
       
  1413           @unlink($signed);
       
  1414         } else {
       
  1415           @unlink($file);
       
  1416           @unlink($signed);
       
  1417           throw new phpmailerException($this->Lang("signing").openssl_error_string());
       
  1418         }
       
  1419       } catch (phpmailerException $e) {
       
  1420         $body = '';
       
  1421         if ($this->exceptions) {
       
  1422           throw $e;
       
  1423         }
       
  1424       }
       
  1425     }
       
  1426 
       
  1427     return $body;
       
  1428   }
       
  1429 
       
  1430   /**
       
  1431    * Returns the start of a message boundary.
       
  1432    * @access protected
   968    * @return string
  1433    * @return string
   969    */
  1434    */
   970   function CreateBody() {
  1435   protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
   971     $result = '';
       
   972     if ($this->sign_key_file) {
       
   973       $result .= $this->GetMailMIME();
       
   974     }
       
   975 
       
   976     $this->SetWordWrap();
       
   977 
       
   978     switch($this->message_type) {
       
   979       case 'alt':
       
   980         $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
       
   981         $result .= $this->EncodeString($this->AltBody, $this->Encoding);
       
   982         $result .= $this->LE.$this->LE;
       
   983         $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
       
   984         $result .= $this->EncodeString($this->Body, $this->Encoding);
       
   985         $result .= $this->LE.$this->LE;
       
   986         $result .= $this->EndBoundary($this->boundary[1]);
       
   987         break;
       
   988       case 'plain':
       
   989         $result .= $this->EncodeString($this->Body, $this->Encoding);
       
   990         break;
       
   991       case 'attachments':
       
   992         $result .= $this->GetBoundary($this->boundary[1], '', '', '');
       
   993         $result .= $this->EncodeString($this->Body, $this->Encoding);
       
   994         $result .= $this->LE;
       
   995         $result .= $this->AttachAll();
       
   996         break;
       
   997       case 'alt_attachments':
       
   998         $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
       
   999         $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
       
  1000         $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
       
  1001         $result .= $this->EncodeString($this->AltBody, $this->Encoding);
       
  1002         $result .= $this->LE.$this->LE;
       
  1003         $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
       
  1004         $result .= $this->EncodeString($this->Body, $this->Encoding);
       
  1005         $result .= $this->LE.$this->LE;
       
  1006         $result .= $this->EndBoundary($this->boundary[2]);
       
  1007         $result .= $this->AttachAll();
       
  1008         break;
       
  1009     }
       
  1010 
       
  1011     if($this->IsError()) {
       
  1012       $result = '';
       
  1013     } else if ($this->sign_key_file) {
       
  1014       $file = tempnam("", "mail");
       
  1015       $fp = fopen($file, "w");
       
  1016       fwrite($fp, $result);
       
  1017       fclose($fp);
       
  1018       $signed = tempnam("", "signed");
       
  1019 
       
  1020       if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) {
       
  1021         $fp = fopen($signed, "r");
       
  1022         $result = fread($fp, filesize($this->sign_key_file));
       
  1023         $result = '';
       
  1024         while(!feof($fp)){
       
  1025           $result = $result . fread($fp, 1024);
       
  1026         }
       
  1027         fclose($fp);
       
  1028       } else {
       
  1029         $this->SetError($this->Lang("signing").openssl_error_string());
       
  1030         $result = '';
       
  1031       }
       
  1032 
       
  1033       unlink($file);
       
  1034       unlink($signed);
       
  1035     }
       
  1036 
       
  1037     return $result;
       
  1038   }
       
  1039 
       
  1040   /**
       
  1041    * Returns the start of a message boundary.
       
  1042    * @access private
       
  1043    */
       
  1044   function GetBoundary($boundary, $charSet, $contentType, $encoding) {
       
  1045     $result = '';
  1436     $result = '';
  1046     if($charSet == '') {
  1437     if($charSet == '') {
  1047       $charSet = $this->CharSet;
  1438       $charSet = $this->CharSet;
  1048     }
  1439     }
  1049     if($contentType == '') {
  1440     if($contentType == '') {
  1051     }
  1442     }
  1052     if($encoding == '') {
  1443     if($encoding == '') {
  1053       $encoding = $this->Encoding;
  1444       $encoding = $this->Encoding;
  1054     }
  1445     }
  1055     $result .= $this->TextLine('--' . $boundary);
  1446     $result .= $this->TextLine('--' . $boundary);
  1056     $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
  1447     $result .= sprintf("Content-Type: %s; charset=\"%s\"", $contentType, $charSet);
  1057     $result .= $this->LE;
  1448     $result .= $this->LE;
  1058     $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
  1449     $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
  1059     $result .= $this->LE;
  1450     $result .= $this->LE;
  1060 
  1451 
  1061     return $result;
  1452     return $result;
  1062   }
  1453   }
  1063 
  1454 
  1064   /**
  1455   /**
  1065    * Returns the end of a message boundary.
  1456    * Returns the end of a message boundary.
  1066    * @access private
  1457    * @access protected
  1067    */
  1458    * @return string
  1068   function EndBoundary($boundary) {
  1459    */
       
  1460   protected function EndBoundary($boundary) {
  1069     return $this->LE . '--' . $boundary . '--' . $this->LE;
  1461     return $this->LE . '--' . $boundary . '--' . $this->LE;
  1070   }
  1462   }
  1071 
  1463 
  1072   /**
  1464   /**
  1073    * Sets the message type.
  1465    * Sets the message type.
  1074    * @access private
  1466    * @access protected
  1075    * @return void
  1467    * @return void
  1076    */
  1468    */
  1077   function SetMessageType() {
  1469   protected function SetMessageType() {
  1078     if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
  1470     $this->message_type = array();
  1079       $this->message_type = 'plain';
  1471     if($this->AlternativeExists()) $this->message_type[] = "alt";
  1080     } else {
  1472     if($this->InlineImageExists()) $this->message_type[] = "inline";
  1081       if(count($this->attachment) > 0) {
  1473     if($this->AttachmentExists()) $this->message_type[] = "attach";
  1082         $this->message_type = 'attachments';
  1474     $this->message_type = implode("_", $this->message_type);
  1083       }
  1475     if($this->message_type == "") $this->message_type = "plain";
  1084       if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
  1476   }
  1085         $this->message_type = 'alt';
  1477 
  1086       }
  1478   /**
  1087       if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
  1479    *  Returns a formatted header line.
  1088         $this->message_type = 'alt_attachments';
  1480    * @access public
  1089       }
       
  1090     }
       
  1091   }
       
  1092 
       
  1093   /* Returns a formatted header line.
       
  1094    * @access private
       
  1095    * @return string
  1481    * @return string
  1096    */
  1482    */
  1097   function HeaderLine($name, $value) {
  1483   public function HeaderLine($name, $value) {
  1098     return $name . ': ' . $value . $this->LE;
  1484     return $name . ': ' . $value . $this->LE;
  1099   }
  1485   }
  1100 
  1486 
  1101   /**
  1487   /**
  1102    * Returns a formatted mail line.
  1488    * Returns a formatted mail line.
  1103    * @access private
  1489    * @access public
  1104    * @return string
  1490    * @return string
  1105    */
  1491    */
  1106   function TextLine($value) {
  1492   public function TextLine($value) {
  1107     return $value . $this->LE;
  1493     return $value . $this->LE;
  1108   }
  1494   }
  1109 
  1495 
  1110   /////////////////////////////////////////////////
  1496   /////////////////////////////////////////////////
  1111   // CLASS METHODS, ATTACHMENTS
  1497   // CLASS METHODS, ATTACHMENTS
  1119    * @param string $name Overrides the attachment name.
  1505    * @param string $name Overrides the attachment name.
  1120    * @param string $encoding File encoding (see $Encoding).
  1506    * @param string $encoding File encoding (see $Encoding).
  1121    * @param string $type File extension (MIME) type.
  1507    * @param string $type File extension (MIME) type.
  1122    * @return bool
  1508    * @return bool
  1123    */
  1509    */
  1124   function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
  1510   public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
  1125     if(!@is_file($path)) {
  1511     try {
  1126       $this->SetError($this->Lang('file_access') . $path);
  1512       if ( !@is_file($path) ) {
  1127       return false;
  1513         throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
  1128     }
  1514       }
  1129 
  1515       $filename = basename($path);
  1130     $filename = basename($path);
  1516       if ( $name == '' ) {
  1131     if($name == '') {
  1517         $name = $filename;
  1132       $name = $filename;
  1518       }
  1133     }
  1519 
  1134 
  1520       $this->attachment[] = array(
  1135     $cur = count($this->attachment);
  1521         0 => $path,
  1136     $this->attachment[$cur][0] = $path;
  1522         1 => $filename,
  1137     $this->attachment[$cur][1] = $filename;
  1523         2 => $name,
  1138     $this->attachment[$cur][2] = $name;
  1524         3 => $encoding,
  1139     $this->attachment[$cur][3] = $encoding;
  1525         4 => $type,
  1140     $this->attachment[$cur][4] = $type;
  1526         5 => false,  // isStringAttachment
  1141     $this->attachment[$cur][5] = false; // isStringAttachment
  1527         6 => 'attachment',
  1142     $this->attachment[$cur][6] = 'attachment';
  1528         7 => 0
  1143     $this->attachment[$cur][7] = 0;
  1529       );
  1144 
  1530 
       
  1531     } catch (phpmailerException $e) {
       
  1532       $this->SetError($e->getMessage());
       
  1533       if ($this->exceptions) {
       
  1534         throw $e;
       
  1535       }
       
  1536 	  if ($this->SMTPDebug) {
       
  1537         echo $e->getMessage()."\n";
       
  1538       }
       
  1539       if ( $e->getCode() == self::STOP_CRITICAL ) {
       
  1540         return false;
       
  1541       }
       
  1542     }
  1145     return true;
  1543     return true;
       
  1544   }
       
  1545 
       
  1546   /**
       
  1547   * Return the current array of attachments
       
  1548   * @return array
       
  1549   */
       
  1550   public function GetAttachments() {
       
  1551     return $this->attachment;
  1146   }
  1552   }
  1147 
  1553 
  1148   /**
  1554   /**
  1149    * Attaches all fs, string, and binary attachments to the message.
  1555    * Attaches all fs, string, and binary attachments to the message.
  1150    * Returns an empty string on failure.
  1556    * Returns an empty string on failure.
  1151    * @access private
  1557    * @access protected
  1152    * @return string
  1558    * @return string
  1153    */
  1559    */
  1154   function AttachAll() {
  1560   protected function AttachAll($disposition_type, $boundary) {
  1155     /* Return text of body */
  1561     // Return text of body
  1156     $mime = array();
  1562     $mime = array();
  1157 
  1563     $cidUniq = array();
  1158     /* Add all attachments */
  1564     $incl = array();
  1159     for($i = 0; $i < count($this->attachment); $i++) {
  1565 
  1160       /* Check for string attachment */
  1566     // Add all attachments
  1161       $bString = $this->attachment[$i][5];
  1567     foreach ($this->attachment as $attachment) {
  1162       if ($bString) {
  1568       // CHECK IF IT IS A VALID DISPOSITION_FILTER
  1163         $string = $this->attachment[$i][0];
  1569       if($attachment[6] == $disposition_type) {
  1164       } else {
  1570         // Check for string attachment
  1165         $path = $this->attachment[$i][0];
  1571         $bString = $attachment[5];
  1166       }
  1572         if ($bString) {
  1167 
  1573           $string = $attachment[0];
  1168       $filename    = $this->attachment[$i][1];
  1574         } else {
  1169       $name        = $this->attachment[$i][2];
  1575           $path = $attachment[0];
  1170       $encoding    = $this->attachment[$i][3];
       
  1171       $type        = $this->attachment[$i][4];
       
  1172       $disposition = $this->attachment[$i][6];
       
  1173       $cid         = $this->attachment[$i][7];
       
  1174 
       
  1175       $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
       
  1176       $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
       
  1177       $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
       
  1178 
       
  1179       if($disposition == 'inline') {
       
  1180         $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
       
  1181       }
       
  1182 
       
  1183       $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
       
  1184 
       
  1185       /* Encode as string attachment */
       
  1186       if($bString) {
       
  1187         $mime[] = $this->EncodeString($string, $encoding);
       
  1188         if($this->IsError()) {
       
  1189           return '';
       
  1190         }
  1576         }
  1191         $mime[] = $this->LE.$this->LE;
  1577 
  1192       } else {
  1578         $inclhash = md5(serialize($attachment));
  1193         $mime[] = $this->EncodeFile($path, $encoding);
  1579         if (in_array($inclhash, $incl)) { continue; }
  1194         if($this->IsError()) {
  1580         $incl[]      = $inclhash;
  1195           return '';
  1581         $filename    = $attachment[1];
       
  1582         $name        = $attachment[2];
       
  1583         $encoding    = $attachment[3];
       
  1584         $type        = $attachment[4];
       
  1585         $disposition = $attachment[6];
       
  1586         $cid         = $attachment[7];
       
  1587         if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
       
  1588         $cidUniq[$cid] = true;
       
  1589 
       
  1590         $mime[] = sprintf("--%s%s", $boundary, $this->LE);
       
  1591         $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
       
  1592         $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
       
  1593 
       
  1594         if($disposition == 'inline') {
       
  1595           $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
  1196         }
  1596         }
  1197         $mime[] = $this->LE.$this->LE;
  1597 
  1198       }
  1598         $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
  1199     }
  1599 
  1200 
  1600         // Encode as string attachment
  1201     $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
  1601         if($bString) {
  1202 
  1602           $mime[] = $this->EncodeString($string, $encoding);
  1203     return join('', $mime);
  1603           if($this->IsError()) {
  1204   }
  1604             return '';
  1205 
  1605           }
  1206   /**
  1606           $mime[] = $this->LE.$this->LE;
  1207    * Encodes attachment in requested format.  Returns an
  1607         } else {
  1208    * empty string on failure.
  1608           $mime[] = $this->EncodeFile($path, $encoding);
  1209    * @access private
  1609           if($this->IsError()) {
       
  1610             return '';
       
  1611           }
       
  1612           $mime[] = $this->LE.$this->LE;
       
  1613         }
       
  1614       }
       
  1615     }
       
  1616 
       
  1617     $mime[] = sprintf("--%s--%s", $boundary, $this->LE);
       
  1618 
       
  1619     return implode("", $mime);
       
  1620   }
       
  1621 
       
  1622   /**
       
  1623    * Encodes attachment in requested format.
       
  1624    * Returns an empty string on failure.
       
  1625    * @param string $path The full path to the file
       
  1626    * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
       
  1627    * @see EncodeFile()
       
  1628    * @access protected
  1210    * @return string
  1629    * @return string
  1211    */
  1630    */
  1212   function EncodeFile ($path, $encoding = 'base64') {
  1631   protected function EncodeFile($path, $encoding = 'base64') {
  1213     if(!@$fd = fopen($path, 'rb')) {
  1632     try {
  1214       $this->SetError($this->Lang('file_open') . $path);
  1633       if (!is_readable($path)) {
       
  1634         throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
       
  1635       }
       
  1636       if (function_exists('get_magic_quotes')) {
       
  1637         function get_magic_quotes() {
       
  1638           return false;
       
  1639         }
       
  1640       }
       
  1641 	  $magic_quotes = get_magic_quotes_runtime();
       
  1642 	  if ($magic_quotes) {
       
  1643         if (version_compare(PHP_VERSION, '5.3.0', '<')) {
       
  1644           set_magic_quotes_runtime(0);
       
  1645         } else {
       
  1646 		  ini_set('magic_quotes_runtime', 0);
       
  1647 		}
       
  1648 	  }
       
  1649       $file_buffer  = file_get_contents($path);
       
  1650       $file_buffer  = $this->EncodeString($file_buffer, $encoding);
       
  1651 	  if ($magic_quotes) {
       
  1652         if (version_compare(PHP_VERSION, '5.3.0', '<')) {
       
  1653           set_magic_quotes_runtime($magic_quotes);
       
  1654         } else {
       
  1655 		  ini_set('magic_quotes_runtime', $magic_quotes);
       
  1656 	    }
       
  1657 	  }
       
  1658       return $file_buffer;
       
  1659     } catch (Exception $e) {
       
  1660       $this->SetError($e->getMessage());
  1215       return '';
  1661       return '';
  1216     }
  1662     }
  1217     $magic_quotes = get_magic_quotes_runtime();
  1663   }
  1218     set_magic_quotes_runtime(0);
  1664 
  1219     $file_buffer = fread($fd, filesize($path));
  1665   /**
  1220     $file_buffer = $this->EncodeString($file_buffer, $encoding);
  1666    * Encodes string to requested format.
  1221     fclose($fd);
  1667    * Returns an empty string on failure.
  1222     set_magic_quotes_runtime($magic_quotes);
  1668    * @param string $str The text to encode
  1223 
  1669    * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
  1224     return $file_buffer;
  1670    * @access public
  1225   }
       
  1226 
       
  1227   /**
       
  1228    * Encodes string to requested format. Returns an
       
  1229    * empty string on failure.
       
  1230    * @access private
       
  1231    * @return string
  1671    * @return string
  1232    */
  1672    */
  1233   function EncodeString ($str, $encoding = 'base64') {
  1673   public function EncodeString($str, $encoding = 'base64') {
  1234     $encoded = '';
  1674     $encoded = '';
  1235     switch(strtolower($encoding)) {
  1675     switch(strtolower($encoding)) {
  1236       case 'base64':
  1676       case 'base64':
  1237         /* chunk_split is found in PHP >= 3.0.6 */
       
  1238         $encoded = chunk_split(base64_encode($str), 76, $this->LE);
  1677         $encoded = chunk_split(base64_encode($str), 76, $this->LE);
  1239         break;
  1678         break;
  1240       case '7bit':
  1679       case '7bit':
  1241       case '8bit':
  1680       case '8bit':
  1242         $encoded = $this->FixEOL($str);
  1681         $encoded = $this->FixEOL($str);
       
  1682         //Make sure it ends with a line break
  1243         if (substr($encoded, -(strlen($this->LE))) != $this->LE)
  1683         if (substr($encoded, -(strlen($this->LE))) != $this->LE)
  1244           $encoded .= $this->LE;
  1684           $encoded .= $this->LE;
  1245         break;
  1685         break;
  1246       case 'binary':
  1686       case 'binary':
  1247         $encoded = $str;
  1687         $encoded = $str;
  1255     }
  1695     }
  1256     return $encoded;
  1696     return $encoded;
  1257   }
  1697   }
  1258 
  1698 
  1259   /**
  1699   /**
  1260    * Encode a header string to best of Q, B, quoted or none.
  1700    * Encode a header string to best (shortest) of Q, B, quoted or none.
  1261    * @access private
  1701    * @access public
  1262    * @return string
  1702    * @return string
  1263    */
  1703    */
  1264   function EncodeHeader ($str, $position = 'text') {
  1704   public function EncodeHeader($str, $position = 'text') {
  1265     $x = 0;
  1705     $x = 0;
  1266 
  1706 
  1267     switch (strtolower($position)) {
  1707     switch (strtolower($position)) {
  1268       case 'phrase':
  1708       case 'phrase':
  1269         if (!preg_match('/[\200-\377]/', $str)) {
  1709         if (!preg_match('/[\200-\377]/', $str)) {
  1270           /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
  1710           // Can't use addslashes as we don't know what value has magic_quotes_sybase
  1271           $encoded = addcslashes($str, "\0..\37\177\\\"");
  1711           $encoded = addcslashes($str, "\0..\37\177\\\"");
  1272           if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
  1712           if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
  1273             return ($encoded);
  1713             return ($encoded);
  1274           } else {
  1714           } else {
  1275             return ("\"$encoded\"");
  1715             return ("\"$encoded\"");
  1277         }
  1717         }
  1278         $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
  1718         $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
  1279         break;
  1719         break;
  1280       case 'comment':
  1720       case 'comment':
  1281         $x = preg_match_all('/[()"]/', $str, $matches);
  1721         $x = preg_match_all('/[()"]/', $str, $matches);
  1282         /* Fall-through */
  1722         // Fall-through
  1283       case 'text':
  1723       case 'text':
  1284       default:
  1724       default:
  1285         $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
  1725         $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
  1286         break;
  1726         break;
  1287     }
  1727     }
  1289     if ($x == 0) {
  1729     if ($x == 0) {
  1290       return ($str);
  1730       return ($str);
  1291     }
  1731     }
  1292 
  1732 
  1293     $maxlen = 75 - 7 - strlen($this->CharSet);
  1733     $maxlen = 75 - 7 - strlen($this->CharSet);
  1294     /* Try to select the encoding which should produce the shortest output */
  1734     // Try to select the encoding which should produce the shortest output
  1295     if (strlen($str)/3 < $x) {
  1735     if (strlen($str)/3 < $x) {
  1296       $encoding = 'B';
  1736       $encoding = 'B';
  1297       if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
  1737       if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
  1298      // Use a custom function which correctly encodes and wraps long
  1738         // Use a custom function which correctly encodes and wraps long
  1299      // multibyte strings without breaking lines within a character
  1739         // multibyte strings without breaking lines within a character
  1300         $encoded = $this->Base64EncodeWrapMB($str);
  1740         $encoded = $this->Base64EncodeWrapMB($str);
  1301       } else {
  1741       } else {
  1302         $encoded = base64_encode($str);
  1742         $encoded = base64_encode($str);
  1303         $maxlen -= $maxlen % 4;
  1743         $maxlen -= $maxlen % 4;
  1304         $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
  1744         $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
  1316     return $encoded;
  1756     return $encoded;
  1317   }
  1757   }
  1318 
  1758 
  1319   /**
  1759   /**
  1320    * Checks if a string contains multibyte characters.
  1760    * Checks if a string contains multibyte characters.
  1321    * @access private
  1761    * @access public
  1322    * @param string $str multi-byte text to wrap encode
  1762    * @param string $str multi-byte text to wrap encode
  1323    * @return bool
  1763    * @return bool
  1324    */
  1764    */
  1325   function HasMultiBytes($str) {
  1765   public function HasMultiBytes($str) {
  1326     if (function_exists('mb_strlen')) {
  1766     if (function_exists('mb_strlen')) {
  1327       return (strlen($str) > mb_strlen($str, $this->CharSet));
  1767       return (strlen($str) > mb_strlen($str, $this->CharSet));
  1328     } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
  1768     } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
  1329       return False;
  1769       return false;
  1330     }
  1770     }
  1331   }
  1771   }
  1332 
  1772 
  1333   /**
  1773   /**
  1334    * Correctly encodes and wraps long multibyte strings for mail headers
  1774    * Correctly encodes and wraps long multibyte strings for mail headers
  1335    * without breaking lines within a character.
  1775    * without breaking lines within a character.
  1336    * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
  1776    * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
  1337    * @access private
  1777    * @access public
  1338    * @param string $str multi-byte text to wrap encode
  1778    * @param string $str multi-byte text to wrap encode
  1339    * @return string
  1779    * @return string
  1340    */
  1780    */
  1341   function Base64EncodeWrapMB($str) {
  1781   public function Base64EncodeWrapMB($str) {
  1342     $start = "=?".$this->CharSet."?B?";
  1782     $start = "=?".$this->CharSet."?B?";
  1343     $end = "?=";
  1783     $end = "?=";
  1344     $encoded = "";
  1784     $encoded = "";
  1345 
  1785 
  1346     $mb_length = mb_strlen($str, $this->CharSet);
  1786     $mb_length = mb_strlen($str, $this->CharSet);
  1369     $encoded = substr($encoded, 0, -strlen($this->LE));
  1809     $encoded = substr($encoded, 0, -strlen($this->LE));
  1370     return $encoded;
  1810     return $encoded;
  1371   }
  1811   }
  1372 
  1812 
  1373   /**
  1813   /**
  1374    * Encode string to quoted-printable.
  1814   * Encode string to quoted-printable.
  1375    * @access private
  1815   * Only uses standard PHP, slow, but will always work
  1376    * @return string
  1816   * @access public
  1377    */
  1817   * @param string $string the text to encode
  1378   function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
  1818   * @param integer $line_max Number of chars allowed on a line before wrapping
  1379     $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
  1819   * @return string
       
  1820   */
       
  1821   public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
       
  1822     $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
  1380     $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
  1823     $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
  1381     $eol = "\r\n";
  1824     $eol = "\r\n";
  1382     $escape = '=';
  1825     $escape = '=';
  1383     $output = '';
  1826     $output = '';
  1384     while( list(, $line) = each($lines) ) {
  1827     while( list(, $line) = each($lines) ) {
  1415     } // end of while
  1858     } // end of while
  1416     return $output;
  1859     return $output;
  1417   }
  1860   }
  1418 
  1861 
  1419   /**
  1862   /**
  1420    * Callback for converting to "=XX".
  1863   * Encode string to RFC2045 (6.7) quoted-printable format
  1421    * @access private
  1864   * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
       
  1865   * Also results in same content as you started with after decoding
       
  1866   * @see EncodeQPphp()
       
  1867   * @access public
       
  1868   * @param string $string the text to encode
       
  1869   * @param integer $line_max Number of chars allowed on a line before wrapping
       
  1870   * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
       
  1871   * @return string
       
  1872   * @author Marcus Bointon
       
  1873   */
       
  1874   public function EncodeQP($string, $line_max = 76, $space_conv = false) {
       
  1875     if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
       
  1876       return quoted_printable_encode($string);
       
  1877     }
       
  1878     $filters = stream_get_filters();
       
  1879     if (!in_array('convert.*', $filters)) { //Got convert stream filter?
       
  1880       return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
       
  1881     }
       
  1882     $fp = fopen('php://temp/', 'r+');
       
  1883     $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
       
  1884     $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
       
  1885     $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
       
  1886     fputs($fp, $string);
       
  1887     rewind($fp);
       
  1888     $out = stream_get_contents($fp);
       
  1889     stream_filter_remove($s);
       
  1890     $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
       
  1891     fclose($fp);
       
  1892     return $out;
       
  1893   }
       
  1894 
       
  1895   /**
       
  1896    * Encode string to q encoding.
       
  1897    * @link http://tools.ietf.org/html/rfc2047
       
  1898    * @param string $str the text to encode
       
  1899    * @param string $position Where the text is going to be used, see the RFC for what that means
       
  1900    * @access public
  1422    * @return string
  1901    * @return string
  1423    */
  1902    */
  1424   function EncodeQ_callback ($matches) {
  1903   public function EncodeQ($str, $position = 'text') {
  1425     return sprintf('=%02X', ord($matches[1]));
  1904     // There should not be any EOL in the string
  1426   }
  1905     $encoded = preg_replace('/[\r\n]*/', '', $str);
  1427 
       
  1428   /**
       
  1429    * Encode string to q encoding.
       
  1430    * @access private
       
  1431    * @return string
       
  1432    */
       
  1433   function EncodeQ ($str, $position = 'text') {
       
  1434     /* There should not be any EOL in the string */
       
  1435     $encoded = preg_replace("/[\r\n]/", '', $str);
       
  1436 
  1906 
  1437     switch (strtolower($position)) {
  1907     switch (strtolower($position)) {
  1438       case 'phrase':
  1908       case 'phrase':
  1439         $encoded = preg_replace_callback("/([^A-Za-z0-9!*+\/ -])/",
  1909         $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
  1440                                          array('PHPMailer', 'EncodeQ_callback'), $encoded);
       
  1441         break;
  1910         break;
  1442       case 'comment':
  1911       case 'comment':
  1443         $encoded = preg_replace_callback("/([\(\)\"])/",
  1912         $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
  1444                                          array('PHPMailer', 'EncodeQ_callback'), $encoded);
       
  1445         break;
       
  1446       case 'text':
  1913       case 'text':
  1447       default:
  1914       default:
  1448         /* Replace every high ascii, control =, ? and _ characters */
  1915         // Replace every high ascii, control =, ? and _ characters
  1449         $encoded = preg_replace_callback('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/',
  1916         //TODO using /e (equivalent to eval()) is probably not a good idea
  1450                                          array('PHPMailer', 'EncodeQ_callback'), $encoded);
  1917         $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
       
  1918                                 "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
  1451         break;
  1919         break;
  1452     }
  1920     }
  1453 
  1921 
  1454     /* Replace every spaces to _ (more readable than =20) */
  1922     // Replace every spaces to _ (more readable than =20)
  1455     $encoded = str_replace(' ', '_', $encoded);
  1923     $encoded = str_replace(' ', '_', $encoded);
  1456 
  1924 
  1457     return $encoded;
  1925     return $encoded;
  1458   }
  1926   }
  1459 
  1927 
  1465    * @param string $filename Name of the attachment.
  1933    * @param string $filename Name of the attachment.
  1466    * @param string $encoding File encoding (see $Encoding).
  1934    * @param string $encoding File encoding (see $Encoding).
  1467    * @param string $type File extension (MIME) type.
  1935    * @param string $type File extension (MIME) type.
  1468    * @return void
  1936    * @return void
  1469    */
  1937    */
  1470   function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
  1938   public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
  1471     /* Append to $attachment array */
  1939     // Append to $attachment array
  1472     $cur = count($this->attachment);
  1940     $this->attachment[] = array(
  1473     $this->attachment[$cur][0] = $string;
  1941       0 => $string,
  1474     $this->attachment[$cur][1] = $filename;
  1942       1 => $filename,
  1475     $this->attachment[$cur][2] = $filename;
  1943       2 => basename($filename),
  1476     $this->attachment[$cur][3] = $encoding;
  1944       3 => $encoding,
  1477     $this->attachment[$cur][4] = $type;
  1945       4 => $type,
  1478     $this->attachment[$cur][5] = true; // isString
  1946       5 => true,  // isStringAttachment
  1479     $this->attachment[$cur][6] = 'attachment';
  1947       6 => 'attachment',
  1480     $this->attachment[$cur][7] = 0;
  1948       7 => 0
       
  1949     );
  1481   }
  1950   }
  1482 
  1951 
  1483   /**
  1952   /**
  1484    * Adds an embedded attachment.  This can include images, sounds, and
  1953    * Adds an embedded attachment.  This can include images, sounds, and
  1485    * just about any other document.  Make sure to set the $type to an
  1954    * just about any other document.  Make sure to set the $type to an
  1491    * @param string $name Overrides the attachment name.
  1960    * @param string $name Overrides the attachment name.
  1492    * @param string $encoding File encoding (see $Encoding).
  1961    * @param string $encoding File encoding (see $Encoding).
  1493    * @param string $type File extension (MIME) type.
  1962    * @param string $type File extension (MIME) type.
  1494    * @return bool
  1963    * @return bool
  1495    */
  1964    */
  1496   function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
  1965   public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
  1497 
  1966 
  1498     if(!@is_file($path)) {
  1967     if ( !@is_file($path) ) {
  1499       $this->SetError($this->Lang('file_access') . $path);
  1968       $this->SetError($this->Lang('file_access') . $path);
  1500       return false;
  1969       return false;
  1501     }
  1970     }
  1502 
  1971 
  1503     $filename = basename($path);
  1972     $filename = basename($path);
  1504     if($name == '') {
  1973     if ( $name == '' ) {
  1505       $name = $filename;
  1974       $name = $filename;
  1506     }
  1975     }
  1507 
  1976 
  1508     /* Append to $attachment array */
  1977     // Append to $attachment array
  1509     $cur = count($this->attachment);
  1978     $this->attachment[] = array(
  1510     $this->attachment[$cur][0] = $path;
  1979       0 => $path,
  1511     $this->attachment[$cur][1] = $filename;
  1980       1 => $filename,
  1512     $this->attachment[$cur][2] = $name;
  1981       2 => $name,
  1513     $this->attachment[$cur][3] = $encoding;
  1982       3 => $encoding,
  1514     $this->attachment[$cur][4] = $type;
  1983       4 => $type,
  1515     $this->attachment[$cur][5] = false;
  1984       5 => false,  // isStringAttachment
  1516     $this->attachment[$cur][6] = 'inline';
  1985       6 => 'inline',
  1517     $this->attachment[$cur][7] = $cid;
  1986       7 => $cid
       
  1987     );
  1518 
  1988 
  1519     return true;
  1989     return true;
  1520   }
  1990   }
  1521 
  1991 
       
  1992   public function AddStringEmbeddedImage($string, $cid, $filename = '', $encoding = 'base64', $type = 'application/octet-stream') {
       
  1993     // Append to $attachment array
       
  1994     $this->attachment[] = array(
       
  1995       0 => $string,
       
  1996       1 => $filename,
       
  1997       2 => basename($filename),
       
  1998       3 => $encoding,
       
  1999       4 => $type,
       
  2000       5 => true,  // isStringAttachment
       
  2001       6 => 'inline',
       
  2002       7 => $cid
       
  2003     );
       
  2004   }
       
  2005 
  1522   /**
  2006   /**
  1523    * Returns true if an inline attachment is present.
  2007    * Returns true if an inline attachment is present.
  1524    * @access private
  2008    * @access public
  1525    * @return bool
  2009    * @return bool
  1526    */
  2010    */
  1527   function InlineImageExists() {
  2011   public function InlineImageExists() {
  1528     $result = false;
  2012     foreach($this->attachment as $attachment) {
  1529     for($i = 0; $i < count($this->attachment); $i++) {
  2013       if ($attachment[6] == 'inline') {
  1530       if($this->attachment[$i][6] == 'inline') {
  2014         return true;
  1531         $result = true;
  2015       }
  1532         break;
  2016     }
  1533       }
  2017     return false;
  1534     }
  2018   }
  1535 
  2019 
  1536     return $result;
  2020   public function AttachmentExists() {
       
  2021     foreach($this->attachment as $attachment) {
       
  2022       if ($attachment[6] == 'attachment') {
       
  2023         return true;
       
  2024       }
       
  2025     }
       
  2026     return false;
       
  2027   }
       
  2028 
       
  2029   public function AlternativeExists() {
       
  2030     return strlen($this->AltBody)>0;
  1537   }
  2031   }
  1538 
  2032 
  1539   /////////////////////////////////////////////////
  2033   /////////////////////////////////////////////////
  1540   // CLASS METHODS, MESSAGE RESET
  2034   // CLASS METHODS, MESSAGE RESET
  1541   /////////////////////////////////////////////////
  2035   /////////////////////////////////////////////////
  1542 
  2036 
  1543   /**
  2037   /**
  1544    * Clears all recipients assigned in the TO array.  Returns void.
  2038    * Clears all recipients assigned in the TO array.  Returns void.
  1545    * @return void
  2039    * @return void
  1546    */
  2040    */
  1547   function ClearAddresses() {
  2041   public function ClearAddresses() {
       
  2042     foreach($this->to as $to) {
       
  2043       unset($this->all_recipients[strtolower($to[0])]);
       
  2044     }
  1548     $this->to = array();
  2045     $this->to = array();
  1549   }
  2046   }
  1550 
  2047 
  1551   /**
  2048   /**
  1552    * Clears all recipients assigned in the CC array.  Returns void.
  2049    * Clears all recipients assigned in the CC array.  Returns void.
  1553    * @return void
  2050    * @return void
  1554    */
  2051    */
  1555   function ClearCCs() {
  2052   public function ClearCCs() {
       
  2053     foreach($this->cc as $cc) {
       
  2054       unset($this->all_recipients[strtolower($cc[0])]);
       
  2055     }
  1556     $this->cc = array();
  2056     $this->cc = array();
  1557   }
  2057   }
  1558 
  2058 
  1559   /**
  2059   /**
  1560    * Clears all recipients assigned in the BCC array.  Returns void.
  2060    * Clears all recipients assigned in the BCC array.  Returns void.
  1561    * @return void
  2061    * @return void
  1562    */
  2062    */
  1563   function ClearBCCs() {
  2063   public function ClearBCCs() {
       
  2064     foreach($this->bcc as $bcc) {
       
  2065       unset($this->all_recipients[strtolower($bcc[0])]);
       
  2066     }
  1564     $this->bcc = array();
  2067     $this->bcc = array();
  1565   }
  2068   }
  1566 
  2069 
  1567   /**
  2070   /**
  1568    * Clears all recipients assigned in the ReplyTo array.  Returns void.
  2071    * Clears all recipients assigned in the ReplyTo array.  Returns void.
  1569    * @return void
  2072    * @return void
  1570    */
  2073    */
  1571   function ClearReplyTos() {
  2074   public function ClearReplyTos() {
  1572     $this->ReplyTo = array();
  2075     $this->ReplyTo = array();
  1573   }
  2076   }
  1574 
  2077 
  1575   /**
  2078   /**
  1576    * Clears all recipients assigned in the TO, CC and BCC
  2079    * Clears all recipients assigned in the TO, CC and BCC
  1577    * array.  Returns void.
  2080    * array.  Returns void.
  1578    * @return void
  2081    * @return void
  1579    */
  2082    */
  1580   function ClearAllRecipients() {
  2083   public function ClearAllRecipients() {
  1581     $this->to = array();
  2084     $this->to = array();
  1582     $this->cc = array();
  2085     $this->cc = array();
  1583     $this->bcc = array();
  2086     $this->bcc = array();
       
  2087     $this->all_recipients = array();
  1584   }
  2088   }
  1585 
  2089 
  1586   /**
  2090   /**
  1587    * Clears all previously set filesystem, string, and binary
  2091    * Clears all previously set filesystem, string, and binary
  1588    * attachments.  Returns void.
  2092    * attachments.  Returns void.
  1589    * @return void
  2093    * @return void
  1590    */
  2094    */
  1591   function ClearAttachments() {
  2095   public function ClearAttachments() {
  1592     $this->attachment = array();
  2096     $this->attachment = array();
  1593   }
  2097   }
  1594 
  2098 
  1595   /**
  2099   /**
  1596    * Clears all custom headers.  Returns void.
  2100    * Clears all custom headers.  Returns void.
  1597    * @return void
  2101    * @return void
  1598    */
  2102    */
  1599   function ClearCustomHeaders() {
  2103   public function ClearCustomHeaders() {
  1600     $this->CustomHeader = array();
  2104     $this->CustomHeader = array();
  1601   }
  2105   }
  1602 
  2106 
  1603   /////////////////////////////////////////////////
  2107   /////////////////////////////////////////////////
  1604   // CLASS METHODS, MISCELLANEOUS
  2108   // CLASS METHODS, MISCELLANEOUS
  1605   /////////////////////////////////////////////////
  2109   /////////////////////////////////////////////////
  1606 
  2110 
  1607   /**
  2111   /**
  1608    * Adds the error message to the error container.
  2112    * Adds the error message to the error container.
  1609    * Returns void.
  2113    * @access protected
  1610    * @access private
       
  1611    * @return void
  2114    * @return void
  1612    */
  2115    */
  1613   function SetError($msg) {
  2116   protected function SetError($msg) {
  1614     $this->error_count++;
  2117     $this->error_count++;
       
  2118     if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
       
  2119       $lasterror = $this->smtp->getError();
       
  2120       if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
       
  2121         $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
       
  2122       }
       
  2123     }
  1615     $this->ErrorInfo = $msg;
  2124     $this->ErrorInfo = $msg;
  1616   }
  2125   }
  1617 
  2126 
  1618   /**
  2127   /**
  1619    * Returns the proper RFC 822 formatted date.
  2128    * Returns the proper RFC 822 formatted date.
  1620    * @access private
  2129    * @access public
  1621    * @return string
  2130    * @return string
  1622    */
  2131    * @static
  1623   function RFCDate() {
  2132    */
       
  2133   public static function RFCDate() {
  1624     $tz = date('Z');
  2134     $tz = date('Z');
  1625     $tzs = ($tz < 0) ? '-' : '+';
  2135     $tzs = ($tz < 0) ? '-' : '+';
  1626     $tz = abs($tz);
  2136     $tz = abs($tz);
  1627     $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
  2137     $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
  1628     $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
  2138     $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
  1629 
  2139 
  1630     return $result;
  2140     return $result;
  1631   }
  2141   }
  1632 
  2142 
  1633   /**
  2143   /**
  1634    * Returns the appropriate server variable.  Should work with both
       
  1635    * PHP 4.1.0+ as well as older versions.  Returns an empty string
       
  1636    * if nothing is found.
       
  1637    * @access private
       
  1638    * @return mixed
       
  1639    */
       
  1640   function ServerVar($varName) {
       
  1641     global $HTTP_SERVER_VARS;
       
  1642     global $HTTP_ENV_VARS;
       
  1643 
       
  1644     if(!isset($_SERVER)) {
       
  1645       $_SERVER = $HTTP_SERVER_VARS;
       
  1646       if(!isset($_SERVER['REMOTE_ADDR'])) {
       
  1647         $_SERVER = $HTTP_ENV_VARS; // must be Apache
       
  1648       }
       
  1649     }
       
  1650 
       
  1651     if(isset($_SERVER[$varName])) {
       
  1652       return $_SERVER[$varName];
       
  1653     } else {
       
  1654       return '';
       
  1655     }
       
  1656   }
       
  1657 
       
  1658   /**
       
  1659    * Returns the server hostname or 'localhost.localdomain' if unknown.
  2144    * Returns the server hostname or 'localhost.localdomain' if unknown.
  1660    * @access private
  2145    * @access protected
  1661    * @return string
  2146    * @return string
  1662    */
  2147    */
  1663   function ServerHostname() {
  2148   protected function ServerHostname() {
  1664     if ($this->Hostname != '') {
  2149     if (!empty($this->Hostname)) {
  1665       $result = $this->Hostname;
  2150       $result = $this->Hostname;
  1666     } elseif ($this->ServerVar('SERVER_NAME') != '') {
  2151     } elseif (isset($_SERVER['SERVER_NAME'])) {
  1667       $result = $this->ServerVar('SERVER_NAME');
  2152       $result = $_SERVER['SERVER_NAME'];
  1668     } else {
  2153     } else {
  1669       $result = 'localhost.localdomain';
  2154       $result = 'localhost.localdomain';
  1670     }
  2155     }
  1671 
  2156 
  1672     return $result;
  2157     return $result;
  1673   }
  2158   }
  1674 
  2159 
  1675   /**
  2160   /**
  1676    * Returns a message in the appropriate language.
  2161    * Returns a message in the appropriate language.
  1677    * @access private
  2162    * @access protected
  1678    * @return string
  2163    * @return string
  1679    */
  2164    */
  1680   function Lang($key) {
  2165   protected function Lang($key) {
  1681     if(count($this->language) < 1) {
  2166     if(count($this->language) < 1) {
  1682       $this->SetLanguage('en'); // set the default language
  2167       $this->SetLanguage('en'); // set the default language
  1683     }
  2168     }
  1684 
  2169 
  1685     if(isset($this->language[$key])) {
  2170     if(isset($this->language[$key])) {
  1689     }
  2174     }
  1690   }
  2175   }
  1691 
  2176 
  1692   /**
  2177   /**
  1693    * Returns true if an error occurred.
  2178    * Returns true if an error occurred.
       
  2179    * @access public
  1694    * @return bool
  2180    * @return bool
  1695    */
  2181    */
  1696   function IsError() {
  2182   public function IsError() {
  1697     return ($this->error_count > 0);
  2183     return ($this->error_count > 0);
  1698   }
  2184   }
  1699 
  2185 
  1700   /**
  2186   /**
  1701    * Changes every end of line from CR or LF to CRLF.
  2187    * Changes every end of line from CR or LF to CRLF.
  1702    * @access private
  2188    * @access public
  1703    * @return string
  2189    * @return string
  1704    */
  2190    */
  1705   function FixEOL($str) {
  2191   public function FixEOL($str) {
  1706     $str = str_replace("\r\n", "\n", $str);
  2192     $str = str_replace("\r\n", "\n", $str);
  1707     $str = str_replace("\r", "\n", $str);
  2193     $str = str_replace("\r", "\n", $str);
  1708     $str = str_replace("\n", $this->LE, $str);
  2194     $str = str_replace("\n", $this->LE, $str);
  1709     return $str;
  2195     return $str;
  1710   }
  2196   }
  1711 
  2197 
  1712   /**
  2198   /**
  1713    * Adds a custom header.
  2199    * Adds a custom header.
       
  2200    * @access public
  1714    * @return void
  2201    * @return void
  1715    */
  2202    */
  1716   function AddCustomHeader($custom_header) {
  2203   public function AddCustomHeader($custom_header) {
  1717     $this->CustomHeader[] = explode(':', $custom_header, 2);
  2204     $this->CustomHeader[] = explode(':', $custom_header, 2);
  1718   }
  2205   }
  1719 
  2206 
  1720   /**
  2207   /**
  1721    * Evaluates the message and returns modifications for inline images and backgrounds
  2208    * Evaluates the message and returns modifications for inline images and backgrounds
  1722    * @access public
  2209    * @access public
  1723    * @return $message
  2210    * @return $message
  1724    */
  2211    */
  1725   function MsgHTML($message,$basedir='') {
  2212   public function MsgHTML($message, $basedir = '') {
  1726     preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
  2213     preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);
  1727     if(isset($images[2])) {
  2214     if(isset($images[2])) {
  1728       foreach($images[2] as $i => $url) {
  2215       foreach($images[2] as $i => $url) {
  1729         // do not change urls for absolute images (thanks to corvuscorax)
  2216         // do not change urls for absolute images (thanks to corvuscorax)
  1730         if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) {
  2217         if (!preg_match('#^[A-z]+://#', $url)) {
  1731           $filename = basename($url);
  2218           $filename = basename($url);
  1732           $directory = dirname($url);
  2219           $directory = dirname($url);
  1733           ($directory == '.')?$directory='':'';
  2220           ($directory == '.') ? $directory='': '';
  1734           $cid = 'cid:' . md5($filename);
  2221           $cid = 'cid:' . md5($filename);
  1735           $fileParts = split("\.", $filename);
  2222           $ext = pathinfo($filename, PATHINFO_EXTENSION);
  1736           $ext = $fileParts[1];
  2223           $mimeType  = self::_mime_types($ext);
  1737           $mimeType = $this->_mime_types($ext);
  2224           if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; }
  1738           if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
  2225           if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; }
  1739           if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
  2226           if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType) ) {
  1740           if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
  2227             $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"".$cid."\"", $message);
  1741             $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
       
  1742           }
  2228           }
  1743         }
  2229         }
  1744       }
  2230       }
  1745     }
  2231     }
  1746     $this->IsHTML(true);
  2232     $this->IsHTML(true);
  1747     $this->Body = $message;
  2233     $this->Body = $message;
  1748     $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
  2234 	if (empty($this->AltBody)) {
  1749     if ( !empty($textMsg) && empty($this->AltBody) ) {
  2235 		$textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message)));
  1750       $this->AltBody = html_entity_decode($textMsg);
  2236 		if (!empty($textMsg)) {
  1751     }
  2237 			$this->AltBody = html_entity_decode($textMsg, ENT_QUOTES, $this->CharSet);
  1752     if ( empty($this->AltBody) ) {
  2238 		}
  1753       $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";
  2239 	}
  1754     }
  2240     if (empty($this->AltBody)) {
  1755   }
  2241       $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
  1756 
  2242     }
  1757   /**
  2243 	return $message;
  1758    * Gets the mime type of the embedded or inline image
  2244   }
  1759    * @access private
  2245 
  1760    * @return mime type of ext
  2246   /**
  1761    */
  2247    * Gets the MIME type of the embedded or inline image
  1762   function _mime_types($ext = '') {
  2248    * @param string File extension
       
  2249    * @access public
       
  2250    * @return string MIME type of ext
       
  2251    * @static
       
  2252    */
       
  2253   public static function _mime_types($ext = '') {
  1763     $mimes = array(
  2254     $mimes = array(
       
  2255       'hqx'   =>  'application/mac-binhex40',
       
  2256       'cpt'   =>  'application/mac-compactpro',
       
  2257       'doc'   =>  'application/msword',
       
  2258       'bin'   =>  'application/macbinary',
       
  2259       'dms'   =>  'application/octet-stream',
       
  2260       'lha'   =>  'application/octet-stream',
       
  2261       'lzh'   =>  'application/octet-stream',
       
  2262       'exe'   =>  'application/octet-stream',
       
  2263       'class' =>  'application/octet-stream',
       
  2264       'psd'   =>  'application/octet-stream',
       
  2265       'so'    =>  'application/octet-stream',
       
  2266       'sea'   =>  'application/octet-stream',
       
  2267       'dll'   =>  'application/octet-stream',
       
  2268       'oda'   =>  'application/oda',
       
  2269       'pdf'   =>  'application/pdf',
  1764       'ai'    =>  'application/postscript',
  2270       'ai'    =>  'application/postscript',
  1765       'aif'   =>  'audio/x-aiff',
  2271       'eps'   =>  'application/postscript',
  1766       'aifc'  =>  'audio/x-aiff',
  2272       'ps'    =>  'application/postscript',
  1767       'aiff'  =>  'audio/x-aiff',
  2273       'smi'   =>  'application/smil',
  1768       'avi'   =>  'video/x-msvideo',
  2274       'smil'  =>  'application/smil',
  1769       'bin'   =>  'application/macbinary',
  2275       'mif'   =>  'application/vnd.mif',
  1770       'bmp'   =>  'image/bmp',
  2276       'xls'   =>  'application/vnd.ms-excel',
  1771       'class' =>  'application/octet-stream',
  2277       'ppt'   =>  'application/vnd.ms-powerpoint',
  1772       'cpt'   =>  'application/mac-compactpro',
  2278       'wbxml' =>  'application/vnd.wap.wbxml',
  1773       'css'   =>  'text/css',
  2279       'wmlc'  =>  'application/vnd.wap.wmlc',
  1774       'dcr'   =>  'application/x-director',
  2280       'dcr'   =>  'application/x-director',
  1775       'dir'   =>  'application/x-director',
  2281       'dir'   =>  'application/x-director',
  1776       'dll'   =>  'application/octet-stream',
  2282       'dxr'   =>  'application/x-director',
  1777       'dms'   =>  'application/octet-stream',
       
  1778       'doc'   =>  'application/msword',
       
  1779       'dvi'   =>  'application/x-dvi',
  2283       'dvi'   =>  'application/x-dvi',
  1780       'dxr'   =>  'application/x-director',
       
  1781       'eml'   =>  'message/rfc822',
       
  1782       'eps'   =>  'application/postscript',
       
  1783       'exe'   =>  'application/octet-stream',
       
  1784       'gif'   =>  'image/gif',
       
  1785       'gtar'  =>  'application/x-gtar',
  2284       'gtar'  =>  'application/x-gtar',
  1786       'htm'   =>  'text/html',
  2285       'php'   =>  'application/x-httpd-php',
  1787       'html'  =>  'text/html',
  2286       'php4'  =>  'application/x-httpd-php',
  1788       'jpe'   =>  'image/jpeg',
  2287       'php3'  =>  'application/x-httpd-php',
  1789       'jpeg'  =>  'image/jpeg',
  2288       'phtml' =>  'application/x-httpd-php',
  1790       'jpg'   =>  'image/jpeg',
  2289       'phps'  =>  'application/x-httpd-php-source',
  1791       'hqx'   =>  'application/mac-binhex40',
       
  1792       'js'    =>  'application/x-javascript',
  2290       'js'    =>  'application/x-javascript',
  1793       'lha'   =>  'application/octet-stream',
  2291       'swf'   =>  'application/x-shockwave-flash',
  1794       'log'   =>  'text/plain',
  2292       'sit'   =>  'application/x-stuffit',
  1795       'lzh'   =>  'application/octet-stream',
  2293       'tar'   =>  'application/x-tar',
       
  2294       'tgz'   =>  'application/x-tar',
       
  2295       'xhtml' =>  'application/xhtml+xml',
       
  2296       'xht'   =>  'application/xhtml+xml',
       
  2297       'zip'   =>  'application/zip',
  1796       'mid'   =>  'audio/midi',
  2298       'mid'   =>  'audio/midi',
  1797       'midi'  =>  'audio/midi',
  2299       'midi'  =>  'audio/midi',
  1798       'mif'   =>  'application/vnd.mif',
  2300       'mpga'  =>  'audio/mpeg',
  1799       'mov'   =>  'video/quicktime',
       
  1800       'movie' =>  'video/x-sgi-movie',
       
  1801       'mp2'   =>  'audio/mpeg',
  2301       'mp2'   =>  'audio/mpeg',
  1802       'mp3'   =>  'audio/mpeg',
  2302       'mp3'   =>  'audio/mpeg',
  1803       'mpe'   =>  'video/mpeg',
  2303       'aif'   =>  'audio/x-aiff',
  1804       'mpeg'  =>  'video/mpeg',
  2304       'aiff'  =>  'audio/x-aiff',
  1805       'mpg'   =>  'video/mpeg',
  2305       'aifc'  =>  'audio/x-aiff',
  1806       'mpga'  =>  'audio/mpeg',
       
  1807       'oda'   =>  'application/oda',
       
  1808       'pdf'   =>  'application/pdf',
       
  1809       'php'   =>  'application/x-httpd-php',
       
  1810       'php3'  =>  'application/x-httpd-php',
       
  1811       'php4'  =>  'application/x-httpd-php',
       
  1812       'phps'  =>  'application/x-httpd-php-source',
       
  1813       'phtml' =>  'application/x-httpd-php',
       
  1814       'png'   =>  'image/png',
       
  1815       'ppt'   =>  'application/vnd.ms-powerpoint',
       
  1816       'ps'    =>  'application/postscript',
       
  1817       'psd'   =>  'application/octet-stream',
       
  1818       'qt'    =>  'video/quicktime',
       
  1819       'ra'    =>  'audio/x-realaudio',
       
  1820       'ram'   =>  'audio/x-pn-realaudio',
  2306       'ram'   =>  'audio/x-pn-realaudio',
  1821       'rm'    =>  'audio/x-pn-realaudio',
  2307       'rm'    =>  'audio/x-pn-realaudio',
  1822       'rpm'   =>  'audio/x-pn-realaudio-plugin',
  2308       'rpm'   =>  'audio/x-pn-realaudio-plugin',
       
  2309       'ra'    =>  'audio/x-realaudio',
       
  2310       'rv'    =>  'video/vnd.rn-realvideo',
       
  2311       'wav'   =>  'audio/x-wav',
       
  2312       'bmp'   =>  'image/bmp',
       
  2313       'gif'   =>  'image/gif',
       
  2314       'jpeg'  =>  'image/jpeg',
       
  2315       'jpg'   =>  'image/jpeg',
       
  2316       'jpe'   =>  'image/jpeg',
       
  2317       'png'   =>  'image/png',
       
  2318       'tiff'  =>  'image/tiff',
       
  2319       'tif'   =>  'image/tiff',
       
  2320       'css'   =>  'text/css',
       
  2321       'html'  =>  'text/html',
       
  2322       'htm'   =>  'text/html',
       
  2323       'shtml' =>  'text/html',
       
  2324       'txt'   =>  'text/plain',
       
  2325       'text'  =>  'text/plain',
       
  2326       'log'   =>  'text/plain',
       
  2327       'rtx'   =>  'text/richtext',
  1823       'rtf'   =>  'text/rtf',
  2328       'rtf'   =>  'text/rtf',
  1824       'rtx'   =>  'text/richtext',
       
  1825       'rv'    =>  'video/vnd.rn-realvideo',
       
  1826       'sea'   =>  'application/octet-stream',
       
  1827       'shtml' =>  'text/html',
       
  1828       'sit'   =>  'application/x-stuffit',
       
  1829       'so'    =>  'application/octet-stream',
       
  1830       'smi'   =>  'application/smil',
       
  1831       'smil'  =>  'application/smil',
       
  1832       'swf'   =>  'application/x-shockwave-flash',
       
  1833       'tar'   =>  'application/x-tar',
       
  1834       'text'  =>  'text/plain',
       
  1835       'txt'   =>  'text/plain',
       
  1836       'tgz'   =>  'application/x-tar',
       
  1837       'tif'   =>  'image/tiff',
       
  1838       'tiff'  =>  'image/tiff',
       
  1839       'wav'   =>  'audio/x-wav',
       
  1840       'wbxml' =>  'application/vnd.wap.wbxml',
       
  1841       'wmlc'  =>  'application/vnd.wap.wmlc',
       
  1842       'word'  =>  'application/msword',
       
  1843       'xht'   =>  'application/xhtml+xml',
       
  1844       'xhtml' =>  'application/xhtml+xml',
       
  1845       'xl'    =>  'application/excel',
       
  1846       'xls'   =>  'application/vnd.ms-excel',
       
  1847       'xml'   =>  'text/xml',
  2329       'xml'   =>  'text/xml',
  1848       'xsl'   =>  'text/xml',
  2330       'xsl'   =>  'text/xml',
  1849       'zip'   =>  'application/zip'
  2331       'mpeg'  =>  'video/mpeg',
       
  2332       'mpg'   =>  'video/mpeg',
       
  2333       'mpe'   =>  'video/mpeg',
       
  2334       'qt'    =>  'video/quicktime',
       
  2335       'mov'   =>  'video/quicktime',
       
  2336       'avi'   =>  'video/x-msvideo',
       
  2337       'movie' =>  'video/x-sgi-movie',
       
  2338       'doc'   =>  'application/msword',
       
  2339       'word'  =>  'application/msword',
       
  2340       'xl'    =>  'application/excel',
       
  2341       'eml'   =>  'message/rfc822'
  1850     );
  2342     );
  1851     return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
  2343     return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
  1852   }
  2344   }
  1853 
  2345 
  1854   /**
  2346   /**
  1855    * Set (or reset) Class Objects (variables)
  2347   * Set (or reset) Class Objects (variables)
  1856    *
  2348   *
  1857    * Usage Example:
  2349   * Usage Example:
  1858    * $page->set('X-Priority', '3');
  2350   * $page->set('X-Priority', '3');
  1859    *
  2351   *
  1860    * @access public
  2352   * @access public
  1861    * @param string $name Parameter Name
  2353   * @param string $name Parameter Name
  1862    * @param mixed $value Parameter Value
  2354   * @param mixed $value Parameter Value
  1863    * NOTE: will not work with arrays, there are no arrays to set/reset
  2355   * NOTE: will not work with arrays, there are no arrays to set/reset
  1864    */
  2356   * @todo Should this not be using __set() magic function?
  1865   function set ( $name, $value = '' ) {
  2357   */
  1866     if ( isset($this->$name) ) {
  2358   public function set($name, $value = '') {
  1867       $this->$name = $value;
  2359     try {
  1868     } else {
  2360       if (isset($this->$name) ) {
  1869       $this->SetError('Cannot set or reset variable ' . $name);
  2361         $this->$name = $value;
  1870       return false;
  2362       } else {
  1871     }
  2363         throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
  1872   }
  2364       }
  1873 
  2365     } catch (Exception $e) {
  1874   /**
  2366       $this->SetError($e->getMessage());
  1875    * Read a file from a supplied filename and return it.
  2367       if ($e->getCode() == self::STOP_CRITICAL) {
  1876    *
  2368         return false;
  1877    * @access public
  2369       }
  1878    * @param string $filename Parameter File Name
  2370     }
  1879    */
  2371     return true;
  1880   function getFile($filename) {
       
  1881     $return = '';
       
  1882     if ($fp = fopen($filename, 'rb')) {
       
  1883       while (!feof($fp)) {
       
  1884         $return .= fread($fp, 1024);
       
  1885       }
       
  1886       fclose($fp);
       
  1887       return $return;
       
  1888     } else {
       
  1889       return false;
       
  1890     }
       
  1891   }
  2372   }
  1892 
  2373 
  1893   /**
  2374   /**
  1894    * Strips newlines to prevent header injection.
  2375    * Strips newlines to prevent header injection.
  1895    * @access private
  2376    * @access public
  1896    * @param string $str String
  2377    * @param string $str String
  1897    * @return string
  2378    * @return string
  1898    */
  2379    */
  1899   function SecureHeader($str) {
  2380   public function SecureHeader($str) {
  1900     $str = trim($str);
  2381     $str = str_replace("\r", '', $str);
  1901     $str = str_replace("\r", "", $str);
  2382     $str = str_replace("\n", '', $str);
  1902     $str = str_replace("\n", "", $str);
  2383     return trim($str);
  1903     return $str;
       
  1904   }
  2384   }
  1905 
  2385 
  1906   /**
  2386   /**
  1907    * Set the private key file and password to sign the message.
  2387    * Set the private key file and password to sign the message.
  1908    *
  2388    *
  1909    * @access public
  2389    * @access public
  1910    * @param string $key_filename Parameter File Name
  2390    * @param string $key_filename Parameter File Name
  1911    * @param string $key_pass Password for private key
  2391    * @param string $key_pass Password for private key
  1912    */
  2392    */
  1913   function Sign($cert_filename, $key_filename, $key_pass) {
  2393   public function Sign($cert_filename, $key_filename, $key_pass) {
  1914     $this->sign_cert_file = $cert_filename;
  2394     $this->sign_cert_file = $cert_filename;
  1915     $this->sign_key_file = $key_filename;
  2395     $this->sign_key_file = $key_filename;
  1916     $this->sign_key_pass = $key_pass;
  2396     $this->sign_key_pass = $key_pass;
  1917   }
  2397   }
  1918 
  2398 
       
  2399   /**
       
  2400    * Set the private key file and password to sign the message.
       
  2401    *
       
  2402    * @access public
       
  2403    * @param string $key_filename Parameter File Name
       
  2404    * @param string $key_pass Password for private key
       
  2405    */
       
  2406   public function DKIM_QP($txt) {
       
  2407     $tmp = '';
       
  2408     $line = '';
       
  2409     for ($i = 0; $i < strlen($txt); $i++) {
       
  2410       $ord = ord($txt[$i]);
       
  2411       if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
       
  2412         $line .= $txt[$i];
       
  2413       } else {
       
  2414         $line .= "=".sprintf("%02X", $ord);
       
  2415       }
       
  2416     }
       
  2417     return $line;
       
  2418   }
       
  2419 
       
  2420   /**
       
  2421    * Generate DKIM signature
       
  2422    *
       
  2423    * @access public
       
  2424    * @param string $s Header
       
  2425    */
       
  2426   public function DKIM_Sign($s) {
       
  2427     $privKeyStr = file_get_contents($this->DKIM_private);
       
  2428     if ($this->DKIM_passphrase != '') {
       
  2429       $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
       
  2430     } else {
       
  2431       $privKey = $privKeyStr;
       
  2432     }
       
  2433     if (openssl_sign($s, $signature, $privKey)) {
       
  2434       return base64_encode($signature);
       
  2435     }
       
  2436   }
       
  2437 
       
  2438   /**
       
  2439    * Generate DKIM Canonicalization Header
       
  2440    *
       
  2441    * @access public
       
  2442    * @param string $s Header
       
  2443    */
       
  2444   public function DKIM_HeaderC($s) {
       
  2445     $s = preg_replace("/\r\n\s+/", " ", $s);
       
  2446     $lines = explode("\r\n", $s);
       
  2447     foreach ($lines as $key => $line) {
       
  2448       list($heading, $value) = explode(":", $line, 2);
       
  2449       $heading = strtolower($heading);
       
  2450       $value = preg_replace("/\s+/", " ", $value) ; // Compress useless spaces
       
  2451       $lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value
       
  2452     }
       
  2453     $s = implode("\r\n", $lines);
       
  2454     return $s;
       
  2455   }
       
  2456 
       
  2457   /**
       
  2458    * Generate DKIM Canonicalization Body
       
  2459    *
       
  2460    * @access public
       
  2461    * @param string $body Message Body
       
  2462    */
       
  2463   public function DKIM_BodyC($body) {
       
  2464     if ($body == '') return "\r\n";
       
  2465     // stabilize line endings
       
  2466     $body = str_replace("\r\n", "\n", $body);
       
  2467     $body = str_replace("\n", "\r\n", $body);
       
  2468     // END stabilize line endings
       
  2469     while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
       
  2470       $body = substr($body, 0, strlen($body) - 2);
       
  2471     }
       
  2472     return $body;
       
  2473   }
       
  2474 
       
  2475   /**
       
  2476    * Create the DKIM header, body, as new header
       
  2477    *
       
  2478    * @access public
       
  2479    * @param string $headers_line Header lines
       
  2480    * @param string $subject Subject
       
  2481    * @param string $body Body
       
  2482    */
       
  2483   public function DKIM_Add($headers_line, $subject, $body) {
       
  2484     $DKIMsignatureType    = 'rsa-sha1'; // Signature & hash algorithms
       
  2485     $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
       
  2486     $DKIMquery            = 'dns/txt'; // Query method
       
  2487     $DKIMtime             = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
       
  2488     $subject_header       = "Subject: $subject";
       
  2489     $headers              = explode($this->LE, $headers_line);
       
  2490     foreach($headers as $header) {
       
  2491       if (strpos($header, 'From:') === 0) {
       
  2492         $from_header = $header;
       
  2493       } elseif (strpos($header, 'To:') === 0) {
       
  2494         $to_header = $header;
       
  2495       }
       
  2496     }
       
  2497     $from     = str_replace('|', '=7C', $this->DKIM_QP($from_header));
       
  2498     $to       = str_replace('|', '=7C', $this->DKIM_QP($to_header));
       
  2499     $subject  = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
       
  2500     $body     = $this->DKIM_BodyC($body);
       
  2501     $DKIMlen  = strlen($body) ; // Length of body
       
  2502     $DKIMb64  = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
       
  2503     $ident    = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
       
  2504     $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
       
  2505                 "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
       
  2506                 "\th=From:To:Subject;\r\n".
       
  2507                 "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
       
  2508                 "\tz=$from\r\n".
       
  2509                 "\t|$to\r\n".
       
  2510                 "\t|$subject;\r\n".
       
  2511                 "\tbh=" . $DKIMb64 . ";\r\n".
       
  2512                 "\tb=";
       
  2513     $toSign   = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
       
  2514     $signed   = $this->DKIM_Sign($toSign);
       
  2515     return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n";
       
  2516   }
       
  2517 
       
  2518   protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body) {
       
  2519     if (!empty($this->action_function) && function_exists($this->action_function)) {
       
  2520       $params = array($isSent, $to, $cc, $bcc, $subject, $body);
       
  2521       call_user_func_array($this->action_function, $params);
       
  2522     }
       
  2523   }
  1919 }
  2524 }
  1920 
  2525 
       
  2526 class phpmailerException extends Exception {
       
  2527   public function errorMessage() {
       
  2528     $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
       
  2529     return $errorMsg;
       
  2530   }
       
  2531 }
  1921 ?>
  2532 ?>