View file fs-phpfox340b2/upload/include/library/phpfox/mail/mail.class.php

File size: 19.08Kb
<?php
/**
 * [PHPFOX_HEADER]
 */

defined('PHPFOX') or exit('NO DICE!');

Phpfox::getLibClass('phpfox.mail.interface');

/**
 * Email Driver Layer
 * Our email loads a 3rd party email class that usually has support for both sendmail and smtp.
 * 
 * Example:
 * <code>
 * Phpfox::getLib('mail')->to('foo@bar.com')
 * 		->subject('Test Subject')
 * 		->message('Test Message')
 * 		->send();
 * </code>
 * 
 * @copyright		[PHPFOX_COPYRIGHT]
 * @author			Raymond Benc
 * @package 		Phpfox
 * @version 		$Id: mail.class.php 4578 2012-07-31 13:07:50Z Miguel_Espinoza $
 */
class Phpfox_Mail
{
	/**
	 * Object of the 3rd party library we are using to send the actual image.
	 *
	 * @var object
	 */
	private $_oMail = null;
	
	/**
	 * STRING or ARRAY of emails or users to send the emai to.
	 *
	 * @var mixed
	 */
	private $_mTo = null;
	
	/**
	 * ARRAY if loading a phrase or STRING if we are passing a subject.
	 *
	 * @var mixed
	 */
	private $_aSubject = null;
	
	/**
	 * The name of the person sending the email.
	 *
	 * @var string
	 */
	private $_sFromName = null;
	
	/**
	 * The email of the person sending the email.
	 *
	 * @var string
	 */
	private $_sFromEmail = null;
	
	/**
	 * Notification ID to be used to check if a user has privacy settings on receiving an email.
	 *
	 * @var string
	 */
	private $_sNotification = null;
	
	/**
	 * ARRAY of users to email and their information.
	 *
	 * @var array
	 */
	private $_aUsers = null;
	
	/**
	 * ARRAY of loading a phrase or STRING of we are passing the message directly.
	 *
	 * @var mixed
	 */
	private $_aMessagePlain = null;
	
	/**
	 * TRUE to send the message to ourself and FALSE to not.
	 *
	 * @var bool
	 */
	private $_bSendToSelf = false;
	
	/**
	 * Controlls if we should include the default header in the message. Default is TRUE.
	 *
	 * @var bool
	 */
	private $_bMessageHeader = true;
	
	/**
	 * ARRAY of loading a phrase or STRING of we are passing the message directly.
	 *
	 * @var mixed
	 */
	private $_aMessage = null;
	
	/**
	 * Used for global replacements like site_name and site_email
	 * @var String 
	 */
	private $_sArray = 'array()';
	/**
	 * Class constructor that loads a specific method of sending emails (sendmail or smtp)
	 *
	 * @param string $sMethod Method to send an email (sendmail or smtp)
	 */
	public function __construct($sMethod = null)
    {    	
    	$this->_oMail = Phpfox::getLib('mail.driver.phpmailer.' . ($sMethod === null ? Phpfox::getParam('core.method') : $sMethod));
		$this->_sArray = 'array("site_name" => "'.Phpfox::getParam('core.site_title').'","site_email" => "'.Phpfox::getParam('core.email_from_email').'")';
    }    
    
    /**
     * Run a test if we are able to send out an email using the default method being loaded.
     *
     * @param array $aVals ARRAY of values to test.
     * @return object Returns this class.
     */
    public function test($aVals)
    {
    	$this->_oMail->test($aVals);
    	
    	return $this;
    }
    
    /**
     * Identify who this email will be sent to. Can be an actual email or a user ID or an array of 
     * emails or user IDs.
     *
     * @param mixed $mTo ARRAY of emails/users or STRING of email/user
     * @return object Returns this class.
     */
    public function to($mTo)
    {    	
    	$this->_mTo = $mTo;
    	
    	return $this;
    }
    
    /**
     * Subject of the email.
     *
     * @param mixed $aSubject ARRAY if loading a phrase or STRING if we are passing a subject.
     * @return object Returns this class.
     */
    public function subject($aSubject)
    {
		$this->_aSubject = $aSubject;
		
		return $this;
    }
    
    /**
     * The name of the person sending out the email.
     *
     * @param string $sFromName Persons name.
     * @return object Returns this class.
     */
    public function fromName($sFromName)
    {
    	$this->_sFromName = $sFromName;
    	
    	return $this;
    }
    
