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