Source for file Email.php

Documentation is available at Email.php

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

Documentation generated on Wed, 01 Jan 2025 23:00:03 -0600 by phpDocumentor 1.4.3