    /**
     * Send a copy to our own email.
     *
     * @param bool $bSendToSelf TRUE will send a copy and FALSE will not.
     * @return object Returns this class.
     */
    public function sendToSelf($bSendToSelf)
    {
    	$this->_bSendToSelf = $bSendToSelf;
    	
    	return $this;
    }
    
    /**
     * Email of the person sending out this email.
     *
     * @param string $sFromEmail Email.
     * @return object Returns this class.
     */
    public function fromEmail($sFromEmail)
    {
    	$this->_sFromEmail = $sFromEmail;
    	
    	return $this;
    }
    
    /**
     * Notification param for this specific email to check a users privacy settings.
     *
     * @param string $sNotification Param of the notification.
     * @return object Returns this class.
     */
    public function notification($sNotification)
    {
    	$this->_sNotification = $sNotification;
    	
    	return $this;
    }
    
    /**
     * Message of the email.
     *
     * @param mixed $aMessage ARRAY of loading a phrase or STRING of we are passing the message directly.
     * @return object Returns this class.
     */
    public function message($aMessage)
    {
		if (is_array($aMessage))
		{
			if (!isset($aMessage[1]['site_name']))
			{
				$aMessage[1]['site_name'] = Phpfox::getParam('core.site_title');
			}
			if (!isset($aMessage[1]['site_url']))
			{
				$aMessage[1]['site_url'] = Phpfox::getLib('url')->getDomain();
			}
		}
		$this->_aMessage = $aMessage;

    	return $this;    	
    }
    
    /**
     * Identify if we should load the message header we include by default.
     *
     * @param bool $bMessageHeader Controlls if we should include the default header in the message. Default is TRUE.
     * @return object Returns this class.
     */
    public function messageHeader($bMessageHeader)
    {
    	$this->_bMessageHeader = $bMessageHeader;
    	
    	return $this;
    }

    /**
     * Message of the email (Plain Text).
     *
     * @param mixed $aMessage ARRAY of loading a phrase or STRING of we are passing the message directly.
     * @return object Returns this class.
     */    
	public function messagePlain($aMessage)
	{		
		$this->_aMessagePlain = $aMessage;

		return $this;
	}

	/**
	 * We load users information in our send() method, however you can also load users by passing
	 * an array of their information with this method.
	 *
	 * @param array $aUser ARRAY of users information.
	 * @return object Returns this class.
	 */
	public function aUser($aUser)
	{
		if (!isset($aUser['user_id']) || !isset($aUser['full_name']) || !isset($aUser['email']))
		{
			// Phpfox_Error::set('aUser incomplete');
		}
		$this->_aUsers[] = ($aUser);

		return $this;
	}
	
	/**
	 * Email address validator based on http://www.linuxjournal.com/article/9585 and RFC 2821
	 * Uses recursion for arrays
	 * 
	 * @param mixed $mEmail array|string
	 * @return boolean true if all valid
	 */
	public function checkEmail($mEmail)
	{
		if (is_array($mEmail))
		{			
			foreach($mEmail as $sEmail)
			{
				if (!$this->_checkEmail($sEmail, Phpfox::getParam('core.use_dnscheck')))
				{
					// return here before keep going					
					return false;
				}
			}
			return true;
		}
		return $this->_checkEmail($mEmail);		
	}

