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