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