    /**
     * Method to send out the email.
     * Checks: 
     * 		(message || to) === null -> return false;
     * 		(sFromName || sFromEmail) === null -> getParam(core.
     * 		(Notification) assumes to is an array of integers, otherwise return false
	 *
	 * @example Phpfox::getLib('mail')->to('user@email.com')->subject('Test Subject')->message('This is a test message')->send();
     * @example Phpfox::getLib('mail')->to(array('user1@email.com', 'user2@email.com', 'user3@email.com')->subject('Test Subject')->message('This is a test message')->send()
     * @return boolean
     */
    public function send($bDoCheck = false)
    {		
		if (defined('PHPFOX_SKIP_MAIL'))
		{
			return true;
		}
    	
    	// turn into an array
    	if (!is_array($this->_mTo))
    	{
    		$this->_mTo = array($this->_mTo);
    	}

		// check if the mail(s) are valid
		if ($bDoCheck && $this->checkEmail($this->_mTo) == false)
		{			
			return false;
		}

    	if ($this->_aMessage === null || $this->_mTo === null)
    	{
    		return false;
    	}
    	
    	if ($this->_sFromName === null)
		{
			$this->_sFromName = Phpfox::getParam('core.mail_from_name');
		}
		
		if ($this->_sFromEmail === null)
		{
			$this->_sFromEmail = Phpfox::getParam('core.email_from_email');
		}
		
		$this->_sFromName = html_entity_decode($this->_sFromName, null, 'UTF-8');
		
		$sIds = '';
		$sEmails = '';

		if (!empty($this->_aUsers))
		{
			foreach ($this->_aUsers as $aUser)
			{
				if (isset($aUser['user_id']) && !empty($aUser['user_id']))
				{
					$sIds .= (int) $aUser['user_id'] . ',';
				}
			}
		}
		else
		{
			foreach ($this->_mTo as $mTo)
			{
				if (strpos($mTo, '@'))
				{
					$sEmails .= $mTo . ',';
				}
				else
				{
					$sIds .= (int) $mTo . ',';
				}
			}			
		}
		$sIds = rtrim($sIds, ',');
		$sEmails = rtrim($sEmails, ',');
		
		$bIsSent = true;		
		
		if (!empty($sIds))
		{
			if ($this->_sNotification !== null)
			{
				Phpfox::getLib('database')->select('un.user_notification, ')->leftJoin(Phpfox::getT('user_notification'), 'un', "un.user_id = u.user_id AND un.user_notification = '" . Phpfox::getLib('database')->escape($this->_sNotification) . "'");
			}		
			
			(($sPlugin = Phpfox_Plugin::get('mail_send_query')) ? eval($sPlugin) : false);
			
			if ($this->_aUsers === null)
		    {
				$aUsers = Phpfox::getLib('database')->select('u.user_id, u.email, u.language_id, u.full_name, u.user_group_id')
					->from(Phpfox::getT('user'), 'u')
					->where('u.user_id IN(' . $sIds . ')')
					->execute('getSlaveRows');
			}
			else
			{
				$aUsers = $this->_aUsers;
			}
		    if (!empty($aUsers) && count($aUsers) > 0)
			{			    
				foreach ($aUsers as $aUser)
				{
					// User is banned, lets not send them any emails
					if (isset($aUser['user_group_id']) && Phpfox::getService('user.group.setting')->getGroupParam($aUser['user_group_id'], 'core.user_is_banned'))
					{
						continue;
					}
					
					// Lets not send out an email to myself					
					if ($this->_bSendToSelf === false && $aUser['user_id'] == Phpfox::getUserId())
					{
						continue;
					}
					
					$bCanSend = true;
					if ($this->_sNotification !== null && $aUser['user_notification'])
					{						
						$bCanSend = false;
					}
					
					if ($bCanSend === true)
					{						
						// load the messages in their language						
						$aUser['language_id'] = ($aUser['language_id'] == null || empty($aUser['language_id'])) ?  Phpfox::getParam('core.default_lang_id') : $aUser['language_id'];
						
						if (is_array($this->_aMessage))
						{
							$sMessage = Phpfox::getPhrase($this->_aMessage[0], isset($this->_aMessage[1]) ? array_merge($aUser, $this->_aMessage[1]) : $aUser, false, null, $aUser['language_id']);
						}
						else
						{
							$sMessage = $this->_aMessage;
						} 
						
						if (is_array($this->_aMessagePlain))
						{
							$sMessagePlain = Phpfox::getPhrase($this->_aMessagePlain[0], isset($this->_aMessagePlain[1]) ? array_merge($aUser, $this->_aMessagePlain[1]) : $aUser, false, null, $aUser['language_id']);
						}
						else
						{
							$sMessagePlain = $this->_aMessagePlain;
						}

						$sMessage = preg_replace('/' . preg_quote(Phpfox::getLib('url')->makeUrl(''), '/') . '/is', str_replace('mobile/', '', Phpfox::getLib('url')->makeUrl('')), $sMessage);
						$sMessagePlain = preg_replace('/' . preg_quote(Phpfox::getLib('url')->makeUrl(''), '/') . '/is', str_replace('mobile/', '', Phpfox::getLib('url')->makeUrl('')), $sMessagePlain);
						
						if (is_array($this->_aSubject))
						{
							$sSubject = Phpfox::getPhrase($this->_aSubject[0], isset($this->_aSubject[1]) ? array_merge($aUser,$this->_aSubject[1]) : $aUser, false, null, $aUser['language_id']);
						}
						else
						{
							$sSubject = $this->_aSubject;
						}

						$sMessage = preg_replace('/\{setting var=\'(.*)\'\}/ise', "'' . Phpfox::getParam('\\1') . ''", $sMessage);
						$sMessage = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1',{$this->_sArray}, false, null, '".$aUser['language_id']."') . ''", $sMessage);
						$sMessagePlain = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1',{$this->_sArray}, false, null, '".$aUser['language_id']."') . ''", $sMessagePlain);
						$sMessagePlain = preg_replace('/\{setting var=\'(.*)\'\}/ise', "'' . Phpfox::getParam('\\1') . ''", $sMessagePlain);
						$sSubject = preg_replace('/\{setting var=\'(.*)\'\}/ise', "'' . Phpfox::getParam('\\1') . ''", $sSubject);
						$sSubject = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1',{$this->_sArray}, false, null, '".$aUser['language_id']."') . ''", $sSubject);
						// $sSubject = html_entity_decode($sSubject, null, 'UTF-8'); // http://www.phpfox.com/tracker/view/10392/
						$sEmailSig = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1',{$this->_sArray}, false, null, '".$aUser['language_id']."') . ''", Phpfox::getParam('core.mail_signature'));
						
						// Load plain text template
						$sTextPlain = Phpfox::getLib('template')->assign(array(
									'sName' => $aUser['full_name'],
									'bHtml' => false,
									'sMessage' => $this->_aMessagePlain !== null ? $sMessagePlain : $sMessage,
									'sEmailSig' => $sEmailSig,
									'bMessageHeader' => $this->_bMessageHeader
								)
							)->getLayout('email', true);

						// Load HTML text template
						$sTextHtml = Phpfox::getLib('template')->assign(array(
									'sName' => $aUser['full_name'],
									'bHtml' => true,
									'sMessage' => str_replace("\n", "<br />", $sMessage),
									'sEmailSig' => str_replace("\n", "<br />", $sEmailSig),
									'bMessageHeader' => $this->_bMessageHeader
								)
							)->getLayout('email', true);
						
						if (defined('PHPFOX_DEFAULT_OUT_EMAIL'))
						{
							$aUser['email'] = PHPFOX_DEFAULT_OUT_EMAIL;
						}
						
						(($sPlugin = Phpfox_Plugin::get('mail_send_call')) ? eval($sPlugin) : false);
						
						if (empty($aUser['email']))
						{
							continue;
						}
						
						if (!isset($bSkipMailSend))
						{
							$bIsSent = (defined('PHPFOX_CACHE_MAIL') ? $this->_cache($aUser['email'], $sSubject, $sTextPlain, $sTextHtml, $this->_sFromName, $this->_sFromEmail) : $this->_oMail->send($aUser['email'], $sSubject, $sTextPlain, $sTextHtml, $this->_sFromName, $this->_sFromEmail));
						}
					}					
				}
			}	
		}
		
		
		if (!empty($sEmails))
		{			
			$aEmails = explode(',', $sEmails);
			foreach ($aEmails as $sEmail)
			{
				$sEmail = trim($sEmail);

				if (is_array($this->_aMessage))
				{
					$sMessage = Phpfox::getPhrase($this->_aMessage[0], $this->_aMessage[1], false, null, Phpfox::getParam('core.default_lang_id'));
				}
				else
				{
					$sMessage = $this->_aMessage;
				}
				if (is_array($this->_aMessagePlain))
				{
					$sMessagePlain = Phpfox::getPhrase($this->_aMessagePlain[0], $this->_aMessagePlain[1], false, null, Phpfox::getParam('core.default_lang_id'));
				}
				else
				{
					$sMessagePlain  = $this->_aMessagePlain;
				}
				if (is_array($this->_aSubject))
				{
					$sSubject = Phpfox::getPhrase($this->_aSubject[0], $this->_aSubject[1], false, null, Phpfox::getParam('core.default_lang_id'));
				}
				else
				{
					$sSubject = $this->_aSubject;
				}
				$sEmailSig = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1', {$this->_sArray}, false, null, '". Phpfox::getParam('core.default_lang_id')."') . ''", Phpfox::getParam('core.mail_signature'));
				$sMessagePlain = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1', {$this->_sArray}, false, null, '". Phpfox::getParam('core.default_lang_id')."') . ''", $sMessagePlain);
				$sMessage = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1', {$this->_sArray}, false, null, '". Phpfox::getParam('core.default_lang_id')."') . ''", $sMessage);
				$sSubject = preg_replace('/\{phrase var=\'(.*)\'\}/ise', "'' . Phpfox::getPhrase('\\1', {$this->_sArray}, false, null, '". Phpfox::getParam('core.default_lang_id')."') . ''", $sSubject);
				
				// Load plain text template
				$sTextPlain = Phpfox::getLib('template')->assign(array(				
						'bHtml' => false,
						'sMessage' => $this->_aMessagePlain !== null ? $sMessagePlain : $sMessage,
						'sEmailSig' => $sEmailSig,
						'bMessageHeader' => $this->_bMessageHeader
					)
				)->getLayout('email', true);
						
				// Load HTML text template
				$sTextHtml = Phpfox::getLib('template')->assign(array(
						'bHtml' => true,
						'sMessage' => str_replace("\n", "<br />", $sMessage),
						'sEmailSig' => str_replace("\n", "<br />", $sEmailSig),
						'bMessageHeader' => $this->_bMessageHeader
					)
				)->getLayout('email', true);	
				
				if (empty($sEmail))
				{
					continue;
				}
				
				$bIsSent = (defined('PHPFOX_CACHE_MAIL') ? $this->_cache($sEmail, $sSubject, $sTextPlain, $sTextHtml, $this->_sFromName, $this->_sFromEmail) : $this->_oMail->send($sEmail, $sSubject, $sTextPlain, $sTextHtml, $this->_sFromName, $this->_sFromEmail));
			}
		}
		$this->_aUsers = null;
		return $bIsSent;
    }
    
