Email.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2008, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * CodeIgniter Email Class
00020  *
00021  * Permits email to be sent using Mail, Sendmail, or SMTP.
00022  *
00023  * @package             CodeIgniter
00024  * @subpackage  Libraries
00025  * @category    Libraries
00026  * @author              ExpressionEngine Dev Team
00027  * @link                http://codeigniter.com/user_guide/libraries/email.html
00028  */
00029 class CI_Email {
00030 
00031         var     $useragent              = "CodeIgniter";
00032         var     $mailpath               = "/usr/sbin/sendmail"; // Sendmail path
00033         var     $protocol               = "mail";       // mail/sendmail/smtp
00034         var     $smtp_host              = "";           // SMTP Server.  Example: mail.earthlink.net
00035         var     $smtp_user              = "";           // SMTP Username
00036         var     $smtp_pass              = "";           // SMTP Password
00037         var     $smtp_port              = "25";         // SMTP Port
00038         var     $smtp_timeout   = 5;            // SMTP Timeout in seconds
00039         var     $wordwrap               = TRUE;         // TRUE/FALSE  Turns word-wrap on/off
00040         var     $wrapchars              = "76";         // Number of characters to wrap at.
00041         var     $mailtype               = "text";       // text/html  Defines email formatting
00042         var     $charset                = "utf-8";      // Default char set: iso-8859-1 or us-ascii
00043         var     $multipart              = "mixed";      // "mixed" (in the body) or "related" (separate)
00044         var $alt_message        = '';           // Alternative message for HTML emails
00045         var     $validate               = FALSE;        // TRUE/FALSE.  Enables email validation
00046         var     $priority               = "3";          // Default priority (1 - 5)
00047         var     $newline                = "\n";         // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
00048         var $crlf                       = "\n";         // The RFC 2045 compliant CRLF for quoted-printable is "\r\n".  Apparently some servers,
00049                                                                         // even on the receiving end think they need to muck with CRLFs, so using "\n", while
00050                                                                         // distasteful, is the only thing that seems to work for all environments.
00051         var $send_multipart     = TRUE;         // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override.  Set to FALSE for Yahoo.     
00052         var     $bcc_batch_mode = FALSE;        // TRUE/FALSE  Turns on/off Bcc batch feature
00053         var     $bcc_batch_size = 200;          // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
00054         var $_safe_mode         = FALSE;
00055         var     $_subject               = "";
00056         var     $_body                  = "";
00057         var     $_finalbody             = "";
00058         var     $_alt_boundary  = "";
00059         var     $_atc_boundary  = "";
00060         var     $_header_str    = "";
00061         var     $_smtp_connect  = "";
00062         var     $_encoding              = "8bit";
00063         var $_IP                        = FALSE;
00064         var     $_smtp_auth             = FALSE;
00065         var $_replyto_flag      = FALSE;
00066         var     $_debug_msg             = array();
00067         var     $_recipients    = array();
00068         var     $_cc_array              = array();
00069         var     $_bcc_array             = array();
00070         var     $_headers               = array();
00071         var     $_attach_name   = array();
00072         var     $_attach_type   = array();
00073         var     $_attach_disp   = array();
00074         var     $_protocols             = array('mail', 'sendmail', 'smtp');
00075         var     $_base_charsets = array('us-ascii', 'iso-2022-');       // 7-bit charsets (excluding language suffix)
00076         var     $_bit_depths    = array('7bit', '8bit');
00077         var     $_priorities    = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
00078 
00079 
00080         /**
00081          * Constructor - Sets Email Preferences
00082          *
00083          * The constructor can be passed an array of config values
00084          */
00085         function CI_Email($config = array())
00086         {       
00087                 if (count($config) > 0)
00088                 {
00089                         $this->initialize($config);
00090                 }       
00091                 else
00092                 {
00093                         $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; 
00094                         $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
00095                 }
00096                 
00097                 log_message('debug', "Email Class Initialized");
00098         }
00099 
00100         // --------------------------------------------------------------------
00101 
00102         /**
00103          * Initialize preferences
00104          *
00105          * @access      public
00106          * @param       array
00107          * @return      void
00108          */
00109         function initialize($config = array())
00110         {
00111                 $this->clear();
00112                 foreach ($config as $key => $val)
00113                 {
00114                         if (isset($this->$key))
00115                         {
00116                                 $method = 'set_'.$key;
00117 
00118                                 if (method_exists($this, $method))
00119                                 {
00120                                         $this->$method($val);
00121                                 }
00122                                 else
00123                                 {
00124                                         $this->$key = $val;
00125                                 }       
00126                         }
00127                 }
00128                 
00129                 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; 
00130                 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
00131         }
00132         
00133         // --------------------------------------------------------------------
00134 
00135         /**
00136          * Initialize the Email Data
00137          *
00138          * @access      public
00139          * @return      void
00140          */     
00141         function clear($clear_attachments = FALSE)
00142         {
00143                 $this->_subject         = "";
00144                 $this->_body            = "";
00145                 $this->_finalbody       = "";
00146                 $this->_header_str      = "";
00147                 $this->_replyto_flag = FALSE;
00148                 $this->_recipients      = array();
00149                 $this->_headers         = array();
00150                 $this->_debug_msg       = array();
00151 
00152                 $this->_set_header('User-Agent', $this->useragent);
00153                 $this->_set_header('Date', $this->_set_date());
00154 
00155                 if ($clear_attachments !== FALSE)
00156                 {
00157                         $this->_attach_name = array();
00158                         $this->_attach_type = array();
00159                         $this->_attach_disp = array();
00160                 }   
00161         }
00162         
00163         // --------------------------------------------------------------------
00164 
00165         /**
00166          * Set FROM
00167          *
00168          * @access      public
00169          * @param       string
00170          * @param       string
00171          * @return      void
00172          */     
00173         function from($from, $name = '')
00174         {
00175                 if (preg_match( '/<(.*)>/', $from, $match))
00176                 {
00177                         $from = $match['1'];
00178                 }
00179 
00180                 if ($this->validate)
00181                 {
00182                         $this->validate_email($this->_str_to_array($from));
00183                 }
00184         
00185                 if ($name != '' && strncmp($name, '"', 1) != 0)
00186                 {
00187                         $name = '"'.$name.'"';
00188                 }
00189         
00190                 $this->_set_header('From', $name.' <'.$from.'>');
00191                 $this->_set_header('Return-Path', '<'.$from.'>');
00192         }
00193         
00194         // --------------------------------------------------------------------
00195 
00196         /**
00197          * Set Reply-to
00198          *
00199          * @access      public
00200          * @param       string
00201          * @param       string
00202          * @return      void
00203          */     
00204         function reply_to($replyto, $name = '')
00205         {
00206                 if (preg_match( '/<(.*)>/', $replyto, $match))
00207                 {
00208                         $replyto = $match['1'];
00209                 }
00210 
00211                 if ($this->validate)
00212                 {
00213                         $this->validate_email($this->_str_to_array($replyto));  
00214                 }
00215 
00216                 if ($name == '')
00217                 {
00218                         $name = $replyto;
00219                 }
00220 
00221                 if (strncmp($name, '"', 1) != 0)
00222                 {
00223                         $name = '"'.$name.'"';
00224                 }
00225 
00226                 $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
00227                 $this->_replyto_flag = TRUE;
00228         }
00229         
00230         // --------------------------------------------------------------------
00231 
00232         /**
00233          * Set Recipients
00234          *
00235          * @access      public
00236          * @param       string
00237          * @return      void
00238          */     
00239         function to($to)
00240         {
00241                 $to = $this->_str_to_array($to);
00242                 $to = $this->clean_email($to);
00243         
00244                 if ($this->validate)
00245                 {
00246                         $this->validate_email($to);
00247                 }
00248         
00249                 if ($this->_get_protocol() != 'mail')
00250                 {
00251                         $this->_set_header('To', implode(", ", $to));
00252                 }
00253 
00254                 switch ($this->_get_protocol())
00255                 {
00256                         case 'smtp'             : $this->_recipients = $to;
00257                         break;
00258                         case 'sendmail' : $this->_recipients = implode(", ", $to);
00259                         break;
00260                         case 'mail'             : $this->_recipients = implode(", ", $to);
00261                         break;
00262                 }       
00263         }
00264         
00265         // --------------------------------------------------------------------
00266 
00267         /**
00268          * Set CC
00269          *
00270          * @access      public
00271          * @param       string
00272          * @return      void
00273          */     
00274         function cc($cc)
00275         {       
00276                 $cc = $this->_str_to_array($cc);
00277                 $cc = $this->clean_email($cc);
00278 
00279                 if ($this->validate)
00280                 {
00281                         $this->validate_email($cc);
00282                 }
00283 
00284                 $this->_set_header('Cc', implode(", ", $cc));
00285 
00286                 if ($this->_get_protocol() == "smtp")
00287                 {
00288                         $this->_cc_array = $cc;
00289                 }
00290         }
00291         
00292         // --------------------------------------------------------------------
00293 
00294         /**
00295          * Set BCC
00296          *
00297          * @access      public
00298          * @param       string
00299          * @param       string
00300          * @return      void
00301          */     
00302         function bcc($bcc, $limit = '')
00303         {
00304                 if ($limit != '' && is_numeric($limit))
00305                 {
00306                         $this->bcc_batch_mode = TRUE;
00307                         $this->bcc_batch_size = $limit;
00308                 }
00309 
00310                 $bcc = $this->_str_to_array($bcc);
00311                 $bcc = $this->clean_email($bcc);
00312 
00313                 if ($this->validate)
00314                 {
00315                         $this->validate_email($bcc);
00316                 }
00317 
00318                 if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
00319                 {
00320                         $this->_bcc_array = $bcc;
00321                 }
00322                 else
00323                 {
00324                         $this->_set_header('Bcc', implode(", ", $bcc));
00325                 }
00326         }
00327         
00328         // --------------------------------------------------------------------
00329 
00330         /**
00331          * Set Email Subject
00332          *
00333          * @access      public
00334          * @param       string
00335          * @return      void
00336          */     
00337         function subject($subject)
00338         {
00339                 if (strpos($subject, "\r") !== FALSE OR strpos($subject, "\n") !== FALSE)
00340                 {
00341                         $subject = str_replace(array("\r\n", "\r", "\n"), '', $subject);                        
00342                 }
00343 
00344                 if (strpos($subject, "\t"))
00345                 {
00346                         $subject = str_replace("\t", ' ', $subject);
00347                 }
00348 
00349                 $this->_set_header('Subject', trim($subject));
00350         }
00351         
00352         // --------------------------------------------------------------------
00353 
00354         /**
00355          * Set Body
00356          *
00357          * @access      public
00358          * @param       string
00359          * @return      void
00360          */     
00361         function message($body)
00362         {
00363                 $this->_body = stripslashes(rtrim(str_replace("\r", "", $body)));       
00364         }       
00365         
00366         // --------------------------------------------------------------------
00367 
00368         /**
00369          * Assign file attachments
00370          *
00371          * @access      public
00372          * @param       string
00373          * @return      string
00374          */
00375         function attach($filename, $disposition = 'attachment')
00376         {       
00377                 $this->_attach_name[] = $filename;
00378                 $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
00379                 $this->_attach_disp[] = $disposition; // Can also be 'inline'  Not sure if it matters
00380         }
00381 
00382         // --------------------------------------------------------------------
00383 
00384         /**
00385          * Add a Header Item
00386          *
00387          * @access      private
00388          * @param       string
00389          * @param       string
00390          * @return      void
00391          */     
00392         function _set_header($header, $value)
00393         {
00394                 $this->_headers[$header] = $value;
00395         }
00396         
00397         // --------------------------------------------------------------------
00398 
00399         /**
00400          * Convert a String to an Array
00401          *
00402          * @access      private
00403          * @param       string
00404          * @return      array
00405          */     
00406         function _str_to_array($email)
00407         {
00408                 if ( ! is_array($email))
00409                 {
00410                         if (strpos($email, ',') !== FALSE)
00411                         {
00412                                 $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
00413                         }
00414                         else
00415                         {
00416                                 $email = trim($email);
00417                                 settype($email, "array");
00418                         }
00419                 }
00420                 return $email;
00421         }
00422         
00423         // --------------------------------------------------------------------
00424 
00425         /**
00426          * Set Multipart Value
00427          *
00428          * @access      public
00429          * @param       string
00430          * @return      void
00431          */     
00432         function set_alt_message($str = '')
00433         {
00434                 $this->alt_message = ($str == '') ? '' : $str;
00435         }
00436         
00437         // --------------------------------------------------------------------
00438 
00439         /**
00440          * Set Mailtype
00441          *
00442          * @access      public
00443          * @param       string
00444          * @return      void
00445          */     
00446         function set_mailtype($type = 'text')
00447         {
00448                 $this->mailtype = ($type == 'html') ? 'html' : 'text';
00449         }
00450         
00451         // --------------------------------------------------------------------
00452 
00453         /**
00454          * Set Wordwrap
00455          *
00456          * @access      public
00457          * @param       string
00458          * @return      void
00459          */     
00460         function set_wordwrap($wordwrap = TRUE)
00461         {
00462                 $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
00463         }
00464         
00465         // --------------------------------------------------------------------
00466 
00467         /**
00468          * Set Protocol
00469          *
00470          * @access      public
00471          * @param       string
00472          * @return      void
00473          */     
00474         function set_protocol($protocol = 'mail')
00475         {
00476                 $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
00477         }
00478         
00479         // --------------------------------------------------------------------
00480 
00481         /**
00482          * Set Priority
00483          *
00484          * @access      public
00485          * @param       integer
00486          * @return      void
00487          */     
00488         function set_priority($n = 3)
00489         {
00490                 if ( ! is_numeric($n))
00491                 {
00492                         $this->priority = 3;
00493                         return;
00494                 }
00495         
00496                 if ($n < 1 OR $n > 5)
00497                 {
00498                         $this->priority = 3;
00499                         return;
00500                 }
00501         
00502                 $this->priority = $n;
00503         }
00504         
00505         // --------------------------------------------------------------------
00506 
00507         /**
00508          * Set Newline Character
00509          *
00510          * @access      public
00511          * @param       string
00512          * @return      void
00513          */     
00514         function set_newline($newline = "\n")
00515         {
00516                 if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
00517                 {
00518                         $this->newline  = "\n"; 
00519                         return;
00520                 }
00521         
00522                 $this->newline  = $newline;     
00523         }
00524         
00525         // --------------------------------------------------------------------
00526 
00527         /**
00528          * Set CRLF
00529          *
00530          * @access      public
00531          * @param       string
00532          * @return      void
00533          */     
00534         function set_crlf($crlf = "\n")
00535         {
00536                 if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
00537                 {
00538                         $this->crlf     = "\n"; 
00539                         return;
00540                 }
00541         
00542                 $this->crlf     = $crlf;        
00543         }
00544         
00545         // --------------------------------------------------------------------
00546 
00547         /**
00548          * Set Message Boundary
00549          *
00550          * @access      private
00551          * @return      void
00552          */     
00553         function _set_boundaries()
00554         {
00555                 $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
00556                 $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
00557         }
00558         
00559         // --------------------------------------------------------------------
00560 
00561         /**
00562          * Get the Message ID
00563          *
00564          * @access      private
00565          * @return      string
00566          */     
00567         function _get_message_id()
00568         {
00569                 $from = $this->_headers['Return-Path'];
00570                 $from = str_replace(">", "", $from);
00571                 $from = str_replace("<", "", $from);
00572         
00573                 return  "<".uniqid('').strstr($from, '@').">";  
00574         }
00575         
00576         // --------------------------------------------------------------------
00577 
00578         /**
00579          * Get Mail Protocol
00580          *
00581          * @access      private
00582          * @param       bool
00583          * @return      string
00584          */     
00585         function _get_protocol($return = TRUE)
00586         {
00587                 $this->protocol = strtolower($this->protocol);
00588                 $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
00589 
00590                 if ($return == TRUE)
00591                 {
00592                         return $this->protocol;
00593                 }
00594         }
00595         
00596         // --------------------------------------------------------------------
00597 
00598         /**
00599          * Get Mail Encoding
00600          *
00601          * @access      private
00602          * @param       bool
00603          * @return      string
00604          */     
00605         function _get_encoding($return = TRUE)
00606         {
00607                 $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
00608 
00609                 foreach ($this->_base_charsets as $charset)
00610                 {
00611                         if (strncmp($charset, $this->charset, strlen($charset)) == 0)
00612                         {
00613                                 $this->_encoding = '7bit';
00614                         }
00615                 }
00616         
00617                 if ($return == TRUE)
00618                 {
00619                         return $this->_encoding;        
00620                 }
00621         }
00622 
00623         // --------------------------------------------------------------------
00624 
00625         /**
00626          * Get content type (text/html/attachment)
00627          *
00628          * @access      private
00629          * @return      string
00630          */     
00631         function _get_content_type()
00632         {       
00633                 if      ($this->mailtype == 'html' &&  count($this->_attach_name) == 0)
00634                 {
00635                         return 'html';
00636                 }
00637                 elseif  ($this->mailtype == 'html' &&  count($this->_attach_name)  > 0)
00638                 {
00639                         return 'html-attach';
00640                 }
00641                 elseif  ($this->mailtype == 'text' &&  count($this->_attach_name)  > 0)
00642                 {
00643                         return 'plain-attach';
00644                 }
00645                 else
00646                 {
00647                         return 'plain';
00648                 }
00649         }
00650         
00651         // --------------------------------------------------------------------
00652 
00653         /**
00654          * Set RFC 822 Date
00655          *
00656          * @access      private
00657          * @return      string
00658          */     
00659         function _set_date()
00660         {
00661                 $timezone = date("Z");
00662                 $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
00663                 $timezone = abs($timezone);
00664                 $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60;
00665 
00666                 return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
00667         }
00668         
00669         // --------------------------------------------------------------------
00670 
00671         /**
00672          * Mime message
00673          *
00674          * @access      private
00675          * @return      string
00676          */     
00677         function _get_mime_message()
00678         {
00679                 return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
00680         }
00681         
00682         // --------------------------------------------------------------------
00683 
00684         /**
00685          * Validate Email Address
00686          *
00687          * @access      public
00688          * @param       string
00689          * @return      bool
00690          */     
00691         function validate_email($email)
00692         {       
00693                 if ( ! is_array($email))
00694                 {
00695                         $this->_set_error_message('email_must_be_array');
00696                         return FALSE;
00697                 }
00698 
00699                 foreach ($email as $val)
00700                 {
00701                         if ( ! $this->valid_email($val))
00702                         {
00703                                 $this->_set_error_message('email_invalid_address', $val);
00704                                 return FALSE;
00705                         }
00706                 }
00707         }       
00708         
00709         // --------------------------------------------------------------------
00710 
00711         /**
00712          * Email Validation
00713          *
00714          * @access      public
00715          * @param       string
00716          * @return      bool
00717          */     
00718         function valid_email($address)
00719         {
00720                 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
00721         }
00722         
00723         // --------------------------------------------------------------------
00724 
00725         /**
00726          * Clean Extended Email Address: Joe Smith <joe@smith.com>
00727          *
00728          * @access      public
00729          * @param       string
00730          * @return      string
00731          */     
00732         function clean_email($email)
00733         {
00734                 if ( ! is_array($email))
00735                 {
00736                         if (preg_match('/<(.*)>/', $email, $match))
00737                         {
00738                                 return $match['1'];
00739                         }
00740                         else
00741                         {
00742                                 return $email;
00743                         }
00744                 }
00745         
00746                 $clean_email = array();
00747 
00748                 foreach ($email as $addy)
00749                 {
00750                         if (preg_match( '/<(.*)>/', $addy, $match))
00751                         {
00752                                 $clean_email[] = $match['1'];
00753                         }
00754                         else
00755                         {
00756                                 $clean_email[] = $addy; 
00757                         }
00758                 }
00759 
00760                 return $clean_email;
00761         }
00762         
00763         // --------------------------------------------------------------------
00764 
00765         /**
00766          * Build alternative plain text message
00767          *
00768          * This function provides the raw message for use
00769          * in plain-text headers of HTML-formatted emails.
00770          * If the user hasn't specified his own alternative message
00771          * it creates one by stripping the HTML
00772          *
00773          * @access      private
00774          * @return      string
00775          */     
00776         function _get_alt_message()
00777         {
00778                 if ($this->alt_message != "")
00779                 {
00780                         return $this->word_wrap($this->alt_message, '76');
00781                 }
00782 
00783                 if (preg_match('/<body.*?>(.*)<\/body>/si', $this->_body, $match))
00784                 {
00785                         $body = $match['1'];
00786                 }
00787                 else
00788                 {
00789                         $body = $this->_body;
00790                 }
00791 
00792                 $body = trim(strip_tags($body));
00793                 $body = preg_replace( '#<!--(.*)-->#', "", $body);
00794                 $body = str_replace("\t", "", $body);
00795 
00796                 for ($i = 20; $i >= 3; $i--)
00797                 {
00798                         $n = "";
00799         
00800                         for ($x = 1; $x <= $i; $x ++)
00801                         {
00802                                  $n .= "\n";
00803                         }
00804 
00805                         $body = str_replace($n, "\n\n", $body); 
00806                 }
00807 
00808                 return $this->word_wrap($body, '76');
00809         }
00810         
00811         // --------------------------------------------------------------------
00812 
00813         /**
00814          * Word Wrap
00815          *
00816          * @access      public
00817          * @param       string
00818          * @param       integer
00819          * @return      string
00820          */     
00821         function word_wrap($str, $charlim = '')
00822         {
00823                 // Se the character limit
00824                 if ($charlim == '')
00825                 {
00826                         $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
00827                 }
00828 
00829                 // Reduce multiple spaces
00830                 $str = preg_replace("| +|", " ", $str);
00831 
00832                 // Standardize newlines
00833                 if (strpos($str, "\r") !== FALSE)
00834                 {
00835                         $str = str_replace(array("\r\n", "\r"), "\n", $str);                    
00836                 }
00837 
00838                 // If the current word is surrounded by {unwrap} tags we'll 
00839                 // strip the entire chunk and replace it with a marker.
00840                 $unwrap = array();
00841                 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
00842                 {
00843                         for ($i = 0; $i < count($matches['0']); $i++)
00844                         {
00845                                 $unwrap[] = $matches['1'][$i];
00846                                 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
00847                         }
00848                 }
00849 
00850                 // Use PHP's native function to do the initial wordwrap.  
00851                 // We set the cut flag to FALSE so that any individual words that are 
00852                 // too long get left alone.  In the next step we'll deal with them.
00853                 $str = wordwrap($str, $charlim, "\n", FALSE);
00854 
00855                 // Split the string into individual lines of text and cycle through them
00856                 $output = "";
00857                 foreach (explode("\n", $str) as $line) 
00858                 {
00859                         // Is the line within the allowed character count?
00860                         // If so we'll join it to the output and continue
00861                         if (strlen($line) <= $charlim)
00862                         {
00863                                 $output .= $line.$this->newline;        
00864                                 continue;
00865                         }
00866 
00867                         $temp = '';
00868                         while((strlen($line)) > $charlim) 
00869                         {
00870                                 // If the over-length word is a URL we won't wrap it
00871                                 if (preg_match("!\[url.+\]|://|wwww.!", $line))
00872                                 {
00873                                         break;
00874                                 }
00875 
00876                                 // Trim the word down
00877                                 $temp .= substr($line, 0, $charlim-1);
00878                                 $line = substr($line, $charlim-1);
00879                         }
00880         
00881                         // If $temp contains data it means we had to split up an over-length 
00882                         // word into smaller chunks so we'll add it back to our current line
00883                         if ($temp != '')
00884                         {
00885                                 $output .= $temp.$this->newline.$line;
00886                         }
00887                         else
00888                         {
00889                                 $output .= $line;
00890                         }
00891 
00892                         $output .= $this->newline;
00893                 }
00894 
00895                 // Put our markers back
00896                 if (count($unwrap) > 0)
00897                 {       
00898                         foreach ($unwrap as $key => $val)
00899                         {
00900                                 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
00901                         }
00902                 }
00903 
00904                 return $output; 
00905         }
00906         
00907         // --------------------------------------------------------------------
00908 
00909         /**
00910          * Build final headers
00911          *
00912          * @access      private
00913          * @param       string
00914          * @return      string
00915          */     
00916         function _build_headers()
00917         {
00918                 $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
00919                 $this->_set_header('X-Mailer', $this->useragent);
00920                 $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
00921                 $this->_set_header('Message-ID', $this->_get_message_id());
00922                 $this->_set_header('Mime-Version', '1.0');
00923         }
00924         
00925         // --------------------------------------------------------------------
00926 
00927         /**
00928          * Write Headers as a string
00929          *
00930          * @access      private
00931          * @return      void
00932          */
00933         function _write_headers()
00934         {
00935                 if ($this->protocol == 'mail')
00936                 {
00937                         $this->_subject = $this->_headers['Subject'];
00938                         unset($this->_headers['Subject']);
00939                 }       
00940 
00941                 reset($this->_headers);
00942                 $this->_header_str = "";
00943 
00944                 foreach($this->_headers as $key => $val)
00945                 {
00946                         $val = trim($val);
00947 
00948                         if ($val != "")
00949                         {
00950                                 $this->_header_str .= $key.": ".$val.$this->newline;
00951                         }
00952                 }
00953 
00954                 if ($this->_get_protocol() == 'mail')
00955                 {
00956                         $this->_header_str = substr($this->_header_str, 0, -1);
00957                 }
00958         }
00959         
00960         // --------------------------------------------------------------------
00961 
00962         /**
00963          * Build Final Body and attachments
00964          *
00965          * @access      private
00966          * @return      void
00967          */     
00968         function _build_message()
00969         {
00970                 if ($this->wordwrap === TRUE  AND  $this->mailtype != 'html')
00971                 {
00972                         $this->_body = $this->word_wrap($this->_body);
00973                 }
00974         
00975                 $this->_set_boundaries();
00976                 $this->_write_headers();
00977 
00978                 $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : '';
00979         
00980                 switch ($this->_get_content_type())
00981                 {
00982                         case 'plain' :
00983         
00984                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
00985                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
00986 
00987                                 if ($this->_get_protocol() == 'mail')
00988                                 {
00989                                         $this->_header_str .= $hdr;
00990                                         $this->_finalbody = $this->_body;
00991         
00992                                         return;
00993                                 }
00994 
00995                                 $hdr .= $this->newline . $this->newline . $this->_body;
00996 
00997                                 $this->_finalbody = $hdr;
00998                                 return;
00999         
01000                         break;
01001                         case 'html' :
01002         
01003                                 if ($this->send_multipart === FALSE)
01004                                 {
01005                                         $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
01006                                         $hdr .= "Content-Transfer-Encoding: quoted-printable";
01007                                 }
01008                                 else
01009                                 {       
01010                                         $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline;
01011                                         $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
01012                                         $hdr .= "--" . $this->_alt_boundary . $this->newline;
01013         
01014                                         $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
01015                                         $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
01016                                         $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
01017 
01018                                         $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
01019                                         $hdr .= "Content-Transfer-Encoding: quoted-printable";
01020                                 }
01021 
01022                                 $this->_body = $this->_prep_quoted_printable($this->_body);
01023 
01024                                 if ($this->_get_protocol() == 'mail')
01025                                 {
01026                                         $this->_header_str .= $hdr;
01027                                         $this->_finalbody = $this->_body . $this->newline . $this->newline;
01028         
01029                                         if ($this->send_multipart !== FALSE)
01030                                         {
01031                                                 $this->_finalbody .= "--" . $this->_alt_boundary . "--";
01032                                         }
01033         
01034                                         return;
01035                                 }
01036 
01037                                 $hdr .= $this->newline . $this->newline;
01038                                 $hdr .= $this->_body . $this->newline . $this->newline;
01039 
01040                                 if ($this->send_multipart !== FALSE)
01041                                 {
01042                                         $hdr .= "--" . $this->_alt_boundary . "--";
01043                                 }
01044 
01045                                 $this->_finalbody = $hdr;
01046                                 return;
01047 
01048                         break;
01049                         case 'plain-attach' :
01050         
01051                                 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
01052                                 $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
01053                                 $hdr .= "--" . $this->_atc_boundary . $this->newline;
01054         
01055                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
01056                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
01057 
01058                                 if ($this->_get_protocol() == 'mail')
01059                                 {
01060                                         $this->_header_str .= $hdr;
01061         
01062                                         $body  = $this->_body . $this->newline . $this->newline;
01063                                 }
01064 
01065                                 $hdr .= $this->newline . $this->newline;
01066                                 $hdr .= $this->_body . $this->newline . $this->newline;
01067 
01068                         break;
01069                         case 'html-attach' :
01070         
01071                                 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
01072                                 $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
01073                                 $hdr .= "--" . $this->_atc_boundary . $this->newline;
01074         
01075                                 $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
01076                                 $hdr .= "--" . $this->_alt_boundary . $this->newline;
01077 
01078                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
01079                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
01080                                 $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
01081         
01082                                 $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
01083                                 $hdr .= "Content-Transfer-Encoding: quoted-printable";
01084 
01085                                 $this->_body = $this->_prep_quoted_printable($this->_body);
01086 
01087                                 if ($this->_get_protocol() == 'mail')
01088                                 {
01089                                         $this->_header_str .= $hdr;     
01090         
01091                                         $body  = $this->_body . $this->newline . $this->newline;
01092                                         $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
01093                                 }
01094 
01095                                 $hdr .= $this->newline . $this->newline;
01096                                 $hdr .= $this->_body . $this->newline . $this->newline;
01097                                 $hdr .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
01098 
01099                         break;
01100                 }
01101 
01102                 $attachment = array();
01103 
01104                 $z = 0;
01105 
01106                 for ($i=0; $i < count($this->_attach_name); $i++)
01107                 {
01108                         $filename = $this->_attach_name[$i];
01109                         $basename = basename($filename);
01110                         $ctype = $this->_attach_type[$i];
01111 
01112                         if ( ! file_exists($filename))
01113                         {
01114                                 $this->_set_error_message('email_attachment_missing', $filename);
01115                                 return FALSE;
01116                         }       
01117 
01118                         $h  = "--".$this->_atc_boundary.$this->newline;
01119                         $h .= "Content-type: ".$ctype."; ";
01120                         $h .= "name=\"".$basename."\"".$this->newline;
01121                         $h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline;
01122                         $h .= "Content-Transfer-Encoding: base64".$this->newline;
01123 
01124                         $attachment[$z++] = $h;
01125                         $file = filesize($filename) +1;
01126         
01127                         if ( ! $fp = fopen($filename, FOPEN_READ))
01128                         {
01129                                 $this->_set_error_message('email_attachment_unreadable', $filename);
01130                                 return FALSE;
01131                         }
01132         
01133                         $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
01134                         fclose($fp);
01135                 }
01136 
01137                 if ($this->_get_protocol() == 'mail')
01138                 {
01139                         $this->_finalbody = $body . implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; 
01140         
01141                         return;
01142                 }
01143 
01144                 $this->_finalbody = $hdr.implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";    
01145 
01146                 return; 
01147         }
01148         
01149         // --------------------------------------------------------------------
01150         
01151         /**
01152          * Prep Quoted Printable
01153          *
01154          * Prepares string for Quoted-Printable Content-Transfer-Encoding
01155          * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
01156          *
01157          * @access      private
01158          * @param       string
01159          * @param       integer
01160          * @return      string
01161          */
01162         function _prep_quoted_printable($str, $charlim = '')
01163         {
01164                 // Set the character limit
01165                 // Don't allow over 76, as that will make servers and MUAs barf
01166                 // all over quoted-printable data
01167                 if ($charlim == '' OR $charlim > '76')
01168                 {
01169                         $charlim = '76';
01170                 }
01171 
01172                 // Reduce multiple spaces
01173                 $str = preg_replace("| +|", " ", $str);
01174 
01175                 // kill nulls
01176                 $str = preg_replace('/\x00+/', '', $str);
01177                 
01178                 // Standardize newlines
01179                 if (strpos($str, "\r") !== FALSE)
01180                 {
01181                         $str = str_replace(array("\r\n", "\r"), "\n", $str);
01182                 }
01183 
01184                 // We are intentionally wrapping so mail servers will encode characters
01185                 // properly and MUAs will behave, so {unwrap} must go!
01186                 $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
01187 
01188                 // Break into an array of lines
01189                 $lines = explode("\n", $str);
01190 
01191                 $escape = '=';
01192                 $output = '';
01193 
01194                 foreach ($lines as $line)
01195                 {
01196                         $length = strlen($line);
01197                         $temp = '';
01198 
01199                         // Loop through each character in the line to add soft-wrap
01200                         // characters at the end of a line " =\r\n" and add the newly
01201                         // processed line(s) to the output (see comment on $crlf class property)
01202                         for ($i = 0; $i < $length; $i++)
01203                         {
01204                                 // Grab the next character
01205                                 $char = substr($line, $i, 1);
01206                                 $ascii = ord($char);
01207 
01208                                 // Convert spaces and tabs but only if it's the end of the line
01209                                 if ($i == ($length - 1))
01210                                 {
01211                                         $char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char;
01212                                 }
01213 
01214                                 // encode = signs
01215                                 if ($ascii == '61')
01216                                 {
01217                                         $char = $escape.strtoupper(sprintf('%02s', dechex($ascii)));  // =3D
01218                                 }
01219 
01220                                 // If we're at the character limit, add the line to the output,
01221                                 // reset our temp variable, and keep on chuggin'
01222                                 if ((strlen($temp) + strlen($char)) >= $charlim)
01223                                 {
01224                                         $output .= $temp.$escape.$this->crlf;
01225                                         $temp = '';
01226                                 }
01227 
01228                                 // Add the character to our temporary line
01229                                 $temp .= $char;
01230                         }
01231 
01232                         // Add our completed line to the output
01233                         $output .= $temp.$this->crlf;
01234                 }
01235 
01236                 // get rid of extra CRLF tacked onto the end
01237                 $output = substr($output, 0, strlen($this->crlf) * -1);
01238 
01239                 return $output;
01240         }
01241 
01242         // --------------------------------------------------------------------
01243         
01244         /**
01245          * Send Email
01246          *
01247          * @access      public
01248          * @return      bool
01249          */     
01250         function send()
01251         {       
01252                 if ($this->_replyto_flag == FALSE)
01253                 {
01254                         $this->reply_to($this->_headers['From']);
01255                 }
01256         
01257                 if (( ! isset($this->_recipients) AND ! isset($this->_headers['To']))  AND
01258                         ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND
01259                         ( ! isset($this->_headers['Cc'])))
01260                 {
01261                         $this->_set_error_message('email_no_recipients');
01262                         return FALSE;
01263                 }
01264 
01265                 $this->_build_headers();
01266 
01267                 if ($this->bcc_batch_mode  AND  count($this->_bcc_array) > 0)
01268                 {
01269                         if (count($this->_bcc_array) > $this->bcc_batch_size)
01270                                 return $this->batch_bcc_send();
01271                 }
01272 
01273                 $this->_build_message();
01274 
01275                 if ( ! $this->_spool_email())
01276                 {
01277                         return FALSE;
01278                 }
01279                 else
01280                 {
01281                         return TRUE;
01282                 }
01283         }
01284         
01285         // --------------------------------------------------------------------
01286 
01287         /**
01288          * Batch Bcc Send.  Sends groups of BCCs in batches
01289          *
01290          * @access      public
01291          * @return      bool
01292          */     
01293         function batch_bcc_send()
01294         {
01295                 $float = $this->bcc_batch_size -1;
01296 
01297                 $set = "";
01298 
01299                 $chunk = array();
01300 
01301                 for ($i = 0; $i < count($this->_bcc_array); $i++)
01302                 {
01303                         if (isset($this->_bcc_array[$i]))
01304                         {
01305                                 $set .= ", ".$this->_bcc_array[$i];
01306                         }
01307 
01308                         if ($i == $float)
01309                         {       
01310                                 $chunk[] = substr($set, 1);
01311                                 $float = $float + $this->bcc_batch_size;
01312                                 $set = "";
01313                         }
01314         
01315                         if ($i == count($this->_bcc_array)-1)
01316                         {
01317                                 $chunk[] = substr($set, 1);
01318                         }
01319                 }
01320 
01321                 for ($i = 0; $i < count($chunk); $i++)
01322                 {
01323                         unset($this->_headers['Bcc']);
01324                         unset($bcc);
01325 
01326                         $bcc = $this->_str_to_array($chunk[$i]);
01327                         $bcc = $this->clean_email($bcc);
01328         
01329                         if ($this->protocol != 'smtp')
01330                         {
01331                                 $this->_set_header('Bcc', implode(", ", $bcc));
01332                         }
01333                         else
01334                         {
01335                                 $this->_bcc_array = $bcc;
01336                         }
01337         
01338                         $this->_build_message();
01339                         $this->_spool_email();
01340                 }
01341         }
01342         
01343         // --------------------------------------------------------------------
01344 
01345         /**
01346          * Unwrap special elements
01347          *
01348          * @access      private
01349          * @return      void
01350          */     
01351         function _unwrap_specials()
01352         {
01353                 $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
01354         }
01355         
01356         // --------------------------------------------------------------------
01357 
01358         /**
01359          * Strip line-breaks via callback
01360          *
01361          * @access      private
01362          * @return      string
01363          */     
01364         function _remove_nl_callback($matches)
01365         {
01366                 if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
01367                 {
01368                         $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]);
01369                 }
01370                 
01371                 return $matches[1];
01372         }
01373         
01374         // --------------------------------------------------------------------
01375 
01376         /**
01377          * Spool mail to the mail server
01378          *
01379          * @access      private
01380          * @return      bool
01381          */     
01382         function _spool_email()
01383         {
01384                 $this->_unwrap_specials();
01385 
01386                 switch ($this->_get_protocol())
01387                 {
01388                         case 'mail'     :
01389         
01390                                         if ( ! $this->_send_with_mail())
01391                                         {
01392                                                 $this->_set_error_message('email_send_failure_phpmail');        
01393                                                 return FALSE;
01394                                         }
01395                         break;
01396                         case 'sendmail' :
01397                 
01398                                         if ( ! $this->_send_with_sendmail())
01399                                         {
01400                                                 $this->_set_error_message('email_send_failure_sendmail');       
01401                                                 return FALSE;
01402                                         }
01403                         break;
01404                         case 'smtp'     :
01405                 
01406                                         if ( ! $this->_send_with_smtp())
01407                                         {
01408                                                 $this->_set_error_message('email_send_failure_smtp');   
01409                                                 return FALSE;
01410                                         }
01411                         break;
01412 
01413                 }
01414 
01415                 $this->_set_error_message('email_sent', $this->_get_protocol());
01416                 return TRUE;
01417         }       
01418         
01419         // --------------------------------------------------------------------
01420 
01421         /**
01422          * Send using mail()
01423          *
01424          * @access      private
01425          * @return      bool
01426          */     
01427         function _send_with_mail()
01428         {       
01429                 if ($this->_safe_mode == TRUE)
01430                 {
01431                         if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str))
01432                         {
01433                                 return FALSE;
01434                         }
01435                         else
01436                         {
01437                                 return TRUE;
01438                         }
01439                 }
01440                 else
01441                 {
01442                         // most documentation of sendmail using the "-f" flag lacks a space after it, however
01443                         // we've encountered servers that seem to require it to be in place.
01444                         if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
01445                         {
01446                                 return FALSE;
01447                         }
01448                         else
01449                         {
01450                                 return TRUE;
01451                         }
01452                 }
01453         }
01454         
01455         // --------------------------------------------------------------------
01456 
01457         /**
01458          * Send using Sendmail
01459          *
01460          * @access      private
01461          * @return      bool
01462          */     
01463         function _send_with_sendmail()
01464         {
01465                 $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
01466 
01467                 if ( ! is_resource($fp))
01468                 {               
01469                         $this->_set_error_message('email_no_socket');
01470                         return FALSE;
01471                 }
01472 
01473                 fputs($fp, $this->_header_str);
01474                 fputs($fp, $this->_finalbody);
01475                 pclose($fp) >> 8 & 0xFF;
01476 
01477                 return TRUE;
01478         }
01479         
01480         // --------------------------------------------------------------------
01481 
01482         /**
01483          * Send using SMTP
01484          *
01485          * @access      private
01486          * @return      bool
01487          */     
01488         function _send_with_smtp()
01489         {       
01490                 if ($this->smtp_host == '')
01491                 {       
01492                         $this->_set_error_message('email_no_hostname');
01493                         return FALSE;
01494                 }
01495 
01496                 $this->_smtp_connect();
01497                 $this->_smtp_authenticate();
01498 
01499                 $this->_send_command('from', $this->clean_email($this->_headers['From']));
01500 
01501                 foreach($this->_recipients as $val)
01502                 {
01503                         $this->_send_command('to', $val);
01504                 }
01505         
01506                 if (count($this->_cc_array) > 0)
01507                 {
01508                         foreach($this->_cc_array as $val)
01509                         {
01510                                 if ($val != "")
01511                                 {
01512                                         $this->_send_command('to', $val);
01513                                 }
01514                         }
01515                 }
01516 
01517                 if (count($this->_bcc_array) > 0)
01518                 {
01519                         foreach($this->_bcc_array as $val)
01520                         {
01521                                 if ($val != "")
01522                                 {
01523                                         $this->_send_command('to', $val);
01524                                 }
01525                         }
01526                 }
01527 
01528                 $this->_send_command('data');
01529 
01530                 // perform dot transformation on any lines that begin with a dot
01531                 $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
01532 
01533                 $this->_send_data('.');
01534 
01535                 $reply = $this->_get_smtp_data();
01536 
01537                 $this->_set_error_message($reply);      
01538 
01539                 if (strncmp($reply, '250', 3) != 0)
01540                 {
01541                         $this->_set_error_message('email_smtp_error', $reply);  
01542                         return FALSE;
01543                 }
01544 
01545                 $this->_send_command('quit');
01546                 return TRUE;
01547         }       
01548         
01549         // --------------------------------------------------------------------
01550 
01551         /**
01552          * SMTP Connect
01553          *
01554          * @access      private
01555          * @param       string
01556          * @return      string
01557          */     
01558         function _smtp_connect()
01559         {
01560                 $this->_smtp_connect = fsockopen($this->smtp_host,
01561                                                                                 $this->smtp_port,
01562                                                                                 $errno,
01563                                                                                 $errstr,
01564                                                                                 $this->smtp_timeout);
01565 
01566                 if( ! is_resource($this->_smtp_connect))
01567                 {               
01568                         $this->_set_error_message('email_smtp_error', $errno." ".$errstr);
01569                         return FALSE;
01570                 }
01571 
01572                 $this->_set_error_message($this->_get_smtp_data());
01573                 return $this->_send_command('hello');
01574         }
01575         
01576         // --------------------------------------------------------------------
01577 
01578         /**
01579          * Send SMTP command
01580          *
01581          * @access      private
01582          * @param       string
01583          * @param       string
01584          * @return      string
01585          */     
01586         function _send_command($cmd, $data = '')
01587         {
01588                 switch ($cmd)
01589                 {
01590                         case 'hello' :
01591 
01592                                         if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
01593                                                 $this->_send_data('EHLO '.$this->_get_hostname());
01594                                         else
01595                                                 $this->_send_data('HELO '.$this->_get_hostname());
01596 
01597                                                 $resp = 250;
01598                         break;
01599                         case 'from' :
01600         
01601                                                 $this->_send_data('MAIL FROM:<'.$data.'>');
01602 
01603                                                 $resp = 250;
01604                         break;
01605                         case 'to'       :
01606         
01607                                                 $this->_send_data('RCPT TO:<'.$data.'>');
01608 
01609                                                 $resp = 250;    
01610                         break;
01611                         case 'data'     :
01612         
01613                                                 $this->_send_data('DATA');
01614 
01615                                                 $resp = 354;    
01616                         break;
01617                         case 'quit'     :
01618 
01619                                                 $this->_send_data('QUIT');
01620 
01621                                                 $resp = 221;
01622                         break;
01623                 }
01624 
01625                 $reply = $this->_get_smtp_data();       
01626 
01627                 $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
01628 
01629                 if (substr($reply, 0, 3) != $resp)
01630                 {
01631                         $this->_set_error_message('email_smtp_error', $reply);
01632                         return FALSE;
01633                 }
01634         
01635                 if ($cmd == 'quit')
01636                 {
01637                         fclose($this->_smtp_connect);
01638                 }
01639         
01640                 return TRUE;
01641         }
01642         
01643         // --------------------------------------------------------------------
01644 
01645         /**
01646          *  SMTP Authenticate
01647          *
01648          * @access      private
01649          * @return      bool
01650          */     
01651         function _smtp_authenticate()
01652         {       
01653                 if ( ! $this->_smtp_auth)
01654                 {
01655                         return TRUE;
01656                 }
01657         
01658                 if ($this->smtp_user == ""  AND  $this->smtp_pass == "")
01659                 {
01660                         $this->_set_error_message('email_no_smtp_unpw');
01661                         return FALSE;
01662                 }
01663 
01664                 $this->_send_data('AUTH LOGIN');
01665 
01666                 $reply = $this->_get_smtp_data();       
01667 
01668                 if (strncmp($reply, '334', 3) != 0)
01669                 {
01670                         $this->_set_error_message('email_failed_smtp_login', $reply);   
01671                         return FALSE;
01672                 }
01673 
01674                 $this->_send_data(base64_encode($this->smtp_user));
01675 
01676                 $reply = $this->_get_smtp_data();       
01677 
01678                 if (strncmp($reply, '334', 3) != 0)
01679                 {
01680                         $this->_set_error_message('email_smtp_auth_un', $reply);        
01681                         return FALSE;
01682                 }
01683 
01684                 $this->_send_data(base64_encode($this->smtp_pass));
01685 
01686                 $reply = $this->_get_smtp_data();       
01687 
01688                 if (strncmp($reply, '235', 3) != 0)
01689                 {
01690                         $this->_set_error_message('email_smtp_auth_pw', $reply);        
01691                         return FALSE;
01692                 }
01693         
01694                 return TRUE;
01695         }
01696         
01697         // --------------------------------------------------------------------
01698 
01699         /**
01700          * Send SMTP data
01701          *
01702          * @access      private
01703          * @return      bool
01704          */     
01705         function _send_data($data)
01706         {
01707                 if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
01708                 {
01709                         $this->_set_error_message('email_smtp_data_failure', $data);    
01710                         return FALSE;
01711                 }
01712                 else
01713                 {
01714                         return TRUE;
01715                 }
01716         }
01717         
01718         // --------------------------------------------------------------------
01719 
01720         /**
01721          * Get SMTP data
01722          *
01723          * @access      private
01724          * @return      string
01725          */     
01726         function _get_smtp_data()
01727         {
01728                 $data = "";
01729 
01730                 while ($str = fgets($this->_smtp_connect, 512))
01731                 {
01732                         $data .= $str;
01733         
01734                         if (substr($str, 3, 1) == " ")
01735                         {
01736                                 break;
01737                         }
01738                 }
01739 
01740                 return $data;
01741         }
01742         
01743         // --------------------------------------------------------------------
01744 
01745         /**
01746          * Get Hostname
01747          *
01748          * @access      private
01749          * @return      string
01750          */
01751         function _get_hostname()
01752         {       
01753                 return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';    
01754         }
01755         
01756         // --------------------------------------------------------------------
01757 
01758         /**
01759          * Get IP
01760          *
01761          * @access      private
01762          * @return      string
01763          */
01764         function _get_ip()
01765         {
01766                 if ($this->_IP !== FALSE)
01767                 {
01768                         return $this->_IP;
01769                 }
01770         
01771                 $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
01772                 $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE;
01773                 $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
01774         
01775                 if ($cip && $rip)       $this->_IP = $cip;      
01776                 elseif ($rip)           $this->_IP = $rip;
01777                 elseif ($cip)           $this->_IP = $cip;
01778                 elseif ($fip)           $this->_IP = $fip;
01779 
01780                 if (strstr($this->_IP, ','))
01781                 {
01782                         $x = explode(',', $this->_IP);
01783                         $this->_IP = end($x);
01784                 }
01785 
01786                 if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP))
01787                 {
01788                         $this->_IP = '0.0.0.0';
01789                 }
01790 
01791                 unset($cip);
01792                 unset($rip);
01793                 unset($fip);
01794 
01795                 return $this->_IP;
01796         }
01797         
01798         // --------------------------------------------------------------------
01799 
01800         /**
01801          * Get Debug Message
01802          *
01803          * @access      public
01804          * @return      string
01805          */     
01806         function print_debugger()
01807         {
01808                 $msg = '';
01809 
01810                 if (count($this->_debug_msg) > 0)
01811                 {
01812                         foreach ($this->_debug_msg as $val)
01813                         {
01814                                 $msg .= $val;
01815                         }
01816                 }
01817 
01818                 $msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';    
01819                 return $msg;
01820         }       
01821         
01822         // --------------------------------------------------------------------
01823 
01824         /**
01825          * Set Message
01826          *
01827          * @access      private
01828          * @param       string
01829          * @return      string
01830          */     
01831         function _set_error_message($msg, $val = '')
01832         {
01833                 $CI =& get_instance();
01834                 $CI->lang->load('email');
01835         
01836                 if (FALSE === ($line = $CI->lang->line($msg)))
01837                 {       
01838                         $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
01839                 }       
01840                 else
01841                 {
01842                         $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
01843                 }       
01844         }
01845         
01846         // --------------------------------------------------------------------
01847 
01848         /**
01849          * Mime Types
01850          *
01851          * @access      private
01852          * @param       string
01853          * @return      string
01854          */
01855         function _mime_types($ext = "")
01856         {
01857                 $mimes = array( 'hqx'   =>      'application/mac-binhex40',
01858                                                 'cpt'   =>      'application/mac-compactpro',
01859                                                 'doc'   =>      'application/msword',
01860                                                 'bin'   =>      'application/macbinary',
01861                                                 'dms'   =>      'application/octet-stream',
01862                                                 'lha'   =>      'application/octet-stream',
01863                                                 'lzh'   =>      'application/octet-stream',
01864                                                 'exe'   =>      'application/octet-stream',
01865                                                 'class' =>      'application/octet-stream',
01866                                                 'psd'   =>      'application/octet-stream',
01867                                                 'so'    =>      'application/octet-stream',
01868                                                 'sea'   =>      'application/octet-stream',
01869                                                 'dll'   =>      'application/octet-stream',
01870                                                 'oda'   =>      'application/oda',
01871                                                 'pdf'   =>      'application/pdf',
01872                                                 'ai'    =>      'application/postscript',
01873                                                 'eps'   =>      'application/postscript',
01874                                                 'ps'    =>      'application/postscript',
01875                                                 'smi'   =>      'application/smil',
01876                                                 'smil'  =>      'application/smil',
01877                                                 'mif'   =>      'application/vnd.mif',
01878                                                 'xls'   =>      'application/vnd.ms-excel',
01879                                                 'ppt'   =>      'application/vnd.ms-powerpoint',
01880                                                 'wbxml' =>      'application/vnd.wap.wbxml',
01881                                                 'wmlc'  =>      'application/vnd.wap.wmlc',
01882                                                 'dcr'   =>      'application/x-director',
01883                                                 'dir'   =>      'application/x-director',
01884                                                 'dxr'   =>      'application/x-director',
01885                                                 'dvi'   =>      'application/x-dvi',
01886                                                 'gtar'  =>      'application/x-gtar',
01887                                                 'php'   =>      'application/x-httpd-php',
01888                                                 'php4'  =>      'application/x-httpd-php',
01889                                                 'php3'  =>      'application/x-httpd-php',
01890                                                 'phtml' =>      'application/x-httpd-php',
01891                                                 'phps'  =>      'application/x-httpd-php-source',
01892                                                 'js'    =>      'application/x-javascript',
01893                                                 'swf'   =>      'application/x-shockwave-flash',
01894                                                 'sit'   =>      'application/x-stuffit',
01895                                                 'tar'   =>      'application/x-tar',
01896                                                 'tgz'   =>      'application/x-tar',
01897                                                 'xhtml' =>      'application/xhtml+xml',
01898                                                 'xht'   =>      'application/xhtml+xml',
01899                                                 'zip'   =>      'application/zip',
01900                                                 'mid'   =>      'audio/midi',
01901                                                 'midi'  =>      'audio/midi',
01902                                                 'mpga'  =>      'audio/mpeg',
01903                                                 'mp2'   =>      'audio/mpeg',
01904                                                 'mp3'   =>      'audio/mpeg',
01905                                                 'aif'   =>      'audio/x-aiff',
01906                                                 'aiff'  =>      'audio/x-aiff',
01907                                                 'aifc'  =>      'audio/x-aiff',
01908                                                 'ram'   =>      'audio/x-pn-realaudio',
01909                                                 'rm'    =>      'audio/x-pn-realaudio',
01910                                                 'rpm'   =>      'audio/x-pn-realaudio-plugin',
01911                                                 'ra'    =>      'audio/x-realaudio',
01912                                                 'rv'    =>      'video/vnd.rn-realvideo',
01913                                                 'wav'   =>      'audio/x-wav',
01914                                                 'bmp'   =>      'image/bmp',
01915                                                 'gif'   =>      'image/gif',
01916                                                 'jpeg'  =>      'image/jpeg',
01917                                                 'jpg'   =>      'image/jpeg',
01918                                                 'jpe'   =>      'image/jpeg',
01919                                                 'png'   =>      'image/png',
01920                                                 'tiff'  =>      'image/tiff',
01921                                                 'tif'   =>      'image/tiff',
01922                                                 'css'   =>      'text/css',
01923                                                 'html'  =>      'text/html',
01924                                                 'htm'   =>      'text/html',
01925                                                 'shtml' =>      'text/html',
01926                                                 'txt'   =>      'text/plain',
01927                                                 'text'  =>      'text/plain',
01928                                                 'log'   =>      'text/plain',
01929                                                 'rtx'   =>      'text/richtext',
01930                                                 'rtf'   =>      'text/rtf',
01931                                                 'xml'   =>      'text/xml',
01932                                                 'xsl'   =>      'text/xml',
01933                                                 'mpeg'  =>      'video/mpeg',
01934                                                 'mpg'   =>      'video/mpeg',
01935                                                 'mpe'   =>      'video/mpeg',
01936                                                 'qt'    =>      'video/quicktime',
01937                                                 'mov'   =>      'video/quicktime',
01938                                                 'avi'   =>      'video/x-msvideo',
01939                                                 'movie' =>      'video/x-sgi-movie',
01940                                                 'doc'   =>      'application/msword',
01941                                                 'word'  =>      'application/msword',
01942                                                 'xl'    =>      'application/excel',
01943                                                 'eml'   =>      'message/rfc822'
01944                                         );
01945 
01946                 return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)];
01947         }
01948 
01949 }
01950 // END CI_Email class
01951 
01952 /* End of file Email.php */
01953 /* Location: ./system/libraries/Email.php */