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