    private function _cache($sEmail, $sSubject, $sTexPlain, $sTextHtml, $sFromName, $sFromEmail)
    {    	
    	Phpfox::getLib('file')->write(PHPFOX_DIR_FILE . 'log' . PHPFOX_DS . 'email_' . md5(str_replace(' ', '_', $this->_aSubject) . PHPFOX_TIME . uniqid()) . '.html', "<b>Email:</b> {$sEmail}<br />\n<b>Subject:</b> {$sSubject}\n<br /><b>Text Plan:</b>{$sTexPlain}\n<br /><b>Text HTML:</b> {$sTextHtml}\n<br /><b>From Name:</b> {$sFromName}\n<br /><b>From Email:</b> {$sFromEmail}");
    	
    	return true;
    }
    
	/**
	 * Checks to validate an email.
	 * 
	 * @param string $sEmail email to check
	 * @param boolean $bDoDnsCheck http://php.net/checkdnsrr check for domain name, this could slow down the function so use wisely
	 * @return boolean
	 */
	private function _checkEmail($sEmail, $bDoDnsCheck = false)
	{		
		$iAtIndex = strrpos($sEmail, "@");
		
		if ($iAtIndex === false)
		{ // there is no @ symbol
		   return false;
		}

		$sDomain = substr($sEmail, $iAtIndex+1);
		$sLocal = substr($sEmail, 0, $iAtIndex);

		$iDomainLen = strlen($sDomain);
		$iLocalLen = strlen($sLocal);

		
		if ( ($iLocalLen < 1) || ($iLocalLen > 64) || ($iDomainLen < 1) || ($iDomainLen > 255))
		{ // either the user or the domain are not within valid values
			return false;
		}
		
		if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$sLocal)))
		{
		   // character not valid in local part unless
		   // local part is quoted
		   if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$sLocal)))
		   {
			  return false;
		   }
		}

		// check for dots according to RFC 2822 3.2.4
		if ($sLocal[0] == '.' || $sLocal[$iLocalLen-1] == '.' || preg_match('/\\.\\./', $sLocal))
		{
		   // local starts or ends with a dot or has 2 consecutive dots
		   return false;
		}
		// validate domain
		if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $sDomain) || (preg_match('/\\.\\./', $sDomain)))
		{
		   // Domain has 2 consecutive dots or invalid characters
		   return false;
		}
		elseif ($bDoDnsCheck == true && function_exists('checkdnsrr')
			&& !(checkdnsrr($sDomain,"MX") || checkdnsrr($sDomain, "A")))
		{
		   // domain not found in DNS
		   return false;
		}

		return true;
	}   
}

?>