Update version.php to 3.3.0
[isso.git] / Mail.php
index 0cc34533d034e888b4a8ab8f566f45574ecfe027..aceb47437561f0d01682b8a2fba878a7a6b82c83 100644 (file)
--- a/Mail.php
+++ b/Mail.php
@@ -2,11 +2,11 @@
 /*=====================================================================*\
 || ###################################################################
 || # Blue Static ISSO Framework
-|| # Copyright ©2002-[#]year[#] Blue Static
+|| # Copyright (c)2005-2009 Blue Static
 || #
 || # This program is free software; you can redistribute it and/or modify
 || # it under the terms of the GNU General Public License as published by
-|| # the Free Software Foundation; version [#]gpl[#] of the License.
+|| # the Free Software Foundation; version 2 of the License.
 || #
 || # This program is distributed in the hope that it will be useful, but
 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 \*=====================================================================*/
 
 /**
-* Mail Sender (mail.php)
-*
-* @package     ISSO
-*/
+ * Mail Sender (mail.php)
+ *
+ * @package    ISSO
+ */
 
-require_once('ISSO/Functions.php');
+require_once(ISSO . '/Functions.php');
 
 /**
-* Mail Sender
-*
-* This framework is a wrapper for the PHP mail function that properly
-* sends mail with full email headers.
-*
-* @author              Blue Static
-* @copyright   Copyright ©2002 - [#]year[#], Blue Static
-* @version             $Revision$
-* @package             ISSO
-* 
-*/
+ * Mail Sender
+ *
+ * This framework is a wrapper for the PHP mail function that properly
+ * sends mail with full email headers.
+ *
+ * @author             Blue Static
+ * @copyright  Copyright (c)2005 - 2009, Blue Static
+ * @package            ISSO
+ * 
+ */
 class BSMail
 {
        /**
-       * The subject of the message
-       * @var  string
-       */
+        * The subject of the message
+        * @var string
+        */
        private $subject = '';
        
        /**
-       * Body plain-text of the message
-       * @var  string
-       */
+        * Body plain-text of the message
+        * @var string
+        */
        private $bodyText = '';
        
        /**
-       * HTML multi-part body of the message
-       * @var  string
-       */
+        * HTML multi-part body of the message
+        * @var string
+        */
        private $bodyHtml = '';
        
        /**
-       * The message sender's email address
-       * @var  string
-       */
+        * The message sender's email address
+        * @var string
+        */
        private $from = '';
        
        /**
-       * The message sender's display name
-       * @var  string
-       */
+        * The message sender's display name
+        * @var string
+        */
        private $fromName = '';
        
        /**
-       * Additional message headers
-       * @var  string
-       */
+        * Additional message headers
+        * @var string
+        */
        private $headers = '';
 
        /**
-       * The new line delimiter used in the message
-       * @var  string
-       * @access       private
-       */
+        * The new line delimiter used in the message
+        * @var string
+        * @access      private
+        */
        private $delim = "\n";
        
        /**
-       * Character set used to send messages with
-       * @var  string
-       * @access       public
-       */
+        * Character set used to send messages with
+        * @var string
+        * @access      public
+        */
        private $charset = 'utf-8'; // should we be using iso-8859-1 ?
+       
+       /**
+        * Constructor
+        */
+       public function __construct()
+       {
+               if (!BSApp::$input instanceof BSInput)
+               {
+                       throw new Exception('BSApp::$input is not an instance of BSInput');
+               }
+       }
                
-       // ###################################################################
        /**
-       * Sets the subject
-       *
-       * @param        string  Subject text
-       */
+        * Sets the subject
+        *
+        * @param       string  Subject text
+        */
        public function setSubject($subject)
        {
                $this->subject = $subject;
        }
        
-       // ###################################################################
        /**
-       * Sets the body text (required)
-       *
-       * @param        string  Body text
-       */
+        * Sets the body text (required)
+        *
+        * @param       string  Body text
+        */
        public function setBodyText($body)
        {
                $this->bodyText = $body;
        }
        
-       // ###################################################################
        /**
-       * Sets the HTML body (optional)
-       *
-       * @param        string  Body HTML
-       */
+        * Sets the HTML body (optional)
+        *
+        * @param       string  Body HTML
+        */
        public function setBodyHtml($body)
        {
                $this->bodyHtml = $body;
        }
        
-       // ###################################################################
        /**
-       * Sets the from address
-       *
-       * @param        string  Sending email address
-       */
+        * Sets the from address
+        *
+        * @param       string  Sending email address
+        */
        public function setFromAddress($address)
        {
                $this->from = $address;
        }
        
-       // ###################################################################
        /**
-       * Sets the from display name
-       *
-       * @param        string  From name
-       */
+        * Sets the from display name
+        *
+        * @param       string  From name
+        */
        public function setFromName($name)
        {
                $this->fromName = $name;
        }
        
-       // ###################################################################
        /**
-       * Sets any additional headers
-       *
-       * @param        string  Additional headers separated by a \n
-       */
+        * Sets any additional headers
+        *
+        * @param       string  Additional headers separated by a \n
+        */
        public function setHeaders($headers)
        {
                $this->headers = $headers;
        }
        
-       // ###################################################################
        /**
-       * Sets the character set to send the email in
-       *
-       * @param        string  Charset
-       */
+        * Sets the character set to send the email in
+        *
+        * @param       string  Charset
+        */
        public function setCharset($charset)
        {
                $this->charset = $charset;
        }
                
-       // ###################################################################
        /**
-       * Sends an email to the specified address with the specified
-       * sender, subject, and body.
-       *
-       * @param        string  Email address to send to
-       * @param        string  Name of the recipient
-       * @param        bool    Send an HTML multipart (if HTML body specified)?
-       *
-       * @return       bool    Status of the message
-       */
-       public function send($address, $name = null, $sendHtml = false)
+        * Sends an email to the specified address with the specified
+        * sender, subject, and body.
+        *
+        * @param       string  Email address to send to
+        * @param       string  Name of the recipient
+        * @param       bool    Send an HTML multipart (if HTML body specified)?
+        *
+        * @return      bool    Status of the message
+        */
+       public function send($address, $name = null, $sendhtml = false)
        {
                if (empty($address))
                {
-                       trigger_error('You need to specify an email address');
-               }
-               
-               // load the input sanitizer
-               $input = BSRegister::GetType('BSInput');
-               if ($input == null)
-               {
-                       BSRegister::Debug('ISSO/Input not loaded, so manually doing so');
-                       $input = BSRegister::LoadModule('Input');
+                       throw new Exception('You need to specify an email address');
                }
                
                // make sure we have a mailer
                // TODO - add support for SMTP
                if (!@ini_get('sendmail_path'))
                {
-                       BSRegister::Debug("email: no sendmail -> not sending");
+                       BSApp::debug("BSMail: no sendmail -> not sending");
                        return false;
                }
                
                // sort out the to addresses
                $address = $this->_fetchFirstLine($address);
-               $address = trim($input->unsanitize($address));
+               $address = trim(BSApp::$input->unsanitize($address));
                $name = $this->_fetchFirstLine($name);
-               $name = trim($input->unsanitize($name));
+               $name = trim(BSApp::$input->unsanitize($name));
                $tostring = ($name == null ?  $address : "\"$name\" <$address>");
                
                // sanitize the from field
-               $this->from = $this->_fetchFirstLine($this->from);
-               $this->from = trim($input->unsanitize($this->from));
-               if (empty($this->from))
+               $from = $this->_fetchFirstLine($this->from);
+               $from = trim(BSApp::$input->unsanitize($from));
+               if (empty($from))
                {
-                       trigger_error('You need to specify a from email address');
+                       throw new Exception('You need to specify a from email address');
                }
                
                // sanitize the from name
-               $this->fromName = $this->_fetchFirstLine($this->fromName);
-               $this->fromName = ($this->fromName == '' ? $this->from : trim($input->unsanitize($this->fromName)));
+               $fromName = $this->_fetchFirstLine($this->fromName);
+               $fromName = ($fromName == '' ? $from : trim(BSApp::$input->unsanitize($fromName)));
+               $fromName = $this->_encodeHeaderValue($this->fromName);
                
                // sanitize the subject
-               $this->subject = $this->_fetchFirstLine($this->subject);
-               $this->subject = trim($input->unsanitize($this->subject));
-               if (empty($this->subject))
+               $subject = $this->_fetchFirstLine($this->subject);
+               $subject = trim(BSApp::$input->unsanitize($subject));
+               if (empty($subject))
                {
-                       trigger_error('You need to specify a subject for the message');
+                       throw new Exception('You need to specify a subject for the message');
                }
                
                // sanitize the body
-               $this->bodyText = BSFunctions::ConvertLineBreaks($this->bodyText, $this->delim);
-               $this->bodyText = trim($input->unsanitize($this->bodyText, true));
-               if (empty($this->bodyText))
+               $bodyText = BSFunctions::convert_line_breaks($this->bodyText, $this->delim);
+               $bodyText = trim(BSApp::$input->unsanitize($bodyText, true));
+               if (empty($bodyText))
                {
-                       trigger_error('You need to specify body text before sending the message');
+                       throw new Exception('You need to specify body text before sending the message');
                }
                
                // attach additional headers
-               $headers = BSFunctions::ConvertLineBreaks($this->headers, $this->delim);
-               $headers .= ((!preg_match("#{$this->delim}$#", $headers) AND $headers != '') ? "\n" : '') . "From: \"{$this->fromName}\" <{$this->from}>" . $this->delim;
-               $headers .= "Return-Path: {$this->from}" . $this->delim;
-               $headers .= "X-Mailer: ISSO Mail Framework \$Revision$" . $this->delim;
+               $headers = BSFunctions::convert_line_breaks($this->headers, $this->delim);
+               $headers .= ((!preg_match("#{$this->delim}$#", $headers) && $headers != '') ? "\n" : '') . "From: \"{$fromName}\" <{$from}>" . $this->delim;
+               $headers .= "Return-Path: {$from}" . $this->delim;
+               $headers .= "X-Mailer: ISSO Mail Framework" . $this->delim;
                $headers .= "MIME-Version: 1.0" . $this->delim;
                
                // see if we need to use mime/multipart
-               if ($sendHtml AND !empty($this->bodyHtml) == true)
+               if ($sendhtml && !empty($bodyhtml) == true)
                {
-                       $boundary = 'ISSO-MULTIPART-' . BSFunctions::Rand(10);
+                       require_once ISSO . '/Functions.php';
+                       $boundary = 'ISSO-MULTIPART-' . BSFunctions::random(10);
                        $headers .= "Content-Type: multipart/alternative; boundary=\"$boundary\"" . $this->delim;
                        
-                       $this->bodyHtml = BSFunctions::ConvertLineBreaks($this->bodyHtml, $this->delim);
+                       $bodyHtml = BSFunctions::convert_line_breaks($this->bodyHtml, $this->delim);
                        
                        // first part of the message (plaintext)
                        $body = "--$boundary" . $this->delim;
                        $body .= "Content-Type: text/plain; charset=\"" . $this->charset . "\"" . $this->delim;
                        $body .= "Content-Transfer-Encoding: 8bit" . $this->delim . $this->delim;
-                       $body .= $this->bodyText . $this->delim;
+                       $body .= $bodyText . $this->delim;
                        
                        // add some space between the parts
                        $body .= $this->delim . $this->delim . $this->delim;
@@ -266,49 +262,65 @@ class BSMail
                        $body .= "Content-Type: text/html; charset=\"" . $this->charset . "\"" . $this->delim;
                        $body .= "Content-Transfer-Encoding: 8bit" . $this->delim;
                        $body .= "Content-Disposition: inline" . $this->delim . $this->delim;
-                       $body .= $this->bodyHtml . $this->delim;
+                       $body .= $bodyHtml . $this->delim;
                        $body .= "--$boundary--";
                }
                else
                {
                        $headers .= "Content-Type: text/plain; charset=\"" . $this->charset . "\"" . $this->delim;
-                       $body = $this->bodyText;
+                       $body = $bodyText;
                }
                $headers .= "Content-Transfer-Encoding: 8bit" . $this->delim;
                
                $headers = trim($headers);
 
                // attempt to send the mail!
-               if (mail($tostring, $this->subject, $body, $headers, "-f {$this->from}"))
+               if (mail($tostring, $subject, $body, $headers, "-f {$from}"))
                {
-                       BSRegister::Debug("email: sent to $address");
+                       BSApp::debug("BSMail: sent to $address");
                }
                else
                {
-                       BSRegister::Debug("email: error sending to $address");
+                       BSApp::debug("BSMail: error sending to $address");
                }
        }
        
-       // ###################################################################
        /**
-       * Fetches the first line of a string
-       *
-       * @param        string  A string
-       *
-       * @return       string  The first line of the string
-       */
+        * Fetches the first line of a string
+        *
+        * @param       string  A string
+        *
+        * @return      string  The first line of the string
+        */
        private function _fetchFirstLine($string)
        {
-               $string = BSFunctions::ConvertLineBreaks($string);
+               $string = BSFunctions::convert_line_breaks($string);
                $broken = explode("\n", $string);
                return $broken[0];
        }
+       
+       /**
+        * Encodes a header value (to name, fron name, subject, etc.) according
+        * to RFC 2047
+        *
+        * @param       string  The text to encode
+        *
+        * @return      string  Encoded text
+        */
+       function _encodeHeaderValue($text)
+       {
+               if (preg_match('#[^a-zA-Z0-9\+\-\*!/]#', $text) == 0)
+               {
+                       return $text;
+               }
+               
+               // perform this on non-ASCII characters; excluding _ and = because we want them to be encoded as they have
+               // different meanings in mail messages
+               $text = preg_replace('#([^a-zA-Z0-9\+\-\*!/])#e', '"=" . strtoupper(dechex(ord("\\1")))', $text);
+               $text = str_replace('=20', '_' , $text);
+               
+               return '=?' . $this->charset . '?q?' . $text . '?=';
+       }
 }
 
-/*=====================================================================*\
-|| ###################################################################
-|| # $HeadURL$
-|| # $Id$
-|| ###################################################################
-\*=====================================================================*/
 ?>
\ No newline at end of file