converted to unix-style eol
[www-register-wizard.git] / libraries / Email.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 4.3.2 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008, EllisLab, Inc.
10  * @license             http://codeigniter.com/user_guide/license.html
11  * @link                http://codeigniter.com
12  * @since               Version 1.0
13  * @filesource
14  */
15
16 // ------------------------------------------------------------------------
17
18 /**
19  * CodeIgniter Email Class
20  *
21  * Permits email to be sent using Mail, Sendmail, or SMTP.
22  *
23  * @package             CodeIgniter
24  * @subpackage  Libraries
25  * @category    Libraries
26  * @author              ExpressionEngine Dev Team
27  * @link                http://codeigniter.com/user_guide/libraries/email.html
28  */
29 class CI_Email {
30
31         var     $useragent              = "CodeIgniter";
32         var     $mailpath               = "/usr/sbin/sendmail"; // Sendmail path
33         var     $protocol               = "mail";       // mail/sendmail/smtp
34         var     $smtp_host              = "";           // SMTP Server.  Example: mail.earthlink.net
35         var     $smtp_user              = "";           // SMTP Username
36         var     $smtp_pass              = "";           // SMTP Password
37         var     $smtp_port              = "25";         // SMTP Port
38         var     $smtp_timeout   = 5;            // SMTP Timeout in seconds
39         var     $wordwrap               = TRUE;         // TRUE/FALSE  Turns word-wrap on/off
40         var     $wrapchars              = "76";         // Number of characters to wrap at.
41         var     $mailtype               = "text";       // text/html  Defines email formatting
42         var     $charset                = "utf-8";      // Default char set: iso-8859-1 or us-ascii
43         var     $multipart              = "mixed";      // "mixed" (in the body) or "related" (separate)
44         var $alt_message        = '';           // Alternative message for HTML emails
45         var     $validate               = FALSE;        // TRUE/FALSE.  Enables email validation
46         var     $priority               = "3";          // Default priority (1 - 5)
47         var     $newline                = "\n";         // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
48         var $crlf                       = "\n";         // The RFC 2045 compliant CRLF for quoted-printable is "\r\n".  Apparently some servers,
49                                                                         // even on the receiving end think they need to muck with CRLFs, so using "\n", while
50                                                                         // distasteful, is the only thing that seems to work for all environments.
51         var $send_multipart     = TRUE;         // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override.  Set to FALSE for Yahoo.     
52         var     $bcc_batch_mode = FALSE;        // TRUE/FALSE  Turns on/off Bcc batch feature
53         var     $bcc_batch_size = 200;          // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
54         var $_safe_mode         = FALSE;
55         var     $_subject               = "";
56         var     $_body                  = "";
57         var     $_finalbody             = "";
58         var     $_alt_boundary  = "";
59         var     $_atc_boundary  = "";
60         var     $_header_str    = "";
61         var     $_smtp_connect  = "";
62         var     $_encoding              = "8bit";
63         var $_IP                        = FALSE;
64         var     $_smtp_auth             = FALSE;
65         var $_replyto_flag      = FALSE;
66         var     $_debug_msg             = array();
67         var     $_recipients    = array();
68         var     $_cc_array              = array();
69         var     $_bcc_array             = array();
70         var     $_headers               = array();
71         var     $_attach_name   = array();
72         var     $_attach_type   = array();
73         var     $_attach_disp   = array();
74         var     $_protocols             = array('mail', 'sendmail', 'smtp');
75         var     $_base_charsets = array('us-ascii', 'iso-2022-');       // 7-bit charsets (excluding language suffix)
76         var     $_bit_depths    = array('7bit', '8bit');
77         var     $_priorities    = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
78
79
80         /**
81          * Constructor - Sets Email Preferences
82          *
83          * The constructor can be passed an array of config values
84          */
85         function CI_Email($config = array())
86         {       
87                 if (count($config) > 0)
88                 {
89                         $this->initialize($config);
90                 }       
91                 else
92                 {
93                         $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; 
94                         $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
95                 }
96                 
97                 log_message('debug', "Email Class Initialized");
98         }
99
100         // --------------------------------------------------------------------
101
102         /**
103          * Initialize preferences
104          *
105          * @access      public
106          * @param       array
107          * @return      void
108          */
109         function initialize($config = array())
110         {
111                 $this->clear();
112                 foreach ($config as $key => $val)
113                 {
114                         if (isset($this->$key))
115                         {
116                                 $method = 'set_'.$key;
117
118                                 if (method_exists($this, $method))
119                                 {
120                                         $this->$method($val);
121                                 }
122                                 else
123                                 {
124                                         $this->$key = $val;
125                                 }       
126                         }
127                 }
128                 
129                 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; 
130                 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
131         }
132         
133         // --------------------------------------------------------------------
134
135         /**
136          * Initialize the Email Data
137          *
138          * @access      public
139          * @return      void
140          */     
141         function clear($clear_attachments = FALSE)
142         {
143                 $this->_subject         = "";
144                 $this->_body            = "";
145                 $this->_finalbody       = "";
146                 $this->_header_str      = "";
147                 $this->_replyto_flag = FALSE;
148                 $this->_recipients      = array();
149                 $this->_headers         = array();
150                 $this->_debug_msg       = array();
151
152                 $this->_set_header('User-Agent', $this->useragent);
153                 $this->_set_header('Date', $this->_set_date());
154
155                 if ($clear_attachments !== FALSE)
156                 {
157                         $this->_attach_name = array();
158                         $this->_attach_type = array();
159                         $this->_attach_disp = array();
160                 }   
161         }
162         
163         // --------------------------------------------------------------------
164
165         /**
166          * Set FROM
167          *
168          * @access      public
169          * @param       string
170          * @param       string
171          * @return      void
172          */     
173         function from($from, $name = '')
174         {
175                 if (preg_match( '/\<(.*)\>/', $from, $match))
176                 {
177                         $from = $match['1'];
178                 }
179
180                 if ($this->validate)
181                 {
182                         $this->validate_email($this->_str_to_array($from));
183                 }
184         
185                 if ($name != '' && strncmp($name, '"', 1) != 0)
186                 {
187                         $name = '"'.$name.'"';
188                 }
189         
190                 $this->_set_header('From', $name.' <'.$from.'>');
191                 $this->_set_header('Return-Path', '<'.$from.'>');
192         }
193         
194         // --------------------------------------------------------------------
195
196         /**
197          * Set Reply-to
198          *
199          * @access      public
200          * @param       string
201          * @param       string
202          * @return      void
203          */     
204         function reply_to($replyto, $name = '')
205         {
206                 if (preg_match( '/\<(.*)\>/', $replyto, $match))
207                 {
208                         $replyto = $match['1'];
209                 }
210
211                 if ($this->validate)
212                 {
213                         $this->validate_email($this->_str_to_array($replyto));  
214                 }
215
216                 if ($name == '')
217                 {
218                         $name = $replyto;
219                 }
220
221                 if (strncmp($name, '"', 1) != 0)
222                 {
223                         $name = '"'.$name.'"';
224                 }
225
226                 $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
227                 $this->_replyto_flag = TRUE;
228         }
229         
230         // --------------------------------------------------------------------
231
232         /**
233          * Set Recipients
234          *
235          * @access      public
236          * @param       string
237          * @return      void
238          */     
239         function to($to)
240         {
241                 $to = $this->_str_to_array($to);
242                 $to = $this->clean_email($to);
243         
244                 if ($this->validate)
245                 {
246                         $this->validate_email($to);
247                 }
248         
249                 if ($this->_get_protocol() != 'mail')
250                 {
251                         $this->_set_header('To', implode(", ", $to));
252                 }
253
254                 switch ($this->_get_protocol())
255                 {
256                         case 'smtp'             : $this->_recipients = $to;
257                         break;
258                         case 'sendmail' : $this->_recipients = implode(", ", $to);
259                         break;
260                         case 'mail'             : $this->_recipients = implode(", ", $to);
261                         break;
262                 }       
263         }
264         
265         // --------------------------------------------------------------------
266
267         /**
268          * Set CC
269          *
270          * @access      public
271          * @param       string
272          * @return      void
273          */     
274         function cc($cc)
275         {       
276                 $cc = $this->_str_to_array($cc);
277                 $cc = $this->clean_email($cc);
278
279                 if ($this->validate)
280                 {
281                         $this->validate_email($cc);
282                 }
283
284                 $this->_set_header('Cc', implode(", ", $cc));
285
286                 if ($this->_get_protocol() == "smtp")
287                 {
288                         $this->_cc_array = $cc;
289                 }
290         }
291         
292         // --------------------------------------------------------------------
293
294         /**
295          * Set BCC
296          *
297          * @access      public
298          * @param       string
299          * @param       string
300          * @return      void
301          */     
302         function bcc($bcc, $limit = '')
303         {
304                 if ($limit != '' && is_numeric($limit))
305                 {
306                         $this->bcc_batch_mode = TRUE;
307                         $this->bcc_batch_size = $limit;
308                 }
309
310                 $bcc = $this->_str_to_array($bcc);
311                 $bcc = $this->clean_email($bcc);
312
313                 if ($this->validate)
314                 {
315                         $this->validate_email($bcc);
316                 }
317
318                 if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
319                 {
320                         $this->_bcc_array = $bcc;
321                 }
322                 else
323                 {
324                         $this->_set_header('Bcc', implode(", ", $bcc));
325                 }
326         }
327         
328         // --------------------------------------------------------------------
329
330         /**
331          * Set Email Subject
332          *
333          * @access      public
334          * @param       string
335          * @return      void
336          */     
337         function subject($subject)
338         {
339                 if (strpos($subject, "\r") !== FALSE OR strpos($subject, "\n") !== FALSE)
340                 {
341                         $subject = str_replace(array("\r\n", "\r", "\n"), '', $subject);                        
342                 }
343
344                 if (strpos($subject, "\t"))
345                 {
346                         $subject = str_replace("\t", ' ', $subject);
347                 }
348
349                 $this->_set_header('Subject', trim($subject));
350         }
351         
352         // --------------------------------------------------------------------
353
354         /**
355          * Set Body
356          *
357          * @access      public
358          * @param       string
359          * @return      void
360          */     
361         function message($body)
362         {
363                 $this->_body = stripslashes(rtrim(str_replace("\r", "", $body)));       
364         }       
365         
366         // --------------------------------------------------------------------
367
368         /**
369          * Assign file attachments
370          *
371          * @access      public
372          * @param       string
373          * @return      string
374          */
375         function attach($filename, $disposition = 'attachment')
376         {       
377                 $this->_attach_name[] = $filename;
378                 $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
379                 $this->_attach_disp[] = $disposition; // Can also be 'inline'  Not sure if it matters
380         }
381
382         // --------------------------------------------------------------------
383
384         /**
385          * Add a Header Item
386          *
387          * @access      private
388          * @param       string
389          * @param       string
390          * @return      void
391          */     
392         function _set_header($header, $value)
393         {
394                 $this->_headers[$header] = $value;
395         }
396         
397         // --------------------------------------------------------------------
398
399         /**
400          * Convert a String to an Array
401          *
402          * @access      private
403          * @param       string
404          * @return      array
405          */     
406         function _str_to_array($email)
407         {
408                 if ( ! is_array($email))
409                 {
410                         if (strpos($email, ',') !== FALSE)
411                         {
412                                 $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
413                         }
414                         else
415                         {
416                                 $email = trim($email);
417                                 settype($email, "array");
418                         }
419                 }
420                 return $email;
421         }
422         
423         // --------------------------------------------------------------------
424
425         /**
426          * Set Multipart Value
427          *
428          * @access      public
429          * @param       string
430          * @return      void
431          */     
432         function set_alt_message($str = '')
433         {
434                 $this->alt_message = ($str == '') ? '' : $str;
435         }
436         
437         // --------------------------------------------------------------------
438
439         /**
440          * Set Mailtype
441          *
442          * @access      public
443          * @param       string
444          * @return      void
445          */     
446         function set_mailtype($type = 'text')
447         {
448                 $this->mailtype = ($type == 'html') ? 'html' : 'text';
449         }
450         
451         // --------------------------------------------------------------------
452
453         /**
454          * Set Wordwrap
455          *
456          * @access      public
457          * @param       string
458          * @return      void
459          */     
460         function set_wordwrap($wordwrap = TRUE)
461         {
462                 $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
463         }
464         
465         // --------------------------------------------------------------------
466
467         /**
468          * Set Protocol
469          *
470          * @access      public
471          * @param       string
472          * @return      void
473          */     
474         function set_protocol($protocol = 'mail')
475         {
476                 $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
477         }
478         
479         // --------------------------------------------------------------------
480
481         /**
482          * Set Priority
483          *
484          * @access      public
485          * @param       integer
486          * @return      void
487          */     
488         function set_priority($n = 3)
489         {
490                 if ( ! is_numeric($n))
491                 {
492                         $this->priority = 3;
493                         return;
494                 }
495         
496                 if ($n < 1 OR $n > 5)
497                 {
498                         $this->priority = 3;
499                         return;
500                 }
501         
502                 $this->priority = $n;
503         }
504         
505         // --------------------------------------------------------------------
506
507         /**
508          * Set Newline Character
509          *
510          * @access      public
511          * @param       string
512          * @return      void
513          */     
514         function set_newline($newline = "\n")
515         {
516                 if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
517                 {
518                         $this->newline  = "\n"; 
519                         return;
520                 }
521         
522                 $this->newline  = $newline;     
523         }
524         
525         // --------------------------------------------------------------------
526
527         /**
528          * Set CRLF
529          *
530          * @access      public
531          * @param       string
532          * @return      void
533          */     
534         function set_crlf($crlf = "\n")
535         {
536                 if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
537                 {
538                         $this->crlf     = "\n"; 
539                         return;
540                 }
541         
542                 $this->crlf     = $crlf;        
543         }
544         
545         // --------------------------------------------------------------------
546
547         /**
548          * Set Message Boundary
549          *
550          * @access      private
551          * @return      void
552          */     
553         function _set_boundaries()
554         {
555                 $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
556                 $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
557         }
558         
559         // --------------------------------------------------------------------
560
561         /**
562          * Get the Message ID
563          *
564          * @access      private
565          * @return      string
566          */     
567         function _get_message_id()
568         {
569                 $from = $this->_headers['Return-Path'];
570                 $from = str_replace(">", "", $from);
571                 $from = str_replace("<", "", $from);
572         
573                 return  "<".uniqid('').strstr($from, '@').">";  
574         }
575         
576         // --------------------------------------------------------------------
577
578         /**
579          * Get Mail Protocol
580          *
581          * @access      private
582          * @param       bool
583          * @return      string
584          */     
585         function _get_protocol($return = TRUE)
586         {
587                 $this->protocol = strtolower($this->protocol);
588                 $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
589
590                 if ($return == TRUE)
591                 {
592                         return $this->protocol;
593                 }
594         }
595         
596         // --------------------------------------------------------------------
597
598         /**
599          * Get Mail Encoding
600          *
601          * @access      private
602          * @param       bool
603          * @return      string
604          */     
605         function _get_encoding($return = TRUE)
606         {
607                 $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
608
609                 foreach ($this->_base_charsets as $charset)
610                 {
611                         if (strncmp($charset, $this->charset, strlen($charset)) == 0)
612                         {
613                                 $this->_encoding = '7bit';
614                         }
615                 }
616         
617                 if ($return == TRUE)
618                 {
619                         return $this->_encoding;        
620                 }
621         }
622
623         // --------------------------------------------------------------------
624
625         /**
626          * Get content type (text/html/attachment)
627          *
628          * @access      private
629          * @return      string
630          */     
631         function _get_content_type()
632         {       
633                 if      ($this->mailtype == 'html' &&  count($this->_attach_name) == 0)
634                 {
635                         return 'html';
636                 }
637                 elseif  ($this->mailtype == 'html' &&  count($this->_attach_name)  > 0)
638                 {
639                         return 'html-attach';
640                 }
641                 elseif  ($this->mailtype == 'text' &&  count($this->_attach_name)  > 0)
642                 {
643                         return 'plain-attach';
644                 }
645                 else
646                 {
647                         return 'plain';
648                 }
649         }
650         
651         // --------------------------------------------------------------------
652
653         /**
654          * Set RFC 822 Date
655          *
656          * @access      private
657          * @return      string
658          */     
659         function _set_date()
660         {
661                 $timezone = date("Z");
662                 $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
663                 $timezone = abs($timezone);
664                 $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60;
665
666                 return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
667         }
668         
669         // --------------------------------------------------------------------
670
671         /**
672          * Mime message
673          *
674          * @access      private
675          * @return      string
676          */     
677         function _get_mime_message()
678         {
679                 return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
680         }
681         
682         // --------------------------------------------------------------------
683
684         /**
685          * Validate Email Address
686          *
687          * @access      public
688          * @param       string
689          * @return      bool
690          */     
691         function validate_email($email)
692         {       
693                 if ( ! is_array($email))
694                 {
695                         $this->_set_error_message('email_must_be_array');
696                         return FALSE;
697                 }
698
699                 foreach ($email as $val)
700                 {
701                         if ( ! $this->valid_email($val))
702                         {
703                                 $this->_set_error_message('email_invalid_address', $val);
704                                 return FALSE;
705                         }
706                 }
707         }       
708         
709         // --------------------------------------------------------------------
710
711         /**
712          * Email Validation
713          *
714          * @access      public
715          * @param       string
716          * @return      bool
717          */     
718         function valid_email($address)
719         {
720                 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
721         }
722         
723         // --------------------------------------------------------------------
724
725         /**
726          * Clean Extended Email Address: Joe Smith <joe@smith.com>
727          *
728          * @access      public
729          * @param       string
730          * @return      string
731          */     
732         function clean_email($email)
733         {
734                 if ( ! is_array($email))
735                 {
736                         if (preg_match('/\<(.*)\>/', $email, $match))
737                         {
738                                 return $match['1'];
739                         }
740                         else
741                         {
742                                 return $email;
743                         }
744                 }
745         
746                 $clean_email = array();
747
748                 foreach ($email as $addy)
749                 {
750                         if (preg_match( '/\<(.*)\>/', $addy, $match))
751                         {
752                                 $clean_email[] = $match['1'];
753                         }
754                         else
755                         {
756                                 $clean_email[] = $addy; 
757                         }
758                 }
759
760                 return $clean_email;
761         }
762         
763         // --------------------------------------------------------------------
764
765         /**
766          * Build alternative plain text message
767          *
768          * This function provides the raw message for use
769          * in plain-text headers of HTML-formatted emails.
770          * If the user hasn't specified his own alternative message
771          * it creates one by stripping the HTML
772          *
773          * @access      private
774          * @return      string
775          */     
776         function _get_alt_message()
777         {
778                 if ($this->alt_message != "")
779                 {
780                         return $this->word_wrap($this->alt_message, '76');
781                 }
782
783                 if (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match))
784                 {
785                         $body = $match['1'];
786                 }
787                 else
788                 {
789                         $body = $this->_body;
790                 }
791
792                 $body = trim(strip_tags($body));
793                 $body = preg_replace( '#<!--(.*)--\>#', "", $body);
794                 $body = str_replace("\t", "", $body);
795
796                 for ($i = 20; $i >= 3; $i--)
797                 {
798                         $n = "";
799         
800                         for ($x = 1; $x <= $i; $x ++)
801                         {
802                                  $n .= "\n";
803                         }
804
805                         $body = str_replace($n, "\n\n", $body); 
806                 }
807
808                 return $this->word_wrap($body, '76');
809         }
810         
811         // --------------------------------------------------------------------
812
813         /**
814          * Word Wrap
815          *
816          * @access      public
817          * @param       string
818          * @param       integer
819          * @return      string
820          */     
821         function word_wrap($str, $charlim = '')
822         {
823                 // Se the character limit
824                 if ($charlim == '')
825                 {
826                         $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
827                 }
828
829                 // Reduce multiple spaces
830                 $str = preg_replace("| +|", " ", $str);
831
832                 // Standardize newlines
833                 if (strpos($str, "\r") !== FALSE)
834                 {
835                         $str = str_replace(array("\r\n", "\r"), "\n", $str);                    
836                 }
837
838                 // If the current word is surrounded by {unwrap} tags we'll 
839                 // strip the entire chunk and replace it with a marker.
840                 $unwrap = array();
841                 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
842                 {
843                         for ($i = 0; $i < count($matches['0']); $i++)
844                         {
845                                 $unwrap[] = $matches['1'][$i];
846                                 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
847                         }
848                 }
849
850                 // Use PHP's native function to do the initial wordwrap.  
851                 // We set the cut flag to FALSE so that any individual words that are 
852                 // too long get left alone.  In the next step we'll deal with them.
853                 $str = wordwrap($str, $charlim, "\n", FALSE);
854
855                 // Split the string into individual lines of text and cycle through them
856                 $output = "";
857                 foreach (explode("\n", $str) as $line) 
858                 {
859                         // Is the line within the allowed character count?
860                         // If so we'll join it to the output and continue
861                         if (strlen($line) <= $charlim)
862                         {
863                                 $output .= $line.$this->newline;        
864                                 continue;
865                         }
866
867                         $temp = '';
868                         while((strlen($line)) > $charlim) 
869                         {
870                                 // If the over-length word is a URL we won't wrap it
871                                 if (preg_match("!\[url.+\]|://|wwww.!", $line))
872                                 {
873                                         break;
874                                 }
875
876                                 // Trim the word down
877                                 $temp .= substr($line, 0, $charlim-1);
878                                 $line = substr($line, $charlim-1);
879                         }
880         
881                         // If $temp contains data it means we had to split up an over-length 
882                         // word into smaller chunks so we'll add it back to our current line
883                         if ($temp != '')
884                         {
885                                 $output .= $temp.$this->newline.$line;
886                         }
887                         else
888                         {
889                                 $output .= $line;
890                         }
891
892                         $output .= $this->newline;
893                 }
894
895                 // Put our markers back
896                 if (count($unwrap) > 0)
897                 {       
898                         foreach ($unwrap as $key => $val)
899                         {
900                                 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
901                         }
902                 }
903
904                 return $output; 
905         }
906         
907         // --------------------------------------------------------------------
908
909         /**
910          * Build final headers
911          *
912          * @access      private
913          * @param       string
914          * @return      string
915          */     
916         function _build_headers()
917         {
918                 $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
919                 $this->_set_header('X-Mailer', $this->useragent);
920                 $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
921                 $this->_set_header('Message-ID', $this->_get_message_id());
922                 $this->_set_header('Mime-Version', '1.0');
923         }
924         
925         // --------------------------------------------------------------------
926
927         /**
928          * Write Headers as a string
929          *
930          * @access      private
931          * @return      void
932          */
933         function _write_headers()
934         {
935                 if ($this->protocol == 'mail')
936                 {
937                         $this->_subject = $this->_headers['Subject'];
938                         unset($this->_headers['Subject']);
939                 }       
940
941                 reset($this->_headers);
942                 $this->_header_str = "";
943
944                 foreach($this->_headers as $key => $val)
945                 {
946                         $val = trim($val);
947
948                         if ($val != "")
949                         {
950                                 $this->_header_str .= $key.": ".$val.$this->newline;
951                         }
952                 }
953
954                 if ($this->_get_protocol() == 'mail')
955                 {
956                         $this->_header_str = substr($this->_header_str, 0, -1);
957                 }
958         }
959         
960         // --------------------------------------------------------------------
961
962         /**
963          * Build Final Body and attachments
964          *
965          * @access      private
966          * @return      void
967          */     
968         function _build_message()
969         {
970                 if ($this->wordwrap === TRUE  AND  $this->mailtype != 'html')
971                 {
972                         $this->_body = $this->word_wrap($this->_body);
973                 }
974         
975                 $this->_set_boundaries();
976                 $this->_write_headers();
977
978                 $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : '';
979         
980                 switch ($this->_get_content_type())
981                 {
982                         case 'plain' :
983         
984                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
985                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
986
987                                 if ($this->_get_protocol() == 'mail')
988                                 {
989                                         $this->_header_str .= $hdr;
990                                         $this->_finalbody = $this->_body;
991         
992                                         return;
993                                 }
994
995                                 $hdr .= $this->newline . $this->newline . $this->_body;
996
997                                 $this->_finalbody = $hdr;
998                                 return;
999         
1000                         break;
1001                         case 'html' :
1002         
1003                                 if ($this->send_multipart === FALSE)
1004                                 {
1005                                         $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1006                                         $hdr .= "Content-Transfer-Encoding: quoted-printable";
1007                                 }
1008                                 else
1009                                 {       
1010                                         $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline;
1011                                         $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
1012                                         $hdr .= "--" . $this->_alt_boundary . $this->newline;
1013         
1014                                         $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1015                                         $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1016                                         $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1017
1018                                         $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1019                                         $hdr .= "Content-Transfer-Encoding: quoted-printable";
1020                                 }
1021
1022                                 $this->_body = $this->_prep_quoted_printable($this->_body);
1023
1024                                 if ($this->_get_protocol() == 'mail')
1025                                 {
1026                                         $this->_header_str .= $hdr;
1027                                         $this->_finalbody = $this->_body . $this->newline . $this->newline;
1028         
1029                                         if ($this->send_multipart !== FALSE)
1030                                         {
1031                                                 $this->_finalbody .= "--" . $this->_alt_boundary . "--";
1032                                         }
1033         
1034                                         return;
1035                                 }
1036
1037                                 $hdr .= $this->newline . $this->newline;
1038                                 $hdr .= $this->_body . $this->newline . $this->newline;
1039
1040                                 if ($this->send_multipart !== FALSE)
1041                                 {
1042                                         $hdr .= "--" . $this->_alt_boundary . "--";
1043                                 }
1044
1045                                 $this->_finalbody = $hdr;
1046                                 return;
1047
1048                         break;
1049                         case 'plain-attach' :
1050         
1051                                 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
1052                                 $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
1053                                 $hdr .= "--" . $this->_atc_boundary . $this->newline;
1054         
1055                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1056                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
1057
1058                                 if ($this->_get_protocol() == 'mail')
1059                                 {
1060                                         $this->_header_str .= $hdr;
1061         
1062                                         $body  = $this->_body . $this->newline . $this->newline;
1063                                 }
1064
1065                                 $hdr .= $this->newline . $this->newline;
1066                                 $hdr .= $this->_body . $this->newline . $this->newline;
1067
1068                         break;
1069                         case 'html-attach' :
1070         
1071                                 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
1072                                 $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
1073                                 $hdr .= "--" . $this->_atc_boundary . $this->newline;
1074         
1075                                 $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
1076                                 $hdr .= "--" . $this->_alt_boundary . $this->newline;
1077
1078                                 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1079                                 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1080                                 $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1081         
1082                                 $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1083                                 $hdr .= "Content-Transfer-Encoding: quoted-printable";
1084
1085                                 $this->_body = $this->_prep_quoted_printable($this->_body);
1086
1087                                 if ($this->_get_protocol() == 'mail')
1088                                 {
1089                                         $this->_header_str .= $hdr;     
1090         
1091                                         $body  = $this->_body . $this->newline . $this->newline;
1092                                         $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
1093                                 }
1094
1095                                 $hdr .= $this->newline . $this->newline;
1096                                 $hdr .= $this->_body . $this->newline . $this->newline;
1097                                 $hdr .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
1098
1099                         break;
1100                 }
1101
1102                 $attachment = array();
1103
1104                 $z = 0;
1105
1106                 for ($i=0; $i < count($this->_attach_name); $i++)
1107                 {
1108                         $filename = $this->_attach_name[$i];
1109                         $basename = basename($filename);
1110                         $ctype = $this->_attach_type[$i];
1111
1112                         if ( ! file_exists($filename))
1113                         {
1114                                 $this->_set_error_message('email_attachment_missing', $filename);
1115                                 return FALSE;
1116                         }       
1117
1118                         $h  = "--".$this->_atc_boundary.$this->newline;
1119                         $h .= "Content-type: ".$ctype."; ";
1120                         $h .= "name=\"".$basename."\"".$this->newline;
1121                         $h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline;
1122                         $h .= "Content-Transfer-Encoding: base64".$this->newline;
1123
1124                         $attachment[$z++] = $h;
1125                         $file = filesize($filename) +1;
1126         
1127                         if ( ! $fp = fopen($filename, FOPEN_READ))
1128                         {
1129                                 $this->_set_error_message('email_attachment_unreadable', $filename);
1130                                 return FALSE;
1131                         }
1132         
1133                         $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
1134                         fclose($fp);
1135                 }
1136
1137                 if ($this->_get_protocol() == 'mail')
1138                 {
1139                         $this->_finalbody = $body . implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; 
1140         
1141                         return;
1142                 }
1143
1144                 $this->_finalbody = $hdr.implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";    
1145
1146                 return; 
1147         }
1148         
1149         // --------------------------------------------------------------------
1150         
1151         /**
1152          * Prep Quoted Printable
1153          *
1154          * Prepares string for Quoted-Printable Content-Transfer-Encoding
1155          * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
1156          *
1157          * @access      private
1158          * @param       string
1159          * @param       integer
1160          * @return      string
1161          */
1162         function _prep_quoted_printable($str, $charlim = '')
1163         {
1164                 // Set the character limit
1165                 // Don't allow over 76, as that will make servers and MUAs barf
1166                 // all over quoted-printable data
1167                 if ($charlim == '' OR $charlim > '76')
1168                 {
1169                         $charlim = '76';
1170                 }
1171
1172                 // Reduce multiple spaces
1173                 $str = preg_replace("| +|", " ", $str);
1174
1175                 // kill nulls
1176                 $str = preg_replace('/\x00+/', '', $str);
1177                 
1178                 // Standardize newlines
1179                 if (strpos($str, "\r") !== FALSE)
1180                 {
1181                         $str = str_replace(array("\r\n", "\r"), "\n", $str);
1182                 }
1183
1184                 // We are intentionally wrapping so mail servers will encode characters
1185                 // properly and MUAs will behave, so {unwrap} must go!
1186                 $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
1187
1188                 // Break into an array of lines
1189                 $lines = explode("\n", $str);
1190
1191                 $escape = '=';
1192                 $output = '';
1193
1194                 foreach ($lines as $line)
1195                 {
1196                         $length = strlen($line);
1197                         $temp = '';
1198
1199                         // Loop through each character in the line to add soft-wrap
1200                         // characters at the end of a line " =\r\n" and add the newly
1201                         // processed line(s) to the output (see comment on $crlf class property)
1202                         for ($i = 0; $i < $length; $i++)
1203                         {
1204                                 // Grab the next character
1205                                 $char = substr($line, $i, 1);
1206                                 $ascii = ord($char);
1207
1208                                 // Convert spaces and tabs but only if it's the end of the line
1209                                 if ($i == ($length - 1))
1210                                 {
1211                                         $char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char;
1212                                 }
1213
1214                                 // encode = signs
1215                                 if ($ascii == '61')
1216                                 {
1217                                         $char = $escape.strtoupper(sprintf('%02s', dechex($ascii)));  // =3D
1218                                 }
1219
1220                                 // If we're at the character limit, add the line to the output,
1221                                 // reset our temp variable, and keep on chuggin'
1222                                 if ((strlen($temp) + strlen($char)) >= $charlim)
1223                                 {
1224                                         $output .= $temp.$escape.$this->crlf;
1225                                         $temp = '';
1226                                 }
1227
1228                                 // Add the character to our temporary line
1229                                 $temp .= $char;
1230                         }
1231
1232                         // Add our completed line to the output
1233                         $output .= $temp.$this->crlf;
1234                 }
1235
1236                 // get rid of extra CRLF tacked onto the end
1237                 $output = substr($output, 0, strlen($this->crlf) * -1);
1238
1239                 return $output;
1240         }
1241
1242         // --------------------------------------------------------------------
1243         
1244         /**
1245          * Send Email
1246          *
1247          * @access      public
1248          * @return      bool
1249          */     
1250         function send()
1251         {       
1252                 if ($this->_replyto_flag == FALSE)
1253                 {
1254                         $this->reply_to($this->_headers['From']);
1255                 }
1256         
1257                 if (( ! isset($this->_recipients) AND ! isset($this->_headers['To']))  AND
1258                         ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND
1259                         ( ! isset($this->_headers['Cc'])))
1260                 {
1261                         $this->_set_error_message('email_no_recipients');
1262                         return FALSE;
1263                 }
1264
1265                 $this->_build_headers();
1266
1267                 if ($this->bcc_batch_mode  AND  count($this->_bcc_array) > 0)
1268                 {
1269                         if (count($this->_bcc_array) > $this->bcc_batch_size)
1270                                 return $this->batch_bcc_send();
1271                 }
1272
1273                 $this->_build_message();
1274
1275                 if ( ! $this->_spool_email())
1276                 {
1277                         return FALSE;
1278                 }
1279                 else
1280                 {
1281                         return TRUE;
1282                 }
1283         }
1284         
1285         // --------------------------------------------------------------------
1286
1287         /**
1288          * Batch Bcc Send.  Sends groups of BCCs in batches
1289          *
1290          * @access      public
1291          * @return      bool
1292          */     
1293         function batch_bcc_send()
1294         {
1295                 $float = $this->bcc_batch_size -1;
1296
1297                 $set = "";
1298
1299                 $chunk = array();
1300
1301                 for ($i = 0; $i < count($this->_bcc_array); $i++)
1302                 {
1303                         if (isset($this->_bcc_array[$i]))
1304                         {
1305                                 $set .= ", ".$this->_bcc_array[$i];
1306                         }
1307
1308                         if ($i == $float)
1309                         {       
1310                                 $chunk[] = substr($set, 1);
1311                                 $float = $float + $this->bcc_batch_size;
1312                                 $set = "";
1313                         }
1314         
1315                         if ($i == count($this->_bcc_array)-1)
1316                         {
1317                                 $chunk[] = substr($set, 1);
1318                         }
1319                 }
1320
1321                 for ($i = 0; $i < count($chunk); $i++)
1322                 {
1323                         unset($this->_headers['Bcc']);
1324                         unset($bcc);
1325
1326                         $bcc = $this->_str_to_array($chunk[$i]);
1327                         $bcc = $this->clean_email($bcc);
1328         
1329                         if ($this->protocol != 'smtp')
1330                         {
1331                                 $this->_set_header('Bcc', implode(", ", $bcc));
1332                         }
1333                         else
1334                         {
1335                                 $this->_bcc_array = $bcc;
1336                         }
1337         
1338                         $this->_build_message();
1339                         $this->_spool_email();
1340                 }
1341         }
1342         
1343         // --------------------------------------------------------------------
1344
1345         /**
1346          * Unwrap special elements
1347          *
1348          * @access      private
1349          * @return      void
1350          */     
1351         function _unwrap_specials()
1352         {
1353                 $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
1354         }
1355         
1356         // --------------------------------------------------------------------
1357
1358         /**
1359          * Strip line-breaks via callback
1360          *
1361          * @access      private
1362          * @return      string
1363          */     
1364         function _remove_nl_callback($matches)
1365         {
1366                 if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
1367                 {
1368                         $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]);
1369                 }
1370                 
1371                 return $matches[1];
1372         }
1373         
1374         // --------------------------------------------------------------------
1375
1376         /**
1377          * Spool mail to the mail server
1378          *
1379          * @access      private
1380          * @return      bool
1381          */     
1382         function _spool_email()
1383         {
1384                 $this->_unwrap_specials();
1385
1386                 switch ($this->_get_protocol())
1387                 {
1388                         case 'mail'     :
1389         
1390                                         if ( ! $this->_send_with_mail())
1391                                         {
1392                                                 $this->_set_error_message('email_send_failure_phpmail');        
1393                                                 return FALSE;
1394                                         }
1395                         break;
1396                         case 'sendmail' :
1397                 
1398                                         if ( ! $this->_send_with_sendmail())
1399                                         {
1400                                                 $this->_set_error_message('email_send_failure_sendmail');       
1401                                                 return FALSE;
1402                                         }
1403                         break;
1404                         case 'smtp'     :
1405                 
1406                                         if ( ! $this->_send_with_smtp())
1407                                         {
1408                                                 $this->_set_error_message('email_send_failure_smtp');   
1409                                                 return FALSE;
1410                                         }
1411                         break;
1412
1413                 }
1414
1415                 $this->_set_error_message('email_sent', $this->_get_protocol());
1416                 return TRUE;
1417         }       
1418         
1419         // --------------------------------------------------------------------
1420
1421         /**
1422          * Send using mail()
1423          *
1424          * @access      private
1425          * @return      bool
1426          */     
1427         function _send_with_mail()
1428         {       
1429                 if ($this->_safe_mode == TRUE)
1430                 {
1431                         if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str))
1432                         {
1433                                 return FALSE;
1434                         }
1435                         else
1436                         {
1437                                 return TRUE;
1438                         }
1439                 }
1440                 else
1441                 {
1442                         // most documentation of sendmail using the "-f" flag lacks a space after it, however
1443                         // we've encountered servers that seem to require it to be in place.
1444                         if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
1445                         {
1446                                 return FALSE;
1447                         }
1448                         else
1449                         {
1450                                 return TRUE;
1451                         }
1452                 }
1453         }
1454         
1455         // --------------------------------------------------------------------
1456
1457         /**
1458          * Send using Sendmail
1459          *
1460          * @access      private
1461          * @return      bool
1462          */     
1463         function _send_with_sendmail()
1464         {
1465                 $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
1466
1467                 if ( ! is_resource($fp))
1468                 {               
1469                         $this->_set_error_message('email_no_socket');
1470                         return FALSE;
1471                 }
1472
1473                 fputs($fp, $this->_header_str);
1474                 fputs($fp, $this->_finalbody);
1475                 pclose($fp) >> 8 & 0xFF;
1476
1477                 return TRUE;
1478         }
1479         
1480         // --------------------------------------------------------------------
1481
1482         /**
1483          * Send using SMTP
1484          *
1485          * @access      private
1486          * @return      bool
1487          */     
1488         function _send_with_smtp()
1489         {       
1490                 if ($this->smtp_host == '')
1491                 {       
1492                         $this->_set_error_message('email_no_hostname');
1493                         return FALSE;
1494                 }
1495
1496                 $this->_smtp_connect();
1497                 $this->_smtp_authenticate();
1498
1499                 $this->_send_command('from', $this->clean_email($this->_headers['From']));
1500
1501                 foreach($this->_recipients as $val)
1502                 {
1503                         $this->_send_command('to', $val);
1504                 }
1505         
1506                 if (count($this->_cc_array) > 0)
1507                 {
1508                         foreach($this->_cc_array as $val)
1509                         {
1510                                 if ($val != "")
1511                                 {
1512                                         $this->_send_command('to', $val);
1513                                 }
1514                         }
1515                 }
1516
1517                 if (count($this->_bcc_array) > 0)
1518                 {
1519                         foreach($this->_bcc_array as $val)
1520                         {
1521                                 if ($val != "")
1522                                 {
1523                                         $this->_send_command('to', $val);
1524                                 }
1525                         }
1526                 }
1527
1528                 $this->_send_command('data');
1529
1530                 // perform dot transformation on any lines that begin with a dot
1531                 $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
1532
1533                 $this->_send_data('.');
1534
1535                 $reply = $this->_get_smtp_data();
1536
1537                 $this->_set_error_message($reply);      
1538
1539                 if (strncmp($reply, '250', 3) != 0)
1540                 {
1541                         $this->_set_error_message('email_smtp_error', $reply);  
1542                         return FALSE;
1543                 }
1544
1545                 $this->_send_command('quit');
1546                 return TRUE;
1547         }       
1548         
1549         // --------------------------------------------------------------------
1550
1551         /**
1552          * SMTP Connect
1553          *
1554          * @access      private
1555          * @param       string
1556          * @return      string
1557          */     
1558         function _smtp_connect()
1559         {
1560                 $this->_smtp_connect = fsockopen($this->smtp_host,
1561                                                                                 $this->smtp_port,
1562                                                                                 $errno,
1563                                                                                 $errstr,
1564                                                                                 $this->smtp_timeout);
1565
1566                 if( ! is_resource($this->_smtp_connect))
1567                 {               
1568                         $this->_set_error_message('email_smtp_error', $errno." ".$errstr);
1569                         return FALSE;
1570                 }
1571
1572                 $this->_set_error_message($this->_get_smtp_data());
1573                 return $this->_send_command('hello');
1574         }
1575         
1576         // --------------------------------------------------------------------
1577
1578         /**
1579          * Send SMTP command
1580          *
1581          * @access      private
1582          * @param       string
1583          * @param       string
1584          * @return      string
1585          */     
1586         function _send_command($cmd, $data = '')
1587         {
1588                 switch ($cmd)
1589                 {
1590                         case 'hello' :
1591
1592                                         if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
1593                                                 $this->_send_data('EHLO '.$this->_get_hostname());
1594                                         else
1595                                                 $this->_send_data('HELO '.$this->_get_hostname());
1596
1597                                                 $resp = 250;
1598                         break;
1599                         case 'from' :
1600         
1601                                                 $this->_send_data('MAIL FROM:<'.$data.'>');
1602
1603                                                 $resp = 250;
1604                         break;
1605                         case 'to'       :
1606         
1607                                                 $this->_send_data('RCPT TO:<'.$data.'>');
1608
1609                                                 $resp = 250;    
1610                         break;
1611                         case 'data'     :
1612         
1613                                                 $this->_send_data('DATA');
1614
1615                                                 $resp = 354;    
1616                         break;
1617                         case 'quit'     :
1618
1619                                                 $this->_send_data('QUIT');
1620
1621                                                 $resp = 221;
1622                         break;
1623                 }
1624
1625                 $reply = $this->_get_smtp_data();       
1626
1627                 $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
1628
1629                 if (substr($reply, 0, 3) != $resp)
1630                 {
1631                         $this->_set_error_message('email_smtp_error', $reply);
1632                         return FALSE;
1633                 }
1634         
1635                 if ($cmd == 'quit')
1636                 {
1637                         fclose($this->_smtp_connect);
1638                 }
1639         
1640                 return TRUE;
1641         }
1642         
1643         // --------------------------------------------------------------------
1644
1645         /**
1646          *  SMTP Authenticate
1647          *
1648          * @access      private
1649          * @return      bool
1650          */     
1651         function _smtp_authenticate()
1652         {       
1653                 if ( ! $this->_smtp_auth)
1654                 {
1655                         return TRUE;
1656                 }
1657         
1658                 if ($this->smtp_user == ""  AND  $this->smtp_pass == "")
1659                 {
1660                         $this->_set_error_message('email_no_smtp_unpw');
1661                         return FALSE;
1662                 }
1663
1664                 $this->_send_data('AUTH LOGIN');
1665
1666                 $reply = $this->_get_smtp_data();       
1667
1668                 if (strncmp($reply, '334', 3) != 0)
1669                 {
1670                         $this->_set_error_message('email_failed_smtp_login', $reply);   
1671                         return FALSE;
1672                 }
1673
1674                 $this->_send_data(base64_encode($this->smtp_user));
1675
1676                 $reply = $this->_get_smtp_data();       
1677
1678                 if (strncmp($reply, '334', 3) != 0)
1679                 {
1680                         $this->_set_error_message('email_smtp_auth_un', $reply);        
1681                         return FALSE;
1682                 }
1683
1684                 $this->_send_data(base64_encode($this->smtp_pass));
1685
1686                 $reply = $this->_get_smtp_data();       
1687
1688                 if (strncmp($reply, '235', 3) != 0)
1689                 {
1690                         $this->_set_error_message('email_smtp_auth_pw', $reply);        
1691                         return FALSE;
1692                 }
1693         
1694                 return TRUE;
1695         }
1696         
1697         // --------------------------------------------------------------------
1698
1699         /**
1700          * Send SMTP data
1701          *
1702          * @access      private
1703          * @return      bool
1704          */     
1705         function _send_data($data)
1706         {
1707                 if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
1708                 {
1709                         $this->_set_error_message('email_smtp_data_failure', $data);    
1710                         return FALSE;
1711                 }
1712                 else
1713                 {
1714                         return TRUE;
1715                 }
1716         }
1717         
1718         // --------------------------------------------------------------------
1719
1720         /**
1721          * Get SMTP data
1722          *
1723          * @access      private
1724          * @return      string
1725          */     
1726         function _get_smtp_data()
1727         {
1728                 $data = "";
1729
1730                 while ($str = fgets($this->_smtp_connect, 512))
1731                 {
1732                         $data .= $str;
1733         
1734                         if (substr($str, 3, 1) == " ")
1735                         {
1736                                 break;
1737                         }
1738                 }
1739
1740                 return $data;
1741         }
1742         
1743         // --------------------------------------------------------------------
1744
1745         /**
1746          * Get Hostname
1747          *
1748          * @access      private
1749          * @return      string
1750          */
1751         function _get_hostname()
1752         {       
1753                 return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';    
1754         }
1755         
1756         // --------------------------------------------------------------------
1757
1758         /**
1759          * Get IP
1760          *
1761          * @access      private
1762          * @return      string
1763          */
1764         function _get_ip()
1765         {
1766                 if ($this->_IP !== FALSE)
1767                 {
1768                         return $this->_IP;
1769                 }
1770         
1771                 $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
1772                 $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE;
1773                 $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
1774         
1775                 if ($cip && $rip)       $this->_IP = $cip;      
1776                 elseif ($rip)           $this->_IP = $rip;
1777                 elseif ($cip)           $this->_IP = $cip;
1778                 elseif ($fip)           $this->_IP = $fip;
1779
1780                 if (strstr($this->_IP, ','))
1781                 {
1782                         $x = explode(',', $this->_IP);
1783                         $this->_IP = end($x);
1784                 }
1785
1786                 if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP))
1787                 {
1788                         $this->_IP = '0.0.0.0';
1789                 }
1790
1791                 unset($cip);
1792                 unset($rip);
1793                 unset($fip);
1794
1795                 return $this->_IP;
1796         }
1797         
1798         // --------------------------------------------------------------------
1799
1800         /**
1801          * Get Debug Message
1802          *
1803          * @access      public
1804          * @return      string
1805          */     
1806         function print_debugger()
1807         {
1808                 $msg = '';
1809
1810                 if (count($this->_debug_msg) > 0)
1811                 {
1812                         foreach ($this->_debug_msg as $val)
1813                         {
1814                                 $msg .= $val;
1815                         }
1816                 }
1817
1818                 $msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';    
1819                 return $msg;
1820         }       
1821         
1822         // --------------------------------------------------------------------
1823
1824         /**
1825          * Set Message
1826          *
1827          * @access      private
1828          * @param       string
1829          * @return      string
1830          */     
1831         function _set_error_message($msg, $val = '')
1832         {
1833                 $CI =& get_instance();
1834                 $CI->lang->load('email');
1835         
1836                 if (FALSE === ($line = $CI->lang->line($msg)))
1837                 {       
1838                         $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
1839                 }       
1840                 else
1841                 {
1842                         $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
1843                 }       
1844         }
1845         
1846         // --------------------------------------------------------------------
1847
1848         /**
1849          * Mime Types
1850          *
1851          * @access      private
1852          * @param       string
1853          * @return      string
1854          */
1855         function _mime_types($ext = "")
1856         {
1857                 $mimes = array( 'hqx'   =>      'application/mac-binhex40',
1858                                                 'cpt'   =>      'application/mac-compactpro',
1859                                                 'doc'   =>      'application/msword',
1860                                                 'bin'   =>      'application/macbinary',
1861                                                 'dms'   =>      'application/octet-stream',
1862                                                 'lha'   =>      'application/octet-stream',
1863                                                 'lzh'   =>      'application/octet-stream',
1864                                                 'exe'   =>      'application/octet-stream',
1865                                                 'class' =>      'application/octet-stream',
1866                                                 'psd'   =>      'application/octet-stream',
1867                                                 'so'    =>      'application/octet-stream',
1868                                                 'sea'   =>      'application/octet-stream',
1869                                                 'dll'   =>      'application/octet-stream',
1870                                                 'oda'   =>      'application/oda',
1871                                                 'pdf'   =>      'application/pdf',
1872                                                 'ai'    =>      'application/postscript',
1873                                                 'eps'   =>      'application/postscript',
1874                                                 'ps'    =>      'application/postscript',
1875                                                 'smi'   =>      'application/smil',
1876                                                 'smil'  =>      'application/smil',
1877                                                 'mif'   =>      'application/vnd.mif',
1878                                                 'xls'   =>      'application/vnd.ms-excel',
1879                                                 'ppt'   =>      'application/vnd.ms-powerpoint',
1880                                                 'wbxml' =>      'application/vnd.wap.wbxml',
1881                                                 'wmlc'  =>      'application/vnd.wap.wmlc',
1882                                                 'dcr'   =>      'application/x-director',
1883                                                 'dir'   =>      'application/x-director',
1884                                                 'dxr'   =>      'application/x-director',
1885                                                 'dvi'   =>      'application/x-dvi',
1886                                                 'gtar'  =>      'application/x-gtar',
1887                                                 'php'   =>      'application/x-httpd-php',
1888                                                 'php4'  =>      'application/x-httpd-php',
1889                                                 'php3'  =>      'application/x-httpd-php',
1890                                                 'phtml' =>      'application/x-httpd-php',
1891                                                 'phps'  =>      'application/x-httpd-php-source',
1892                                                 'js'    =>      'application/x-javascript',
1893                                                 'swf'   =>      'application/x-shockwave-flash',
1894                                                 'sit'   =>      'application/x-stuffit',
1895                                                 'tar'   =>      'application/x-tar',
1896                                                 'tgz'   =>      'application/x-tar',
1897                                                 'xhtml' =>      'application/xhtml+xml',
1898                                                 'xht'   =>      'application/xhtml+xml',
1899                                                 'zip'   =>      'application/zip',
1900                                                 'mid'   =>      'audio/midi',
1901                                                 'midi'  =>      'audio/midi',
1902                                                 'mpga'  =>      'audio/mpeg',
1903                                                 'mp2'   =>      'audio/mpeg',
1904                                                 'mp3'   =>      'audio/mpeg',
1905                                                 'aif'   =>      'audio/x-aiff',
1906                                                 'aiff'  =>      'audio/x-aiff',
1907                                                 'aifc'  =>      'audio/x-aiff',
1908                                                 'ram'   =>      'audio/x-pn-realaudio',
1909                                                 'rm'    =>      'audio/x-pn-realaudio',
1910                                                 'rpm'   =>      'audio/x-pn-realaudio-plugin',
1911                                                 'ra'    =>      'audio/x-realaudio',
1912                                                 'rv'    =>      'video/vnd.rn-realvideo',
1913                                                 'wav'   =>      'audio/x-wav',
1914                                                 'bmp'   =>      'image/bmp',
1915                                                 'gif'   =>      'image/gif',
1916                                                 'jpeg'  =>      'image/jpeg',
1917                                                 'jpg'   =>      'image/jpeg',
1918                                                 'jpe'   =>      'image/jpeg',
1919                                                 'png'   =>      'image/png',
1920                                                 'tiff'  =>      'image/tiff',
1921                                                 'tif'   =>      'image/tiff',
1922                                                 'css'   =>      'text/css',
1923                                                 'html'  =>      'text/html',
1924                                                 'htm'   =>      'text/html',
1925                                                 'shtml' =>      'text/html',
1926                                                 'txt'   =>      'text/plain',
1927                                                 'text'  =>      'text/plain',
1928                                                 'log'   =>      'text/plain',
1929                                                 'rtx'   =>      'text/richtext',
1930                                                 'rtf'   =>      'text/rtf',
1931                                                 'xml'   =>      'text/xml',
1932                                                 'xsl'   =>      'text/xml',
1933                                                 'mpeg'  =>      'video/mpeg',
1934                                                 'mpg'   =>      'video/mpeg',
1935                                                 'mpe'   =>      'video/mpeg',
1936                                                 'qt'    =>      'video/quicktime',
1937                                                 'mov'   =>      'video/quicktime',
1938                                                 'avi'   =>      'video/x-msvideo',
1939                                                 'movie' =>      'video/x-sgi-movie',
1940                                                 'doc'   =>      'application/msword',
1941                                                 'word'  =>      'application/msword',
1942                                                 'xl'    =>      'application/excel',
1943                                                 'eml'   =>      'message/rfc822'
1944                                         );
1945
1946                 return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)];
1947         }
1948
1949 }
1950 // END CI_Email class
1951
1952 /* End of file Email.php */
1953 /* Location: ./system/libraries/Email.php */