init_class('CI_Email'); // ------------------------------------------------------------------------ /** * Code Igniter Email Class * * Permits email to be sent using Mail, Sendmail, or SMTP. * * @package CodeIgniter * @subpackage Libraries * @category Libraries * @author Rick Ellis * @link http://www.codeigniter.com/user_guide/libraries/email.html */ class CI_Email { var $useragent = "Code Igniter"; var $mailpath = "/usr/sbin/sendmail"; // Sendmail path var $protocol = "mail"; // mail/sendmail/smtp var $smtp_host = ""; // SMTP Server. Example: mail.earthlink.net var $smtp_user = ""; // SMTP Username var $smtp_pass = ""; // SMTP Password var $smtp_port = "25"; // SMTP Port var $smtp_timeout = 5; // SMTP Timeout in seconds var $wordwrap = TRUE; // true/false Turns word-wrap on/off var $wrapchars = "76"; // Number of characters to wrap at. var $mailtype = "text"; // text/html Defines email formatting var $charset = "utf-8"; // Default char set: iso-8859-1 or us-ascii var $multipart = "mixed"; // "mixed" (in the body) or "related" (separate) var $alt_message = ''; // Alternative message for HTML emails var $validate = FALSE; // true/false. Enables email validation var $priority = "3"; // Default priority (1 - 5) var $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822) 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 $_subject = ""; var $_body = ""; var $_finalbody = ""; var $_alt_boundary = ""; var $_atc_boundary = ""; var $_header_str = ""; var $_smtp_connect = ""; var $_encoding = "8bit"; var $_safe_mode = FALSE; var $_IP = FALSE; var $_smtp_auth = FALSE; var $_replyto_flag = FALSE; var $_debug_msg = array(); var $_recipients = array(); var $_cc_array = array(); var $_bcc_array = array(); var $_headers = array(); var $_attach_name = array(); var $_attach_type = array(); var $_attach_disp = array(); var $_protocols = array('mail', 'sendmail', 'smtp'); var $_base_charsets = array('iso-8859-1', 'us-ascii'); var $_bit_depths = array('7bit', '8bit'); var $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)'); /** * Constructor - Sets Email Preferences * * The constructor can be passed an array of config values */ function CI_Email($config = array()) { if (count($config) > 0) { $this->initialize($config); } log_message('debug', "Email Class Initialized"); } // END CI_Email() // -------------------------------------------------------------------- /** * Initialize preferences * * @access public * @param array * @return void */ function initialize($config = array()) { $this->clear(); foreach ($config as $key => $val) { if (isset($this->$key)) { $method = 'set_'.$key; if (method_exists($this, $method)) { $this->$method($val); } else { $this->$key = $val; } } } $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; $this->_safe_mode = (@ini_get("safe_mode") == 0) ? FALSE : TRUE; } // END initialize() // -------------------------------------------------------------------- /** * Initialize the Email Data * * @access public * @return void */ function clear($clear_attachments = FALSE) { $this->_subject = ""; $this->_body = ""; $this->_finalbody = ""; $this->_header_str = ""; $this->_replyto_flag = FALSE; $this->_recipients = array(); $this->_headers = array(); $this->_debug_msg = array(); $this->_set_header('User-Agent', $this->useragent); $this->_set_header('Date', $this->_set_date()); if ($clear_attachments !== FALSE) { $this->_attach_name = array(); $this->_attach_type = array(); $this->_attach_disp = array(); } } // END clear() // -------------------------------------------------------------------- /** * Set FROM * * @access public * @param string * @param string * @return void */ function from($from, $name = '') { if (preg_match( '/\<(.*)\>/', $from, $match)) $from = $match['1']; if ($this->validate) $this->validate_email($this->_str_to_array($from)); if ($name != '' && substr($name, 0, 1) != '"') { $name = '"'.$name.'"'; } $this->_set_header('From', $name.' <'.$from.'>'); $this->_set_header('Return-Path', '<'.$from.'>'); } // END from() // -------------------------------------------------------------------- /** * Set Reply-to * * @access public * @param string * @param string * @return void */ function reply_to($replyto, $name = '') { if (preg_match( '/\<(.*)\>/', $replyto, $match)) $replyto = $match['1']; if ($this->validate) $this->validate_email($this->_str_to_array($replyto)); if ($name == '') { $name = $replyto; } if (substr($name, 0, 1) != '"') { $name = '"'.$name.'"'; } $this->_set_header('Reply-To', $name.' <'.$replyto.'>'); $this->_replyto_flag = TRUE; } // END reply_to() // -------------------------------------------------------------------- /** * Set Recipients * * @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)); switch ($this->_get_protocol()) { case 'smtp' : $this->_recipients = $to; break; case 'sendmail' : $this->_recipients = implode(", ", $to); break; case 'mail' : $this->_recipients = implode(", ", $to); break; } } // END to() // -------------------------------------------------------------------- /** * Set CC * * @access public * @param string * @return void */ function cc($cc) { $cc = $this->_str_to_array($cc); $cc = $this->clean_email($cc); if ($this->validate) $this->validate_email($cc); $this->_set_header('Cc', implode(", ", $cc)); if ($this->_get_protocol() == "smtp") $this->_cc_array = $cc; } // END cc() // -------------------------------------------------------------------- /** * Set BCC * * @access public * @param string * @param string * @return void */ function bcc($bcc, $limit = '') { if ($limit != '' && is_numeric($limit)) { $this->bcc_batch_mode = true; $this->bcc_batch_size = $limit; } $bcc = $this->_str_to_array($bcc); $bcc = $this->clean_email($bcc); if ($this->validate) $this->validate_email($bcc); if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size)) $this->_bcc_array = $bcc; else $this->_set_header('Bcc', implode(", ", $bcc)); } // END bcc() // -------------------------------------------------------------------- /** * Set Email Subject * * @access public * @param string * @return void */ function subject($subject) { $subject = preg_replace("/(\r\n)|(\r)|(\n)/", "", $subject); $subject = preg_replace("/(\t)/", " ", $subject); $this->_set_header('Subject', trim($subject)); } // END subject() // -------------------------------------------------------------------- /** * Set Body * * @access public * @param string * @return void */ function message($body) { $body = rtrim(str_replace("\r", "", $body)); if ($this->wordwrap === TRUE AND $this->mailtype != 'html') $this->_body = $this->word_wrap($body); else $this->_body = $body; $this->_body = stripslashes($this->_body); } // END message() // -------------------------------------------------------------------- /** * Assign file attachments * * @access public * @param string * @return string */ 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 } // END attach() // -------------------------------------------------------------------- /** * Add a Header Item * * @access public * @param string * @param string * @return void */ function _set_header($header, $value) { $this->_headers[$header] = $value; } // END _set_header() // -------------------------------------------------------------------- /** * Convert a String to an Array * * @access public * @param string * @return array */ function _str_to_array($email) { if ( ! is_array($email)) { if (ereg(',$', $email)) $email = substr($email, 0, -1); if (ereg('^,', $email)) $email = substr($email, 1); if (ereg(',', $email)) { $x = explode(',', $email); $email = array(); for ($i = 0; $i < count($x); $i ++) $email[] = trim($x[$i]); } else { $email = trim($email); settype($email, "array"); } } return $email; } // END _str_to_array() // -------------------------------------------------------------------- /** * Set Multipart Value * * @access public * @param string * @return void */ function set_alt_message($str = '') { $this->alt_message = ($str == '') ? '' : $str; } // END set_alt_message() // -------------------------------------------------------------------- /** * Set Mailtype * * @access public * @param string * @return void */ function set_mailtype($type = 'text') { $this->mailtype = ($type == 'html') ? 'html' : 'text'; } // END set_mailtype() // -------------------------------------------------------------------- /** * Set Wordwrap * * @access public * @param string * @return void */ function set_wordwrap($wordwrap = TRUE) { $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE; } // END set_wordwrap() // -------------------------------------------------------------------- /** * Set Protocal * * @access public * @param string * @return void */ function set_protocol($protocol = 'mail') { $this->protocol = ( ! in_array($protocol, $this->_protocols)) ? 'mail' : strtolower($protocol); } // END set_protocol() // -------------------------------------------------------------------- /** * Set Priority * * @access public * @param integer * @return void */ function set_priority($n = 3) { if ( ! is_numeric($n)) { $this->priority = 3; return; } if ($n < 1 OR $n > 5) { $this->priority = 3; return; } $this->priority = $n; } // END set_priority() // -------------------------------------------------------------------- /** * Set Newline Character * * @access public * @param string * @return void */ function set_newline($newline = "\n") { if ($newline != "\n" OR $newline != "\r\n" OR $newline != "\r") { $this->newline = "\n"; return; } $this->newline = $newline; } // END set_newline() // -------------------------------------------------------------------- /** * Set Message Boundry * * @access private * @return void */ function _set_boundaries() { $this->_alt_boundary = "B_ALT_".uniqid(''); // mulipart/alternative $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary } // END _set_boundaries() // -------------------------------------------------------------------- /** * Get the Message ID * * @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, '@').">"; } // END _get_message_id() // -------------------------------------------------------------------- /** * Get Mail Protocol * * @access private * @param bool * @return string */ function _get_protocol($return = true) { $this->protocol = strtolower($this->protocol); $this->protocol = ( ! in_array($this->protocol, $this->_protocols)) ? 'mail' : $this->protocol; if ($return == true) return $this->protocol; } // END _get_protocol() // -------------------------------------------------------------------- /** * Get Mail Encoding * * @access private * @param bool * @return string */ function _get_encoding($return = true) { $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '7bit' : $this->_encoding; if ( ! in_array($this->charset, $this->_base_charsets)) $this->_encoding = "8bit"; if ($return == true) return $this->_encoding; } // END _get_encoding() // -------------------------------------------------------------------- /** * Get content type (text/html/attachment) * * @access private * @return string */ function _get_content_type() { if ($this->mailtype == 'html' && count($this->_attach_name) == 0) return 'html'; elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0) return 'html-attach'; elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0) return 'plain-attach'; else return 'plain'; } // END _get_content_type() // -------------------------------------------------------------------- /** * Set RFC 822 Date * * @access public * @return string */ function _set_date() { $timezone = date("Z"); $operator = (substr($timezone, 0, 1) == '-') ? '-' : '+'; $timezone = abs($timezone); $timezone = ($timezone/3600) * 100 + ($timezone % 3600) /60; return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone); } // END _set_date() // -------------------------------------------------------------------- /** * Mime message * * @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."; } // END _get_mime_message() // -------------------------------------------------------------------- /** * Validate Email Address * * @access public * @param string * @return bool */ function validate_email($email) { if ( ! is_array($email)) { $this->_set_error_message('email_must_be_array'); return FALSE; } foreach ($email as $val) { if ( ! $this->valid_email($val)) { $this->_set_error_message('email_invalid_address', $val); return FALSE; } } } // END validate_email() // -------------------------------------------------------------------- /** * Email Validation * * @access public * @param string * @return bool */ function valid_email($address) { if ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) return FALSE; else return TRUE; } // END valid_email() // -------------------------------------------------------------------- /** * Clean Extended Email Address: Joe Smith * * @access public * @param string * @return string */ function clean_email($email) { if ( ! is_array($email)) { if (preg_match('/\<(.*)\>/', $email, $match)) return $match['1']; else return $email; } $clean_email = array(); for ($i=0; $i < count($email); $i++) { if (preg_match( '/\<(.*)\>/', $email[$i], $match)) $clean_email[] = $match['1']; else $clean_email[] = $email[$i]; } return $clean_email; } // END clean_email() // -------------------------------------------------------------------- /** * Build alternative plain text message * * This function provides the raw message for use * in plain-text headers of HTML-formatted emails. * If the user hasn't specified his own alternative message * it creates one by stripping the HTML * * @access private * @return string */ function _get_alt_message() { if ($this->alt_message != "") { return $this->word_wrap($this->alt_message, '76'); } if (eregi( '\', $this->_body, $match)) { $body = $match['1']; $body = substr($body, strpos($body, ">") + 1); } else { $body = $this->_body; } $body = trim(strip_tags($body)); $body = preg_replace( '#