Deprecated: Assigning the return value of new by reference is deprecated in /home/bluestat/public_html/source/index.php on line 477
ISSO - Blob - ViewGit - Blue Static
<?php
/*=====================================================================*\
|| ###################################################################
|| # Blue Static ISSO Framework
|| # 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 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
|| # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|| # more details.
|| #
|| # You should have received a copy of the GNU General Public License along
|| # with this program; if not, write to the Free Software Foundation, Inc.,
|| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|| ###################################################################
\*=====================================================================*/

/**
 * Mail Sender (mail.php)
 *
 * @package	ISSO
 */

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 (c)2005 - 2009, Blue Static
 * @package		ISSO
 *
 */
class BSMail
{
	/**
	 * The subject of the message
	 * @var	string
	 */
	private $subject = '';

	/**
	 * Body plain-text of the message
	 * @var	string
	 */
	private $bodyText = '';

	/**
	 * HTML multi-part body of the message
	 * @var	string
	 */
	private $bodyHtml = '';

	/**
	 * The message sender's email address
	 * @var	string
	 */
	private $from = '';

	/**
	 * The message sender's display name
	 * @var	string
	 */
	private $fromName = '';

	/**
	 * Additional message headers
	 * @var	string
	 */
	private $headers = '';

	/**
	 * 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
	 */
	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
	 */
	public function setSubject($subject)
	{
		$this->subject = $subject;
	}

	/**
	 * 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
	 */
	public function setBodyHtml($body)
	{
		$this->bodyHtml = $body;
	}

	/**
	 * 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
	 */
	public function setFromName($name)
	{
		$this->fromName = $name;
	}

	/**
	 * 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
	 */
	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)
	{
		if (empty($address))
		{
			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'))
		{
			BSApp::debug("BSMail: no sendmail -> not sending");
			return false;
		}

		// sort out the to addresses
		$address = $this->_fetchFirstLine($address);
		$address = trim(BSApp::$input->unsanitize($address));
		$name = $this->_fetchFirstLine($name);
		$name = trim(BSApp::$input->unsanitize($name));
		$tostring = ($name == null ?  $address : "\"$name\" <$address>");

		// sanitize the from field
		$from = $this->_fetchFirstLine($this->from);
		$from = trim(BSApp::$input->unsanitize($from));
		if (empty($from))
		{
			throw new Exception('You need to specify a from email address');
		}

		// sanitize the from name
		$fromName = $this->_fetchFirstLine($this->fromName);
		$fromName = ($fromName == '' ? $from : trim(BSApp::$input->unsanitize($fromName)));
		$fromName = $this->_encodeHeaderValue($this->fromName);

		// sanitize the subject
		$subject = $this->_fetchFirstLine($this->subject);
		$subject = trim(BSApp::$input->unsanitize($subject));
		if (empty($subject))
		{
			throw new Exception('You need to specify a subject for the message');
		}

		// sanitize the body
		$bodyText = BSFunctions::convert_line_breaks($this->bodyText, $this->delim);
		$bodyText = trim(BSApp::$input->unsanitize($bodyText, true));
		if (empty($bodyText))
		{
			throw new Exception('You need to specify body text before sending the message');
		}

		// attach additional headers
		$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 && !empty($bodyhtml) == true)
		{
			require_once ISSO . '/Functions.php';
			$boundary = 'ISSO-MULTIPART-' . BSFunctions::random(10);
			$headers .= "Content-Type: multipart/alternative; boundary=\"$boundary\"" . $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 .= $bodyText . $this->delim;

			// add some space between the parts
			$body .= $this->delim . $this->delim . $this->delim;

			// second part (html)
			$body .= "--$boundary" . $this->delim;
			$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 .= $bodyHtml . $this->delim;
			$body .= "--$boundary--";
		}
		else
		{
			$headers .= "Content-Type: text/plain; charset=\"" . $this->charset . "\"" . $this->delim;
			$body = $bodyText;
		}
		$headers .= "Content-Transfer-Encoding: 8bit" . $this->delim;

		$headers = trim($headers);

		// attempt to send the mail!
		if (mail($tostring, $subject, $body, $headers, "-f {$from}"))
		{
			BSApp::debug("BSMail: sent to $address");
		}
		else
		{
			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
	 */
	private function _fetchFirstLine($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 . '?=';
	}
}

?>