<?php

/**
 * ###############################################
 *
 * SWIFT Framework
 * _______________________________________________
 *
 * @author		Varun Shoor
 *
 * @package		SWIFT
 * @copyright	Copyright (c) 2001-2012, Kayako
 * @license		http://www.kayako.com/license
 * @link		http://www.kayako.com
 *
 * ###############################################
 */

/**
 * The Mail Management Class
 *
 * @author Varun Shoor
 */
class SWIFT_Mail extends SWIFT_Model
{

	private $_addedFieldCount = 0;
	private $SwiftMailer = false;
	private $SwiftMessage = false;
	private $_mailerType = false;
	private $_swiftSMTPResource = false;
	private $_isHTML = false;
	private $_swiftMailContainer = array();
	private $_mailCC = array();
	private $_mailBCC = array();
	private $_mailTo = array();
	private $_mailToEmailList = array();

	// Core Constants
	const TYPE_SWIFTMAILER = 3;

	/**
	 * Constructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __construct($_mailerType = 3)
	{
		parent::__construct();

		$this->_isHTML = intval($this->Settings->Get('cpu_enablehtmlmails'));

		if ($_mailerType == self::TYPE_SWIFTMAILER) {
			$this->_mailerType = self::TYPE_SWIFTMAILER;

			require_once ('./' . SWIFT_BASEDIRECTORY . '/' . SWIFT_THIRDPARTYDIRECTORY . '/SwiftMailer/swiftmailer_required.php');

			$this->SwiftMessage = SwiftMailer_Message::newInstance();

			/**
			 * BUG Fix: Ashish Kataria
			 *
			 * SWIFT-2616 Notifications do not respect the mail encoding configured in Admin CP
			 * SWIFT-2439 Even if you select Base64 and Binary under Outgoing emails, it always use 'Quoted printable' . It doesn't send it in that format that is selected
			 *
			 * Comments: None
			 */
			if ($this->Settings->Get('cpu_messageencoding') == "quoted-printable") {
				$this->SwiftMessage->setEncoder(SwiftMailer_Encoding::getQpEncoding());
			} else if ($this->Settings->Get('cpu_messageencoding') == "base64") {
				$this->SwiftMessage->setEncoder(SwiftMailer_Encoding::getBase64Encoding());
			} else if ($this->Settings->Get('cpu_messageencoding') == "binary") {
				$this->SwiftMessage->setEncoder(SwiftMailer_Encoding::get8BitEncoding());
			}

