X-Git-Url: http://git.onelab.eu/?p=www-register-wizard.git;a=blobdiff_plain;f=libraries%2FEmail.php;h=585815934dd42b6de0ff4e20967b377d2c5b242a;hp=7bcb1d8ca4aad1b0d3ff6e35c3ae18eddd1d05d9;hb=47598daa8c32dbbd72db83dc33f2ce91b3f6f7b0;hpb=4afb2fe256f094a1caf6bff14f51c6a88938cc9f diff --git a/libraries/Email.php b/libraries/Email.php index 7bcb1d8..5858159 100644 --- a/libraries/Email.php +++ b/libraries/Email.php @@ -6,7 +6,7 @@ * * @package CodeIgniter * @author ExpressionEngine Dev Team - * @copyright Copyright (c) 2008, EllisLab, Inc. + * @copyright Copyright (c) 2008 - 2009, EllisLab, Inc. * @license http://codeigniter.com/user_guide/license.html * @link http://codeigniter.com * @since Version 1.0 @@ -48,7 +48,7 @@ class CI_Email { var $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers, // even on the receiving end think they need to muck with CRLFs, so using "\n", while // distasteful, is the only thing that seems to work for all environments. - var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo. + var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo. var $bcc_batch_mode = FALSE; // TRUE/FALSE Turns on/off Bcc batch feature var $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch var $_safe_mode = FALSE; @@ -83,17 +83,17 @@ class CI_Email { * The constructor can be passed an array of config values */ function CI_Email($config = array()) - { + { if (count($config) > 0) { $this->initialize($config); - } + } else { - $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; + $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; } - + log_message('debug', "Email Class Initialized"); } @@ -122,14 +122,14 @@ class CI_Email { else { $this->$key = $val; - } + } } } - - $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; + + $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; } - + // -------------------------------------------------------------------- /** @@ -137,7 +137,7 @@ class CI_Email { * * @access public * @return void - */ + */ function clear($clear_attachments = FALSE) { $this->_subject = ""; @@ -157,9 +157,9 @@ class CI_Email { $this->_attach_name = array(); $this->_attach_type = array(); $this->_attach_disp = array(); - } + } } - + // -------------------------------------------------------------------- /** @@ -169,7 +169,7 @@ class CI_Email { * @param string * @param string * @return void - */ + */ function from($from, $name = '') { if (preg_match( '/\<(.*)\>/', $from, $match)) @@ -181,16 +181,26 @@ class CI_Email { { $this->validate_email($this->_str_to_array($from)); } - - if ($name != '' && strncmp($name, '"', 1) != 0) + + // prepare the display name + if ($name != '') { - $name = '"'.$name.'"'; + // only use Q encoding if there are characters that would require it + if ( ! preg_match('/[\200-\377]/', $name)) + { + // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes + $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"'; + } + else + { + $name = $this->_prep_q_encoding($name, TRUE); + } } - + $this->_set_header('From', $name.' <'.$from.'>'); $this->_set_header('Return-Path', '<'.$from.'>'); } - + // -------------------------------------------------------------------- /** @@ -200,7 +210,7 @@ class CI_Email { * @param string * @param string * @return void - */ + */ function reply_to($replyto, $name = '') { if (preg_match( '/\<(.*)\>/', $replyto, $match)) @@ -210,7 +220,7 @@ class CI_Email { if ($this->validate) { - $this->validate_email($this->_str_to_array($replyto)); + $this->validate_email($this->_str_to_array($replyto)); } if ($name == '') @@ -226,7 +236,7 @@ class CI_Email { $this->_set_header('Reply-To', $name.' <'.$replyto.'>'); $this->_replyto_flag = TRUE; } - + // -------------------------------------------------------------------- /** @@ -235,17 +245,17 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function to($to) { $to = $this->_str_to_array($to); $to = $this->clean_email($to); - + if ($this->validate) { $this->validate_email($to); } - + if ($this->_get_protocol() != 'mail') { $this->_set_header('To', implode(", ", $to)); @@ -259,9 +269,9 @@ class CI_Email { break; case 'mail' : $this->_recipients = implode(", ", $to); break; - } + } } - + // -------------------------------------------------------------------- /** @@ -270,9 +280,9 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function cc($cc) - { + { $cc = $this->_str_to_array($cc); $cc = $this->clean_email($cc); @@ -288,7 +298,7 @@ class CI_Email { $this->_cc_array = $cc; } } - + // -------------------------------------------------------------------- /** @@ -298,7 +308,7 @@ class CI_Email { * @param string * @param string * @return void - */ + */ function bcc($bcc, $limit = '') { if ($limit != '' && is_numeric($limit)) @@ -324,7 +334,7 @@ class CI_Email { $this->_set_header('Bcc', implode(", ", $bcc)); } } - + // -------------------------------------------------------------------- /** @@ -333,22 +343,13 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function subject($subject) { - if (strpos($subject, "\r") !== FALSE OR strpos($subject, "\n") !== FALSE) - { - $subject = str_replace(array("\r\n", "\r", "\n"), '', $subject); - } - - if (strpos($subject, "\t")) - { - $subject = str_replace("\t", ' ', $subject); - } - - $this->_set_header('Subject', trim($subject)); + $subject = $this->_prep_q_encoding($subject); + $this->_set_header('Subject', $subject); } - + // -------------------------------------------------------------------- /** @@ -357,12 +358,12 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function message($body) { - $this->_body = stripslashes(rtrim(str_replace("\r", "", $body))); - } - + $this->_body = stripslashes(rtrim(str_replace("\r", "", $body))); + } + // -------------------------------------------------------------------- /** @@ -370,10 +371,10 @@ class CI_Email { * * @access public * @param string - * @return string + * @return void */ function attach($filename, $disposition = 'attachment') - { + { $this->_attach_name[] = $filename; $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename)))); $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters @@ -388,12 +389,12 @@ class CI_Email { * @param string * @param string * @return void - */ + */ function _set_header($header, $value) { $this->_headers[$header] = $value; } - + // -------------------------------------------------------------------- /** @@ -402,7 +403,7 @@ class CI_Email { * @access private * @param string * @return array - */ + */ function _str_to_array($email) { if ( ! is_array($email)) @@ -419,7 +420,7 @@ class CI_Email { } return $email; } - + // -------------------------------------------------------------------- /** @@ -428,12 +429,12 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_alt_message($str = '') { $this->alt_message = ($str == '') ? '' : $str; } - + // -------------------------------------------------------------------- /** @@ -442,12 +443,12 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_mailtype($type = 'text') { $this->mailtype = ($type == 'html') ? 'html' : 'text'; } - + // -------------------------------------------------------------------- /** @@ -456,12 +457,12 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_wordwrap($wordwrap = TRUE) { $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE; } - + // -------------------------------------------------------------------- /** @@ -470,12 +471,12 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_protocol($protocol = 'mail') { $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol); } - + // -------------------------------------------------------------------- /** @@ -484,7 +485,7 @@ class CI_Email { * @access public * @param integer * @return void - */ + */ function set_priority($n = 3) { if ( ! is_numeric($n)) @@ -492,16 +493,16 @@ class CI_Email { $this->priority = 3; return; } - + if ($n < 1 OR $n > 5) { $this->priority = 3; return; } - + $this->priority = $n; } - + // -------------------------------------------------------------------- /** @@ -510,18 +511,18 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_newline($newline = "\n") { if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r") { - $this->newline = "\n"; + $this->newline = "\n"; return; } - - $this->newline = $newline; + + $this->newline = $newline; } - + // -------------------------------------------------------------------- /** @@ -530,18 +531,18 @@ class CI_Email { * @access public * @param string * @return void - */ + */ function set_crlf($crlf = "\n") { if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r") { - $this->crlf = "\n"; + $this->crlf = "\n"; return; } - - $this->crlf = $crlf; + + $this->crlf = $crlf; } - + // -------------------------------------------------------------------- /** @@ -549,13 +550,13 @@ class CI_Email { * * @access private * @return void - */ + */ function _set_boundaries() { $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary } - + // -------------------------------------------------------------------- /** @@ -563,16 +564,16 @@ class CI_Email { * * @access private * @return string - */ + */ function _get_message_id() { $from = $this->_headers['Return-Path']; $from = str_replace(">", "", $from); $from = str_replace("<", "", $from); - - return "<".uniqid('').strstr($from, '@').">"; + + return "<".uniqid('').strstr($from, '@').">"; } - + // -------------------------------------------------------------------- /** @@ -581,7 +582,7 @@ class CI_Email { * @access private * @param bool * @return string - */ + */ function _get_protocol($return = TRUE) { $this->protocol = strtolower($this->protocol); @@ -592,7 +593,7 @@ class CI_Email { return $this->protocol; } } - + // -------------------------------------------------------------------- /** @@ -601,7 +602,7 @@ class CI_Email { * @access private * @param bool * @return string - */ + */ function _get_encoding($return = TRUE) { $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding; @@ -613,10 +614,10 @@ class CI_Email { $this->_encoding = '7bit'; } } - + if ($return == TRUE) { - return $this->_encoding; + return $this->_encoding; } } @@ -627,9 +628,9 @@ class CI_Email { * * @access private * @return string - */ + */ function _get_content_type() - { + { if ($this->mailtype == 'html' && count($this->_attach_name) == 0) { return 'html'; @@ -647,7 +648,7 @@ class CI_Email { return 'plain'; } } - + // -------------------------------------------------------------------- /** @@ -655,7 +656,7 @@ class CI_Email { * * @access private * @return string - */ + */ function _set_date() { $timezone = date("Z"); @@ -665,7 +666,7 @@ class CI_Email { return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone); } - + // -------------------------------------------------------------------- /** @@ -673,12 +674,12 @@ class CI_Email { * * @access private * @return string - */ + */ function _get_mime_message() { return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format."; } - + // -------------------------------------------------------------------- /** @@ -687,9 +688,9 @@ class CI_Email { * @access public * @param string * @return bool - */ + */ function validate_email($email) - { + { if ( ! is_array($email)) { $this->_set_error_message('email_must_be_array'); @@ -704,8 +705,10 @@ class CI_Email { return FALSE; } } - } - + + return TRUE; + } + // -------------------------------------------------------------------- /** @@ -714,12 +717,12 @@ class CI_Email { * @access public * @param string * @return bool - */ + */ function valid_email($address) { return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE; } - + // -------------------------------------------------------------------- /** @@ -728,7 +731,7 @@ class CI_Email { * @access public * @param string * @return string - */ + */ function clean_email($email) { if ( ! is_array($email)) @@ -742,7 +745,7 @@ class CI_Email { return $email; } } - + $clean_email = array(); foreach ($email as $addy) @@ -753,13 +756,13 @@ class CI_Email { } else { - $clean_email[] = $addy; + $clean_email[] = $addy; } } return $clean_email; } - + // -------------------------------------------------------------------- /** @@ -772,7 +775,7 @@ class CI_Email { * * @access private * @return string - */ + */ function _get_alt_message() { if ($this->alt_message != "") @@ -796,18 +799,18 @@ class CI_Email { for ($i = 20; $i >= 3; $i--) { $n = ""; - + for ($x = 1; $x <= $i; $x ++) { $n .= "\n"; } - $body = str_replace($n, "\n\n", $body); + $body = str_replace($n, "\n\n", $body); } return $this->word_wrap($body, '76'); } - + // -------------------------------------------------------------------- /** @@ -817,7 +820,7 @@ class CI_Email { * @param string * @param integer * @return string - */ + */ function word_wrap($str, $charlim = '') { // Se the character limit @@ -832,10 +835,10 @@ class CI_Email { // Standardize newlines if (strpos($str, "\r") !== FALSE) { - $str = str_replace(array("\r\n", "\r"), "\n", $str); + $str = str_replace(array("\r\n", "\r"), "\n", $str); } - // If the current word is surrounded by {unwrap} tags we'll + // If the current word is surrounded by {unwrap} tags we'll // strip the entire chunk and replace it with a marker. $unwrap = array(); if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches)) @@ -847,25 +850,25 @@ class CI_Email { } } - // Use PHP's native function to do the initial wordwrap. - // We set the cut flag to FALSE so that any individual words that are + // Use PHP's native function to do the initial wordwrap. + // We set the cut flag to FALSE so that any individual words that are // too long get left alone. In the next step we'll deal with them. $str = wordwrap($str, $charlim, "\n", FALSE); // Split the string into individual lines of text and cycle through them $output = ""; - foreach (explode("\n", $str) as $line) + foreach (explode("\n", $str) as $line) { // Is the line within the allowed character count? // If so we'll join it to the output and continue if (strlen($line) <= $charlim) { - $output .= $line.$this->newline; + $output .= $line.$this->newline; continue; } $temp = ''; - while((strlen($line)) > $charlim) + while((strlen($line)) > $charlim) { // If the over-length word is a URL we won't wrap it if (preg_match("!\[url.+\]|://|wwww.!", $line)) @@ -877,8 +880,8 @@ class CI_Email { $temp .= substr($line, 0, $charlim-1); $line = substr($line, $charlim-1); } - - // If $temp contains data it means we had to split up an over-length + + // If $temp contains data it means we had to split up an over-length // word into smaller chunks so we'll add it back to our current line if ($temp != '') { @@ -894,16 +897,16 @@ class CI_Email { // Put our markers back if (count($unwrap) > 0) - { + { foreach ($unwrap as $key => $val) { $output = str_replace("{{unwrapped".$key."}}", $val, $output); } } - return $output; + return $output; } - + // -------------------------------------------------------------------- /** @@ -912,7 +915,7 @@ class CI_Email { * @access private * @param string * @return string - */ + */ function _build_headers() { $this->_set_header('X-Sender', $this->clean_email($this->_headers['From'])); @@ -921,7 +924,7 @@ class CI_Email { $this->_set_header('Message-ID', $this->_get_message_id()); $this->_set_header('Mime-Version', '1.0'); } - + // -------------------------------------------------------------------- /** @@ -936,7 +939,7 @@ class CI_Email { { $this->_subject = $this->_headers['Subject']; unset($this->_headers['Subject']); - } + } reset($this->_headers); $this->_header_str = ""; @@ -953,10 +956,10 @@ class CI_Email { if ($this->_get_protocol() == 'mail') { - $this->_header_str = substr($this->_header_str, 0, -1); + $this->_header_str = rtrim($this->_header_str); } } - + // -------------------------------------------------------------------- /** @@ -964,23 +967,23 @@ class CI_Email { * * @access private * @return void - */ + */ function _build_message() { if ($this->wordwrap === TRUE AND $this->mailtype != 'html') { $this->_body = $this->word_wrap($this->_body); } - + $this->_set_boundaries(); $this->_write_headers(); $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : ''; - + switch ($this->_get_content_type()) { case 'plain' : - + $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding(); @@ -988,7 +991,7 @@ class CI_Email { { $this->_header_str .= $hdr; $this->_finalbody = $this->_body; - + return; } @@ -996,21 +999,21 @@ class CI_Email { $this->_finalbody = $hdr; return; - + break; case 'html' : - + if ($this->send_multipart === FALSE) { $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: quoted-printable"; } else - { - $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline; + { + $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline . $this->newline; $hdr .= $this->_get_mime_message() . $this->newline . $this->newline; $hdr .= "--" . $this->_alt_boundary . $this->newline; - + $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline; $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline; @@ -1025,12 +1028,12 @@ class CI_Email { { $this->_header_str .= $hdr; $this->_finalbody = $this->_body . $this->newline . $this->newline; - + if ($this->send_multipart !== FALSE) { $this->_finalbody .= "--" . $this->_alt_boundary . "--"; } - + return; } @@ -1047,18 +1050,18 @@ class CI_Email { break; case 'plain-attach' : - - $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline; + + $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline; $hdr .= $this->_get_mime_message() . $this->newline . $this->newline; $hdr .= "--" . $this->_atc_boundary . $this->newline; - + $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding(); if ($this->_get_protocol() == 'mail') { $this->_header_str .= $hdr; - + $body = $this->_body . $this->newline . $this->newline; } @@ -1067,18 +1070,18 @@ class CI_Email { break; case 'html-attach' : - - $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline; + + $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline; $hdr .= $this->_get_mime_message() . $this->newline . $this->newline; $hdr .= "--" . $this->_atc_boundary . $this->newline; - + $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline; $hdr .= "--" . $this->_alt_boundary . $this->newline; $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline; $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline; - + $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline; $hdr .= "Content-Transfer-Encoding: quoted-printable"; @@ -1086,8 +1089,8 @@ class CI_Email { if ($this->_get_protocol() == 'mail') { - $this->_header_str .= $hdr; - + $this->_header_str .= $hdr; + $body = $this->_body . $this->newline . $this->newline; $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline; } @@ -1113,7 +1116,7 @@ class CI_Email { { $this->_set_error_message('email_attachment_missing', $filename); return FALSE; - } + } $h = "--".$this->_atc_boundary.$this->newline; $h .= "Content-type: ".$ctype."; "; @@ -1123,31 +1126,31 @@ class CI_Email { $attachment[$z++] = $h; $file = filesize($filename) +1; - + if ( ! $fp = fopen($filename, FOPEN_READ)) { $this->_set_error_message('email_attachment_unreadable', $filename); return FALSE; } - + $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file))); fclose($fp); } if ($this->_get_protocol() == 'mail') { - $this->_finalbody = $body . implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; - + $this->_finalbody = $body . implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; + return; } - $this->_finalbody = $hdr.implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; + $this->_finalbody = $hdr.implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--"; - return; + return; } - + // -------------------------------------------------------------------- - + /** * Prep Quoted Printable * @@ -1174,7 +1177,7 @@ class CI_Email { // kill nulls $str = preg_replace('/\x00+/', '', $str); - + // Standardize newlines if (strpos($str, "\r") !== FALSE) { @@ -1241,19 +1244,91 @@ class CI_Email { // -------------------------------------------------------------------- + /** + * Prep Q Encoding + * + * Performs "Q Encoding" on a string for use in email headers. It's related + * but not identical to quoted-printable, so it has its own method + * + * @access public + * @param str + * @param bool // set to TRUE for processing From: headers + * @return str + */ + function _prep_q_encoding($str, $from = FALSE) + { + $str = str_replace(array("\r", "\n"), array('', ''), $str); + + // Line length must not exceed 76 characters, so we adjust for + // a space, 7 extra characters =??Q??=, and the charset that we will add to each line + $limit = 75 - 7 - strlen($this->charset); + + // these special characters must be converted too + $convert = array('_', '=', '?'); + + if ($from === TRUE) + { + $convert[] = ','; + $convert[] = ';'; + } + + $output = ''; + $temp = ''; + + for ($i = 0, $length = strlen($str); $i < $length; $i++) + { + // Grab the next character + $char = substr($str, $i, 1); + $ascii = ord($char); + + // convert ALL non-printable ASCII characters and our specials + if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert)) + { + $char = '='.dechex($ascii); + } + + // handle regular spaces a bit more compactly than =20 + if ($ascii == 32) + { + $char = '_'; + } + + // If we're at the character limit, add the line to the output, + // reset our temp variable, and keep on chuggin' + if ((strlen($temp) + strlen($char)) >= $limit) + { + $output .= $temp.$this->crlf; + $temp = ''; + } + + // Add the character to our temporary line + $temp .= $char; + } + + $str = $output.$temp; + + // wrap each line with the shebang, charset, and transfer encoding + // the preceding space on successive lines is required for header "folding" + $str = trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str)); + + return $str; + } + + // -------------------------------------------------------------------- + /** * Send Email * * @access public * @return bool - */ + */ function send() - { + { if ($this->_replyto_flag == FALSE) { $this->reply_to($this->_headers['From']); } - + if (( ! isset($this->_recipients) AND ! isset($this->_headers['To'])) AND ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND ( ! isset($this->_headers['Cc']))) @@ -1281,7 +1356,7 @@ class CI_Email { return TRUE; } } - + // -------------------------------------------------------------------- /** @@ -1289,7 +1364,7 @@ class CI_Email { * * @access public * @return bool - */ + */ function batch_bcc_send() { $float = $this->bcc_batch_size -1; @@ -1306,12 +1381,12 @@ class CI_Email { } if ($i == $float) - { + { $chunk[] = substr($set, 1); $float = $float + $this->bcc_batch_size; $set = ""; } - + if ($i == count($this->_bcc_array)-1) { $chunk[] = substr($set, 1); @@ -1325,7 +1400,7 @@ class CI_Email { $bcc = $this->_str_to_array($chunk[$i]); $bcc = $this->clean_email($bcc); - + if ($this->protocol != 'smtp') { $this->_set_header('Bcc', implode(", ", $bcc)); @@ -1334,12 +1409,12 @@ class CI_Email { { $this->_bcc_array = $bcc; } - + $this->_build_message(); $this->_spool_email(); } } - + // -------------------------------------------------------------------- /** @@ -1347,12 +1422,12 @@ class CI_Email { * * @access private * @return void - */ + */ function _unwrap_specials() { $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody); } - + // -------------------------------------------------------------------- /** @@ -1360,17 +1435,17 @@ class CI_Email { * * @access private * @return string - */ + */ function _remove_nl_callback($matches) { if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE) { $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]); } - + return $matches[1]; } - + // -------------------------------------------------------------------- /** @@ -1378,7 +1453,7 @@ class CI_Email { * * @access private * @return bool - */ + */ function _spool_email() { $this->_unwrap_specials(); @@ -1386,26 +1461,26 @@ class CI_Email { switch ($this->_get_protocol()) { case 'mail' : - + if ( ! $this->_send_with_mail()) { - $this->_set_error_message('email_send_failure_phpmail'); + $this->_set_error_message('email_send_failure_phpmail'); return FALSE; } break; case 'sendmail' : - + if ( ! $this->_send_with_sendmail()) { - $this->_set_error_message('email_send_failure_sendmail'); + $this->_set_error_message('email_send_failure_sendmail'); return FALSE; } break; case 'smtp' : - + if ( ! $this->_send_with_smtp()) { - $this->_set_error_message('email_send_failure_smtp'); + $this->_set_error_message('email_send_failure_smtp'); return FALSE; } break; @@ -1414,8 +1489,8 @@ class CI_Email { $this->_set_error_message('email_sent', $this->_get_protocol()); return TRUE; - } - + } + // -------------------------------------------------------------------- /** @@ -1423,9 +1498,9 @@ class CI_Email { * * @access private * @return bool - */ + */ function _send_with_mail() - { + { if ($this->_safe_mode == TRUE) { if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str)) @@ -1451,7 +1526,7 @@ class CI_Email { } } } - + // -------------------------------------------------------------------- /** @@ -1459,24 +1534,37 @@ class CI_Email { * * @access private * @return bool - */ + */ function _send_with_sendmail() { $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w'); - if ( ! is_resource($fp)) - { - $this->_set_error_message('email_no_socket'); + if ($fp === FALSE OR $fp === NULL) + { + // server probably has popen disabled, so nothing we can do to get a verbose error. return FALSE; } - + fputs($fp, $this->_header_str); fputs($fp, $this->_finalbody); - pclose($fp) >> 8 & 0xFF; + + $status = pclose($fp); + + if (version_compare(PHP_VERSION, '4.2.3') == -1) + { + $status = $status >> 8 & 0xFF; + } + + if ($status != 0) + { + $this->_set_error_message('email_exit_status', $status); + $this->_set_error_message('email_no_socket'); + return FALSE; + } return TRUE; } - + // -------------------------------------------------------------------- /** @@ -1484,11 +1572,11 @@ class CI_Email { * * @access private * @return bool - */ + */ function _send_with_smtp() - { + { if ($this->smtp_host == '') - { + { $this->_set_error_message('email_no_hostname'); return FALSE; } @@ -1502,7 +1590,7 @@ class CI_Email { { $this->_send_command('to', $val); } - + if (count($this->_cc_array) > 0) { foreach($this->_cc_array as $val) @@ -1534,18 +1622,18 @@ class CI_Email { $reply = $this->_get_smtp_data(); - $this->_set_error_message($reply); + $this->_set_error_message($reply); if (strncmp($reply, '250', 3) != 0) { - $this->_set_error_message('email_smtp_error', $reply); + $this->_set_error_message('email_smtp_error', $reply); return FALSE; } $this->_send_command('quit'); return TRUE; - } - + } + // -------------------------------------------------------------------- /** @@ -1554,7 +1642,7 @@ class CI_Email { * @access private * @param string * @return string - */ + */ function _smtp_connect() { $this->_smtp_connect = fsockopen($this->smtp_host, @@ -1564,7 +1652,7 @@ class CI_Email { $this->smtp_timeout); if( ! is_resource($this->_smtp_connect)) - { + { $this->_set_error_message('email_smtp_error', $errno." ".$errstr); return FALSE; } @@ -1572,7 +1660,7 @@ class CI_Email { $this->_set_error_message($this->_get_smtp_data()); return $this->_send_command('hello'); } - + // -------------------------------------------------------------------- /** @@ -1582,7 +1670,7 @@ class CI_Email { * @param string * @param string * @return string - */ + */ function _send_command($cmd, $data = '') { switch ($cmd) @@ -1597,22 +1685,22 @@ class CI_Email { $resp = 250; break; case 'from' : - + $this->_send_data('MAIL FROM:<'.$data.'>'); $resp = 250; break; case 'to' : - + $this->_send_data('RCPT TO:<'.$data.'>'); - $resp = 250; + $resp = 250; break; case 'data' : - + $this->_send_data('DATA'); - $resp = 354; + $resp = 354; break; case 'quit' : @@ -1622,7 +1710,7 @@ class CI_Email { break; } - $reply = $this->_get_smtp_data(); + $reply = $this->_get_smtp_data(); $this->_debug_msg[] = "
".$cmd.": ".$reply."
"; @@ -1631,15 +1719,15 @@ class CI_Email { $this->_set_error_message('email_smtp_error', $reply); return FALSE; } - + if ($cmd == 'quit') { fclose($this->_smtp_connect); } - + return TRUE; } - + // -------------------------------------------------------------------- /** @@ -1647,14 +1735,14 @@ class CI_Email { * * @access private * @return bool - */ + */ function _smtp_authenticate() - { + { if ( ! $this->_smtp_auth) { return TRUE; } - + if ($this->smtp_user == "" AND $this->smtp_pass == "") { $this->_set_error_message('email_no_smtp_unpw'); @@ -1663,37 +1751,37 @@ class CI_Email { $this->_send_data('AUTH LOGIN'); - $reply = $this->_get_smtp_data(); + $reply = $this->_get_smtp_data(); if (strncmp($reply, '334', 3) != 0) { - $this->_set_error_message('email_failed_smtp_login', $reply); + $this->_set_error_message('email_failed_smtp_login', $reply); return FALSE; } $this->_send_data(base64_encode($this->smtp_user)); - $reply = $this->_get_smtp_data(); + $reply = $this->_get_smtp_data(); if (strncmp($reply, '334', 3) != 0) { - $this->_set_error_message('email_smtp_auth_un', $reply); + $this->_set_error_message('email_smtp_auth_un', $reply); return FALSE; } $this->_send_data(base64_encode($this->smtp_pass)); - $reply = $this->_get_smtp_data(); + $reply = $this->_get_smtp_data(); if (strncmp($reply, '235', 3) != 0) { - $this->_set_error_message('email_smtp_auth_pw', $reply); + $this->_set_error_message('email_smtp_auth_pw', $reply); return FALSE; } - + return TRUE; } - + // -------------------------------------------------------------------- /** @@ -1701,12 +1789,12 @@ class CI_Email { * * @access private * @return bool - */ + */ function _send_data($data) { if ( ! fwrite($this->_smtp_connect, $data . $this->newline)) { - $this->_set_error_message('email_smtp_data_failure', $data); + $this->_set_error_message('email_smtp_data_failure', $data); return FALSE; } else @@ -1714,7 +1802,7 @@ class CI_Email { return TRUE; } } - + // -------------------------------------------------------------------- /** @@ -1722,7 +1810,7 @@ class CI_Email { * * @access private * @return string - */ + */ function _get_smtp_data() { $data = ""; @@ -1730,7 +1818,7 @@ class CI_Email { while ($str = fgets($this->_smtp_connect, 512)) { $data .= $str; - + if (substr($str, 3, 1) == " ") { break; @@ -1739,7 +1827,7 @@ class CI_Email { return $data; } - + // -------------------------------------------------------------------- /** @@ -1749,10 +1837,10 @@ class CI_Email { * @return string */ function _get_hostname() - { - return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain'; + { + return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain'; } - + // -------------------------------------------------------------------- /** @@ -1767,12 +1855,12 @@ class CI_Email { { return $this->_IP; } - + $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE; $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE; $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE; - - if ($cip && $rip) $this->_IP = $cip; + + if ($cip && $rip) $this->_IP = $cip; elseif ($rip) $this->_IP = $rip; elseif ($cip) $this->_IP = $cip; elseif ($fip) $this->_IP = $fip; @@ -1794,7 +1882,7 @@ class CI_Email { return $this->_IP; } - + // -------------------------------------------------------------------- /** @@ -1802,7 +1890,7 @@ class CI_Email { * * @access public * @return string - */ + */ function print_debugger() { $msg = ''; @@ -1815,10 +1903,10 @@ class CI_Email { } } - $msg .= "
".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'
'; + $msg .= "
".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'
'; return $msg; - } - + } + // -------------------------------------------------------------------- /** @@ -1827,22 +1915,22 @@ class CI_Email { * @access private * @param string * @return string - */ + */ function _set_error_message($msg, $val = '') { $CI =& get_instance(); $CI->lang->load('email'); - + if (FALSE === ($line = $CI->lang->line($msg))) - { + { $this->_debug_msg[] = str_replace('%s', $val, $msg)."
"; - } + } else { $this->_debug_msg[] = str_replace('%s', $val, $line)."
"; - } + } } - + // -------------------------------------------------------------------- /**