<?php
/*
	DevSaver Web Framework
	Copyright (c) 2002-2018 DevSaver. 
	All rights reserved.
		web:  www.devsaver.com
		mail: support@devsaver.com
*/

if (!defined("STPBase")) {
	die("This file can't be accessed directly!");
}
// dependencies

/**
* description
*
* @library	
* @author	
* @since	
*/
class CMailBackend extends CPlugin{
	
	var $tplvars; 

	function __construct() {
		//$this->CPlugin($db, $tables , $templates);
		$this->name = "mail";
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function GetMail($code , $vars = array()) {
		global $_LANG_ID;

		//try to read from cache
		if ($this->cache_mails[$code]) {

			$mail = $this->cache_mails[$code];

		} else {

			if ($_LANG_ID) {
				$mail = $this->db->QFetchArray(
					"SELECT * FROM 
						{$this->tables['plugin:mail_emails']} as e, 
						{$this->tables['plugin:mail_emails_lang']} as l

						WHERE 
							e.email_id=l.email_id AND 
							l.lang_id={$_LANG_ID} AND 
							email_status=1 AND 
							email_code LIKE '{$code}'
					"
				);
			} else {
				//this is the admin case so work with the default language 
				$mail = $this->db->QFetchArray(
					"SELECT * FROM 
						{$this->tables['core:languages']} as lang, 
						{$this->tables['plugin:mail_emails']} as e, 
						{$this->tables['plugin:mail_emails_lang']} as l

						WHERE 
							e.email_id=l.email_id AND 
							l.lang_id=lang.lang_id AND 
							lang.lang_default=1 AND 
							email_status=1 AND 
							email_code LIKE '{$code}'
					"
				);

			}
			

			$this->cache_mails[$code] = $mail;

		}

		if (!is_array($mail)) {
			return null;
		}
		
		

		if (is_array($vars) && count($vars)) {

			$vars_to_replace = array(
				"email_subject",
				"email_from",
				"email_from_name",
				"email_to",
				"email_to_name",
				"email_replyto",
				"email_replyto_name",
				"email_body"
			);

			foreach ($vars_to_replace as $key => $val) {
				$mail[$val] = CTemplateStatic::Replace(
					$mail[$val],
					$vars
				);
			}			
		}
		

		return $mail;
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function AddToQueue($data) {

		$this->db->QueryInsert(
			$this->tables["plugin:mail_queue"],
			array(
				"mail_date"			=> time(),
				"mail_from_name"	=> $data["email_from_name"],
				"mail_from_email"	=> $data["email_from"],
				"mail_to_name"		=> $data["email_to_name"],
				"mail_to_email"		=> $data["email_to"],
				"mail_subject"		=> $data["email_subject"],
				"mail_body"			=> $data["email_body"],
				"mail_type"			=> "html",
				"mail_status"		=> "0",
				"mail_priority"		=> $data["priority"] ? $data["priority"]  : "5",
			)
		);

		return true;
	}
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function SendMail() {
		global $_CONF;


		$params = AStripSlashes(func_get_args());	
		//check to see the numbers of the arguments

		//debug($params);

		switch (func_num_args()) {
			case 1:
				$email = $params[0];
				$vars = array();
			break;

			case 2:
				$email = $params[0];
				$vars = $params[1];
			break;

			case 3:
				$to = $params[0];
				$email = $params[1];
				$vars = $params[2];
			break;

			case 4:
				$to = $params[0];
				$to_name = $params[1];
				$email = $params[2];
				$vars = $params[3];
			break;
		}

		if (isset($email["email_status"]) && !$email["email_status"]) {
			return false;
		}

		//this check its for templates, in case was sent an empty or disabled email template
		if (!($email["email_to"] && $email["email_from"])) {
			return false;
		}

		global $_CONF;

		$vars["site:url"] = $_CONF["url"];

		//add some extra vars
		$vars["visitor_date"]	=	CDate::ToStr("F j, Y" , time());
		$vars["visitor_ip"]		=	$_SERVER["REMOTE_ADDR"];
		$vars["visitor_domain"]	=	$_SERVER["REMOTE_HOST"];
		$vars["visitor_agent"]	=	$_SERVER["HTTP_USER_AGENT"];
		$vars["site_link"]		=	$_CONF["url"];
		$vars["year"]			=	CDate::ToStr("Y" , time());
				
		$msg = CTemplateStatic::Replace(stripslashes($email["email_body"]) , ($vars));

	
		if (!stristr($msg , "<html")) {
			//add full html page, will help with spam filters
			$msg = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body>' . $msg . '</body></html>';
		}
		

		if ($email["email_body_text"]) {
			$msg_text = CTemplateStatic::Replace(stripslashes($email["email_body_text"]) , $vars);
		}
		

		$sub = CTemplateStatic::Replace(stripslashes($email["email_subject"]) , $vars);

		$email["email_from"] = CTemplateStatic::Replace($email["email_from"] , $vars);
		$email["email_from_name"] = CTemplateStatic::Replace($email["email_from_name"] , $vars);


		if (!$email["email_replyto"]) 
			$email["email_replyto"] = $email["email_from"];
		if (!$email["email_replyto_name"]) 
			$email["email_replyto_name"] = $email["email_from_name"];

		$email["email_replyto"] = CTemplateStatic::Replace($email["email_replyto"] , $vars);
		$email["email_replyto_name"] = CTemplateStatic::Replace($email["email_replyto_name"] , $vars);

		//check for seding mail
		$this->__loadServers();

		if ($email["email_server"] && $this->servers[$email["email_server"]]) {
			$server = $this->servers[$email["email_server"]];
		} else {
			$server = $this->servers["default"];
		}


		if (stristr($email["email_to"] , ",")) {
			$rec = explode("," , $email["email_to"]);

			foreach ($rec as $key => $val) {
				if (trim($val)) {
					$recipients[$val] = $email["email_to_name"] ? $email["email_to_name"] : $val;
				}					
			}				
		} else {
			$recipients = array($email["email_to"] => $email["email_to_name"] ? $email["email_to_name"] : $email["email_to"]);	
		}

		$from = array($email["email_from"] => $email["email_from_name"] ? $email["email_from_name"] : $email["email_from"]);	
		$body = $msg;
		$subject = $sub;



		$body = $this->processMessage($body);
	
		//initialize the mail sending



		switch ($server["set_switft_transport"]) {

			case "smtp":
				$transport = Swift_SmtpTransport::newInstance(
					$server["set_swiftp_smtp_server"],
					$server["set_swiftp_smtp_port"]
				);

				if ($server["set_swiftp_smtp_auth"]) {
					$transport->setUsername($server["set_swiftp_smtp_auth_username"]);
					$transport->setPassword($server["set_swiftp_smtp_auth_password"]);
				}
				
				switch ($server["set_swiftp_smtp_enc"]) {
					case "ssl":
						$transport->setEncryption("ssl");
					break;

					case "tls":
						$transport->setEncryption("tls");
					break;
				}
			break;

			case "sendmail":
				$transport = Swift_SendmailTransport::newInstance(
					$server["set_swiftp_sendmail"]
				);
			break;
	
			case "php":
				$transport = Swift_MailTransport::newInstance();
			break;

		}

		
		//build the message and attachments
		switch ($server["set_switft_transport"]) {
			case "smtp":
			case "sendmail":
			case "php":



				//add dkim signature
				if ($server["server_dkim"]) {
					$signer = new Swift_Signers_DKIMSigner(
						$server["server_dkim_key"],
						$server["server_dkim_domain"],
						$server["server_dkim_selector"]
					);

					$message = Swift_SignedMessage::newInstance($subject);
					$message->attachSigner($signer);
				} else {
					$message = Swift_Message::newInstance($subject);
				}

				$message->setFrom($from)
					->setTo($recipients)
					->setReplyTo(array($email["email_replyto"] => $email["email_replyto_name"]))
					->setBody(
						$body , 
						"text/html",
						'utf-8'
					);
			

				if ($msg_text != "") {
					$message->addPart($msg_text, 'text/plain');
				}
				


				if (is_Array($email["attachments"])) {
					foreach ($email["attachments"] as $key => $val) {

						if (is_array($val)) {
							$attach = (new Swift_Attachment())
							  ->setFilename($key)
							  ->setContentType($val["mime"])
							  ->setBody($val["body"]);

							$message->attach($attach);

						} else {						
							$message->attach(
								Swift_Attachment::fromPath($val)->setFilename($key)
							);
						}
					}					
				}

				if (is_array($email["headers"])) {
					foreach ($email["headers"] as $key => $val) {
						$message->getHeaders()->addTextHeader($key , $val);
					}					
				}
				

				reset($recipients);

				//try sending the mail
				try {

					$mailer = Swift_Mailer::newInstance($transport);

					$logger = new Swift_Plugins_Loggers_ArrayLogger();
					$mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));

					$result = $mailer->send($message);

					$_headers = $message->getHeaders();

					//log the sent email 
					$this->db->QueryInsert(
						$this->tables["plugin:mail_log"],

						array_merge(
							array(
								"mail_date"		=> time(),
								"mail_to"		=> key($recipients)	,
								"mail_to_name"	=> $recipients[key($recipients)],

								"mail_from"		=> key($from)	,
								"mail_from_name" => $from[key($from)],

								"mail_code"		=> $email["email_code"],

								"mail_subject"	=> $subject,
								"mail_body"		=> $body,

								"mail_raw_header"	=> $_headers->getAll(),
								"mail_raw_body"		=> $message->toString(),

								"mail_log"		=> $logger->dump(),
							),
							$server
						)
					);


					return true;

				} catch( Exception $e ){

					$this->db->QueryInsert(
						$this->tables["plugin:mail_failed"],
						array_merge(
							array(
								"mail_date"		=> time(),
								"mail_to"		=> key($recipients)	,
								"mail_to_name"	=> $recipients[key($recipients)],

								"mail_from"		=> key($from)	,
								"mail_from_name" => $from[key($from)],

								"mail_code"		=> $email["email_code"],

								"mail_subject"	=> $subject,
								"mail_body"		=> $body,
								
								"mail_error"	=> $e->getMessage(),

//								"mail_raw_header"	=> $headers->getAll(),
								"mail_raw_body"		=> $message->toString(),

								"mail_log"		=> $logger->dump(),

							),
							$server
						)
					);
					return $e->getMessage();
				}

				
			break;
		}

	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function Cron() {
		global $_ADMIN;

		if ($_GET["mail_id"] && $_ADMIN) {
			//get the emails list
			$emails = $this->db->QFetchRowArray(
				"SELECT * FROM {$this->tables['plugin:mail_queue']} WHERE mail_id = %d ORDER BY mail_priority ASC , mail_date DESC ", array($_GET["mail_id"])
			);
		} else {
			//get the emails list
			$emails = $this->db->QFetchRowArray(
				"SELECT * FROM {$this->tables['plugin:mail_queue']} WHERE mail_date_sent = 0 ORDER BY mail_priority ASC , mail_date DESC "
			);

		}
		 


		if (is_array($emails)) {
			foreach ($emails as $key => $data) {
				$this->module->plugins["mail"]->SendMail(
					array(
						"email_from_name"	=> $data["mail_from_name"],
						"email_from"		=> $data["mail_from_email"],

						"email_to_name"		=> $data["mail_to_name"],
						"email_to"			=> $data["mail_to_email"],

						"email_subject"		=> $data["mail_subject"],
						"email_body"		=> $data["mail_body"],

						"email_type"		=> "html",
					)
				);

				//update email status
				$this->db->QueryUpdate(
					$this->tables["plugin:mail_queue"],
					array(
						"mail_date_sent"	=> time(),
						"mail_status"		=> "1",
					),

					"mail_id={$data[mail_id]}"
				);

				$count ++;
			}
		}

		if ($_GET["returnURL"]) {
			urlredirect($_GET["returnURL"]);
		}
		
		
		echo "Sent {$count} emails...";
		die();
	}



	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function AddMail($code , $email_data) {
		global $_LANG_ID;

		$mail = $this->db->QFetchArray(
			"SELECT * FROM 
				{$this->tables['plugin:mail_emails']} 

				WHERE 
					email_code LIKE '{$code}'
			"
		);

		if (is_array($mail)) {
			return false;
		}


		$id = $this->db->QueryInsert(
			$this->tables["plugin:mail_emails"] ,
			array(
				"email_code"	=> $code,
				"email_status"	=> $email_data["status"],			
			)
		);

		//insert the current language
		$lang = $this->plugins["languages"]->DefaultLang();

		$this->db->QueryINsert(
			$this->tables["plugin:mail_emails_lang"],
			array(
				"email_id"				=> $id,
				"lang_id"				=> $lang["lang_id"],
				"email_subject"			=> $email_data["subject"],
				"email_from"			=> $email_data["from"],
				"email_from_name"		=> $email_data["from_name"],
				"email_to"				=> $email_data["to"],
				"email_to_name"			=> $email_data["to_name"],
				"email_body"			=> $email_data["body"],
			)
		);		

	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function __loadServers() {

		if ($this->loaded) {
			return true;
		}

		$servers = $this->db->QFetchRowArray(
			"SELECT * FROM {$this->tables['plugin:mail_servers']} WHERE server_status=1"
		);

		$this->loaded = 1;

		if (is_array($servers)) {
			foreach ($servers as $key => $val) {
				$this->servers[$val["server_id"]] = $val;

				if ($val["server_default"]) {
					$this->servers["default"] = &$this->servers[$val["server_id"]];
				}				
			}			
		}

		//if no server is set as default then use the local server
		if (!is_array($this->servers["default"])) {

			//try smtp
			$type = "php";

			$this->servers["default"] = array(
				"set_switft_transport"	=> $type,
			);
		}	
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function processMessage($msg) {
		global $_CONF , $HTTPS;

		if ($HTTPS) {
			$_CONF["base_url"] = "https://" . $_SERVER["HTTP_HOST"];
		} else {
			$_CONF["base_url"] = "http://" . $_SERVER["HTTP_HOST"];
		}

		$dom = new DOMDocument();
		libxml_use_internal_errors(true);
		$dom->loadHTML($msg);
		$dom->normalizeDocument();


		$images = $dom->getElementsByTagName('img');


		foreach ($images as $image) {
		  $src = $image->getAttribute('src');

			if (stristr($src , "http://") || stristr($src , "https://")) {
			} else {

				if ($src[0] == "/") {
					$replace["src=\"" . $src . "\""] = "src=\"" . $_CONF["base_url"] . $src . "\"";
					$replace["src='" . $src . "'"] = "src='" . $_CONF["base_url"] . $src . "'";
				} else {
					$replace["src=\"" . $src . "\""] = "src=\"" . $_CONF["url"] . $src . "\"";
					$replace["src='" . $src . "'"] = "src='" . $_CONF["url"] . $src . "'";
				}							
			}
		}

		$links = $dom->getElementsByTagName('a');

		foreach ($links as $link) {
		  $src = $link->getAttribute('href');

			//this should cover all type of links
			if (stristr($src , ":")) {
			} else {

				if ($src[0] == "/") {
					$replace["href=\"" . $src . "\""] = "href=\"" . $_CONF["base_url"] . $src . "\"";
					$replace["href='" . $src . "'"] = "href='" . $_CONF["base_url"] . $src . "'";
				} else {
					$replace["href=\"" . $src . "\""] = "href=\"" . $_CONF["url"] . $src . "\"";
					$replace["href='" . $src . "'"] = "href='" . $_CONF["url"] . $src . "'";
				}							
			}
		}

		if (is_array($replace)) {
			//replace the links in body with tracking
			foreach ($replace as $key => $val) {
				$msg = str_replace(
					$key , 
					$val , 
					$msg
				);
			}
		}

		return $msg;
	}
	
	
}

?>