			$this->SwiftMessage->setPriority(intval($this->Settings->Get('cpu_maildefaultpriority')));
		}

		return true;
	}

	/**
	 * Destructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __destruct()
	{
		parent::__destruct();

		return true;
	}

	/**
	 * Attach a File
	 *
	 * @author Varun Shoor
	 * @param string $_content The Contents of the File
	 * @param string $_mimeType The File Mime TYpe
	 * @param string $_fileName The Filename
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Attach($_content, $_mimeType, $_fileName)
	{
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			$_attachment = SwiftMailer_Attachment::newInstance($_content, $_fileName, $_mimeType);
			$this->SwiftMessage->attach($_attachment);
		}

		return true;
	}

	/**
	 * Sets the From Field for the Outgoing Email
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SetFromField($_emailAddress, $_name = '')
	{

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			$this->SwiftMessage->setFrom(array($_emailAddress => $_name));
			$this->SwiftMessage->setReplyTo($_emailAddress);
			$this->SwiftMessage->setReturnPath($_emailAddress);
		}

		$this->_swiftMailContainer['fromname'] = $_name;
		$this->_swiftMailContainer['fromemail'] = $_emailAddress;

		return true;
	}

	/**
	 * Sets the Destination Email Address
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SetToField($_emailAddress, $_name = '')
	{
		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			if (!empty($_name)) {
				$this->SwiftMessage->addTo($_emailAddress, $_name);
			} else {
				$this->SwiftMessage->addTo($_emailAddress);
			}
		}

		$this->_mailTo[] = array('address' => $_emailAddress, 'name' => $_name);
		$this->_swiftMailContainer['toname'] = $_name;
		$this->_swiftMailContainer['toemail'] = $_emailAddress;

		return true;
	}

	/**
	 * Adds the Destination Email Address
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function AddToField($_emailAddress, $_name = '')
	{
		$_emailAddress = mb_strtolower($_emailAddress);

		if (in_array($_emailAddress, $this->_mailToEmailList)) {
			return true;
		}

		$this->_mailTo[] = array('address' => $_emailAddress, 'name' => $_name);
		$this->_mailToEmailList[] = $_emailAddress;
		$this->_addedFieldCount++;

		return true;
	}

	/**
	 * Sets the Destination Email Address
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function OverrideToField($_emailAddress, $_name = '')
	{
		$_emailAddress = mb_strtolower($_emailAddress);

		if (in_array($_emailAddress, $this->_mailToEmailList)) {
			return true;
		}

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			if (!empty($_name)) {
				$this->SwiftMessage->setTo($_emailAddress, $_name);
			} else {
				$this->SwiftMessage->setTo($_emailAddress);
			}
		}

		$this->_mailTo = array(array('address' => $_emailAddress, 'name' => $_name));
		$this->_swiftMailContainer['toname'] = $_name;
		$this->_swiftMailContainer['toemail'] = $_emailAddress;

		return true;
	}

	/**
	 * Deletes the Destination Email Address
	 *
	 * @author Parminder Singh
	 * @param string $_emailAddress The Email Address (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function DelToField($_emailAddress = '')
	{
	}

	/**
	 * Sets the Email Subject
	 *
	 * @author Varun Shoor
	 * @param string $_subject The Email Subject
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SetSubjectField($_subject)
	{
		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			$this->SwiftMessage->setSubject($_subject);
		}

		$this->_swiftMailContainer['subject'] = $_subject;

		return true;
	}

	/**
	 * Sets the Data As Text
	 *
	 * @author Varun Shoor
	 * @param string $_content The Content Holder
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SetDataText($_content)
	{
		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			$this->SwiftMessage->setBody($_content, 'text/plain');
		}

		$this->_swiftMailContainer['text'] = $_content;

		return true;
	}

	/**
	 * Sets the Data as HTML
	 *
	 * @author Varun Shoor
	 *
	 * @param string $_content
	 * @param bool   $_forceHTML
	 *
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SetDataHTML($_content, $_forceHTML = false)
	{
		$this->_swiftMailContainer['html'] = '';

		if ($this->Settings->Get('cpu_enablehtmlmails') != '1' && $_forceHTML == false) {
			return false;
		}

		$_content = AutoLink($_content);

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {

			// Checking whether we have already set text content, then add as multipart
			if (!empty($this->_swiftMailContainer['text'])) {
				$this->SwiftMessage->addPart($_content, 'text/html');
			} else {
				$this->SwiftMessage->setBody($_content, 'text/html');
			}
		}

		$this->_isHTML = true;

		$this->_swiftMailContainer['html'] = $_content;

		return true;
	}

	/**
	 * Gets the Probable Local Hostname for this System
	 *
	 * @author Varun Shoor
	 * @return string Local Hostname
	 */
	static public function GetMailLocalHost()
	{
		if (!empty($_SERVER['SERVER_NAME'])) {
			return $_SERVER['SERVER_NAME'];
		}

		if (!empty($_SERVER['HTTP_HOST'])) {
			return $_SERVER['HTTP_HOST'];
		}

		if (!empty($_SERVER['HOST'])) {
			return $_SERVER['HOST'];
		}

		return "localhost";
	}

	/**
	 * Add a CC Recipient
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function AddCC($_emailAddress, $_name = '')
	{
		if (!$this->GetIsClassLoaded() || empty($_emailAddress)) {
			return false;
		}

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			if (!empty($_name)) {
				$this->SwiftMessage->addCc($_emailAddress, $_name);
			} else {
				$this->SwiftMessage->addCc($_emailAddress);
			}
		}

		$this->_mailCC[] = array('address' => $_emailAddress, 'name' => $_name);

		return true;
	}

	/**
	 * Add a BCC Recipient
	 *
	 * @author Varun Shoor
	 * @param string $_emailAddress The Email Address
	 * @param string $_name The Name (OPTIONAL)
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function AddBCC($_emailAddress, $_name = '')
	{
		if (!$this->GetIsClassLoaded() || empty($_emailAddress)) {
			return false;
		}

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			if (!empty($_name)) {
				$this->SwiftMessage->addBcc($_emailAddress, $_name);
			} else {
				$this->SwiftMessage->addBcc($_emailAddress);
			}
		}

		$this->_mailBCC[] = array('address' => $_emailAddress, 'name' => $_name);

		return true;
	}

	/**
	 * Connects to SMTP Server
	 *
	 * @author Varun Shoor
	 * @param int $_emailQueueID (OPTIONAL) The Email Queue ID for Custom SMTP Dispatch
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function ConnectSMTP($_emailQueueID = false)
	{
		$_emailQueueCache = $this->Cache->Get('queuecache');

		$_smtpHost = $this->Settings->Get('cpu_smtphost');

		$_smtpPort = false;

		if ($this->Settings->Get('cpu_smtptype') == 'nonssl') {
			$_smtpPort = $this->Settings->Get('cpu_smtpport');
		} else {
			$_smtpPort = $this->Settings->Get('cpu_smtpportssl');
		}

		$_smtpVssl = $this->Settings->Get('cpu_smtptype');

		$_smtpUser = $_smtpPass = '';

		if ($this->Settings->Get('cpu_smtpuseauth') == '1') {
			$_smtpUser = $this->Settings->Get('cpu_smtpuser');
			$_smtpPass = $this->Settings->Get('cpu_smtppass');
		}

		if (!empty($_emailQueueID) && isset($_emailQueueCache['list'][$_emailQueueID]) && SWIFT_App::IsInstalled(APP_PARSER)) {
			SWIFT_Loader::LoadModel('EmailQueue:EmailQueue', APP_PARSER);
			$_SWIFT_EmailQueueObject = SWIFT_EmailQueue::RetrieveStore($_emailQueueCache['list'][$_emailQueueID]);

			if ($_SWIFT_EmailQueueObject instanceof SWIFT_EmailQueue && $_SWIFT_EmailQueueObject->GetIsClassLoaded() && $_SWIFT_EmailQueueObject->GetProperty('usequeuesmtp') == '1') {
				$_smtpUser = $_SWIFT_EmailQueueObject->GetProperty('username');
				$_smtpPass = $_SWIFT_EmailQueueObject->GetProperty('userpassword');
				$_smtpHost = $_SWIFT_EmailQueueObject->GetProperty('host');
				$_smtpVssl = $_SWIFT_EmailQueueObject->GetProperty('smtptype');
			}
		}


		// We reset the value if we arent using SSL.
		if ($_smtpVssl == 'nonssl') {
			$_smtpVssl = null;
		}

		if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
			/*
			 * BUG FIX - Varun Shoor
			 *
			 * SWIFT-1300 SMTP does not works with SMTP Type TLS
			 *
			 * Comments: None
			 */
			$_smtpResource = false;
			if ($_smtpVssl == 'tls') {
				$_smtpResource = SwiftMailer_SmtpTransport::newInstance($_smtpHost, $_smtpPort, $_smtpVssl)
						->setEncryption('tls')
						->setUsername($_smtpUser)
						->setPassword($_smtpPass);
			} else {
				$_smtpResource = SwiftMailer_SmtpTransport::newInstance($_smtpHost, $_smtpPort, $_smtpVssl)
						->setUsername($_smtpUser)
						->setPassword($_smtpPass);
			}

			if (!is_object($_smtpResource)) {
				SWIFT_ErrorLog::Create(SWIFT_ErrorLog::TYPE_MAILERROR, $this->Language->Get('errorsmtpconnect'), '');
			}

			$this->_swiftSMTPResource = $_smtpResource;

			return $_smtpResource;
		}

		return false;
	}

	/**
	 * Retrieves the combined email list of To, CC & BCC Emails
	 *
	 * @author Varun Shoor
	 * @return array Email List Holder
	 */
	private function GetEmailList()
	{
		$_emailList = array();

		// ======= TO =======
		if (_is_array($this->_mailTo)) {
			foreach ($this->_mailTo as $_key => $_val) {
				if (!in_array(strtolower($_val['address']), $_emailList)) {
					$_emailList[] = strtolower($_val['address']);
				}
			}
		}

		// ======= CC =======
		if (_is_array($this->_mailCC)) {
			foreach ($this->_mailCC as $_key => $_val) {
				if (!in_array(strtolower($_val['address']), $_emailList)) {
					$_emailList[] = strtolower($_val['address']);
				}
			}
		}

		// ======= BCC =======
		if (_is_array($this->_mailBCC)) {
			foreach ($this->_mailBCC as $_key => $_val) {
				if (!in_array(strtolower($_val['address']), $_emailList)) {
					$_emailList[] = strtolower($_val['address']);
				}
			}
		}

		return $_emailList;
	}

	/**
	 * Sends the Mail
	 *
	 * @author Varun Shoor
	 * @param bool $_useMailQueue Whether or not to use the inbuilt Mail Queue for dispatching email
	 * @param int $_emailQueueID (OPTIONAL) The Email Queue ID to check for custom SMTP server
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function SendMail($_useMailQueue = false, $_emailQueueID = false)
	{
		// Check to see if mail queue is enabled
		if ($this->Settings->Get('cpu_enablemailqueue') != 1) {
			$_useMailQueue = false;
		}

		$_result = false;

		// Check to see if we need to use smtp
		$_mailType = 'mail';
		$_smtpResource = false;

		if ($this->Settings->Get('cpu_enablesmtp') == '1') {
			$_mailType = 'smtp';

			if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
				$_smtpResource = $this->ConnectSMTP($_emailQueueID);
			}
		}

		if (!$_useMailQueue) {
			if ($this->_mailerType == self::TYPE_SWIFTMAILER) {
				if ($_mailType == 'smtp') {
					$this->SwiftMailer = SwiftMailer_Mailer::newInstance($_smtpResource);
					$_result = $this->SwiftMailer->send($this->SwiftMessage);
				} else {
					$_localResource = SwiftMailer_MailTransport::newInstance();
					$this->SwiftMailer = SwiftMailer_Mailer::newInstance($_localResource);
					$_result = $this->SwiftMailer->send($this->SwiftMessage);
				}
			}
		} else {
			$this->Load->Model('Mail:MailQueueManager');

			foreach ($this->GetEmailList() as $_val) {
				$this->MailQueueManager->AddToQueue($_val, $this->_swiftMailContainer['fromemail'], $this->_swiftMailContainer['fromname'], $this->_swiftMailContainer['subject'], $this->_swiftMailContainer['text'], $this->_swiftMailContainer['html'], IIF(!empty($this->_isHTML), '1', '0'), false);
			}

			$this->MailQueueManager->RecountMailQueue();
			$this->MailQueueManager->ProcessMailQueue();
		}

		return $_result;
	}

}

?>