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

// dependencies

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

	function CMail() {
		//$this->CPlugin($db, $tables , $templates);
	}

	function DoEvents(){
		global $base, $_CONF, $_TSM , $_VARS , $_USER , $_BASE , $_SESS , $_ADMIN;

		parent::DoEvents();


		if ($_ADMIN) {

			if ($_GET["mod"] == "mail") {
				$sub = $_GET["sub"];
				$action = $_GET["action"];

				//read the module
				//$this->tpl_module = $this->module->plugins["modules"]->getModuleInfo($_GET["module_id"]);

				$this->tpl_module["mod_name"] = "Emails & Mailing Server";

				switch ($sub) {

					case "duplicate":
						return $this->Duplicate();
					break;

					case "failed-flush":
						$this->FlushErrors();
					break;

					case "sent-flush":
						$this->FlushSent();
					break;

					case "emails":
					case "queue":
					case "failed":
					case "sent":
					case "servers":
						$data = new CSQLAdmin($sub, $this->__parent_templates,$this->db,$this->tables,$extra);
						$this->PrepareFields($data->forms["forms"]);
						$this->PrepareVariables($data->forms);

						if ($sub == "servers") {
							$data->functions = array( 
									"onstore" => array(&$this , "StoreServer"),
//									"ondelete" => array(&$this , "DeleteServer"),
							);					
						}
						

						return $data->DoEvents();
					break;

					case "test-email":
						$this->SendTestEmail();
					break;

					case "replace":
							$data = new CFormSettings($this->forms_path  . $sub . ".xml" ,$_CONF["forms"]["admintemplate"] , $this->db,$this->tables);

							$this->PrepareDashboard($data->form);

							if ($data->Done()) {

								$this->processREplace();
							}

							return $data->Show();
					break;

					case "send-mail":
						return $this->Cron();
					break;

				}
			}

		} else {

			
			if (isModSub("mail" , "cron")) {
				return $this->Cron();
			}
		}
	}

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

		$emails = $this->db->QFetchRowArray("SELECT * FROM {$this->tables['plugin:mail_emails_lang']}");

		if (is_array($emails)) {
			foreach ($emails as $key => $val) {

				$val["email_from"] = str_replace($_POST["find"] , $_POST["replace"] , $val["email_from"]);
				$val["email_to"] = str_replace($_POST["find"] , $_POST["replace"] , $val["email_to"]);

				$this->db->QueryUpdate(
					$this->tables["plugin:mail_emails_lang"],
					$val , 
					"email_id={$val[email_id]} AND lang_id={$val[lang_id]}"
				);
			}			
		}

		urlredirect("index.php?mod=mail&sub=emails");		
	}
	

	/**
	* 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_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"];
			
				
		$msg = new CTemplate(stripslashes($email["email_body"]) , "string");
		$msg = $msg->Replace($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 = new CTemplate(stripslashes($email["email_body_text"]) , "string");
			$msg_text = $msg_text->Replace($vars);
		}
		

		$sub = new CTemplate(stripslashes($email["email_subject"]) , "string");
		$sub = $sub->Replace($vars);

		$email["email_from"] = new CTemplate(stripslashes($email["email_from"]) , "string");
		$email["email_from"] = $email["email_from"]->Replace($vars);

		$email["email_from_name"] = new CTemplate(stripslashes($email["email_from_name"]) , "string");
		$email["email_from_name"] = $email["email_from_name"]->Replace($vars);

		if (!$email["email_reply"]) 
			$email["email_reply"] = $email["email_from"];
		if (!$email["email_reply_name"]) 
			$email["email_reply_name"] = $email["email_from_name"];


		//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;
	
		//initialize the mail sending



		switch ($server["set_switft_transport"]) {

			case "smtp":
				External::Load("swiftmailer");
				$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":
				External::Load("swiftmailer");
				$transport = Swift_SendmailTransport::newInstance(
					$server["set_swiftp_sendmail"]
				);
			break;
	
			case "php":
				External::Load("swiftmailer");
				$transport = Swift_MailTransport::newInstance();
			break;

			case "php-smtp":
				External::Load("phpmailer");
				$mail = new PHPMailer;
				$mail->isSMTP();                                      // Set mailer to use SMTP

				$mail->Host = $server["set_swiftp_smtp_server"];  // Specify main and backup SMTP servers

				if ($server["set_swiftp_smtp_auth"]) {
					$mail->SMTPAuth = true;                               // Enable SMTP authentication
					$mail->Username = $server["set_swiftp_smtp_auth_username"];                 // SMTP username
					$mail->Password = $server["set_swiftp_smtp_auth_password"];                           // SMTP password
				}

				if ($server["set_swiftp_smtp_enc"]) {
					$mail->SMTPSecure = $server["set_swiftp_smtp_enc"];                            // Enable TLS encryption, `ssl` also accepted
				}
				
				//debug($from,1);
				
				$mail->Port = $server["set_swiftp_smtp_port"];                                    // TCP port to connect to

			break;


			case "php-local":
				External::Load("phpmailer");
				$mail = new PHPMailer;
			break;

		}

		
		//build the message and attachments
		switch ($server["set_switft_transport"]) {
			case "smtp":
			case "sendmail":
			case "php":
				$message = Swift_Message::newInstance($subject)
					->setFrom($from)
					->setTo($recipients)
					->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) {
						$message->attach(
							Swift_Attachment::fromPath($val)->setFilename($key)
						);
					}
					
				}

				reset($recipients);

				//try sending the mail
				try {

					$mailer = Swift_Mailer::newInstance($transport);
					$result = $mailer->send($message);


					//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,
							),
							$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()
							),
							$server
						)
					);
					return $e->getMessage();
				}

				
			break;

			case "php-local":
			case "php-smtp":

				if (is_Array($email["attachments"])) {
					foreach ($email["attachments"] as $key => $val) {
						$mail->addAttachment($val, $key);
					}
					
				}

				

				$mail->From = $email["email_from"];

				if ($email["email_from_name"]) {
					$mail->FromName = $email["email_from_name"];
				}

				foreach ($recipients as $key => $val) {
					$mail->addAddress($key, $val);     // Add a recipient
				}

				reset($recipients);

				//$mail->addReplyTo('info@example.com', 'Information');
				//$mail->addCC('cc@example.com');
				//$mail->addBCC('bcc@example.com');

				//$mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
				//$mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name
				$mail->isHTML(true);                                  // Set email format to HTML

				$mail->Subject = $subject;
				$mail->Body    = $body;
				$mail->AltBody = $msg_text;

				if (!$mail->send()) {
					$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"	=> $mail->ErrorInfo
							),
							$server
						)
					);

				} else {
					$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,
							),
							$server
						)
					);

				}				
			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 = \"{$_GET[mail_id]}\" ORDER BY mail_priority ASC , mail_date DESC "
			);
		} 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();
	}

	
	function PrepareVariables(&$forms) {

		//read all the forms

		global $_MODULES;

		switch ($_GET["sub"]) {
			case "emails":
				foreach ($_MODULES as $key => $val) {

					$folder = $val->path . "variables";

					if (is_dir($folder)) {

						$files = CDir::GetFiles($folder , "htm");

						if (is_array($files)) {

							foreach ($files as $k => $v) {

								$_files[$v] = strtoupper($key) . " / " . basename($v , ".htm");
							}					
						}				
					}			
				}

				if (is_array($_files)) {

					ksort($_files);
					//sort by key 

					if (!is_array($forms["forms"]["add"]["fields"]["template"]["options"])) {
						$forms["forms"]["add"]["fields"]["template"]["options"] = array();
						$forms["forms"]["edit"]["fields"]["template"]["options"] = array();
					}
					
					foreach ($_files as $key => $val) {
						$forms["forms"]["add"]["fields"]["template"]["options"][$key] = $val;
						$forms["forms"]["edit"]["fields"]["template"]["options"][$key] = $val;
					}			
				}
			

			break;

			case "servers":
				if (!External::Load("swiftmailer")) {
					unset($forms["forms"]["edit"]["fields"]["box"][0]["fields"]["set_switft_transport"]["options"]["smtp"]);
					unset($forms["forms"]["edit"]["fields"]["box"][0]["fields"]["set_switft_transport"]["options"]["sendmail"]);
					unset($forms["forms"]["edit"]["fields"]["box"][0]["fields"]["set_switft_transport"]["options"]["php"]);
				} 

				if (!External::Load("phpmailer")) {
					unset($forms["forms"]["edit"]["fields"]["box"][0]["fields"]["set_switft_transport"]["options"]["php-smtp"]);
					unset($forms["forms"]["edit"]["fields"]["box"][0]["fields"]["set_switft_transport"]["options"]["php-local"]);
				} 

			break;
		}
				
	}


	/**
	* 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 FlushErrors() {
		$this->db->Query("TRUNCATE TABLE {$this->tables['plugin:mail_failed']}");
		urlredirect($_GET["returnURL"]);
	}

	
	function FlushSent() {
		$this->db->Query("TRUNCATE TABLE {$this->tables['plugin:mail_log']}");
		urlredirect($_GET["returnURL"]);
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function Duplicate() {
		global $_LANG_ID;

		$item = $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 
				e.email_id={$_GET['email_id']}
		");

		if (!is_array($item)) {
			return "Invalid link !";
		}

		unset($item["email_id"]);
		$item["email_code"] .= "_copy_";

		$item["email_id"] = $this->db->QueryInsert(
			$this->tables['plugin:mail_emails'] , 
			$item
		);

		$this->db->QueryInsert(
			$this->tables['plugin:mail_emails_lang'] , 
			$item
		);

		
		//redirect to details page
		urlredirect(
			"index.php?mod=mail&sub=emails&email_id={$item[email_id]}&action=edit&returnurl=" . 
				urlencode("index.php?mod=mail&sub=emails")
		);
				

	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function StoreServer($record) {

		if ($record["server_id"]) {

			//check for default 
			if ($record["server_default"]) {

				$this->db->QueryUpdate(
					$this->tables["plugin:mail_servers"],
					array( "server_default"	=>	0) ,
					"server_default=1 AND server_id != {$record[server_id]}"
				);
			}

			//send the test email if applies
			if ($_POST["test"]) {
				//send the test mail	
				$results = $this->SendMail(
					array(
						"email_to" => $_POST["test_to"],
						"email_from" => "no-reply@" . $_SERVER["HTTP_HOST"],
						"email_subject" => $_POST["test_subject"],
						"email_body" => $_POST["test_body"],
						"email_server"	=> $record["server_id"]
					)
				);
				
			}		
			
		}
		

	}

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

		if (!Validate::Email($_POST["test_to"])) {
			die("email");
		}
		

		$email = $_POST;
		$_POST["email_to"] = $_POST["test_to"];
		$_POST["email_to_name"]	= "";

		//overwrite the from name
		$_POST["email_from"] = "no-reply@" . $_SERVER["HTTP_HOST"];
		$_POST["email_from_name"] = $_SERVER["HTTP_HOST"];

		$this->SendMail(
			$_POST
		);

		die("1");
	}
	

	/**
	* 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
			if (External::Load("swiftmailer")) {
				$type = "php";
			} elseif(External::Load("phpmailer")) {
				$type = "php-local";
			} else {
				throw new Exception("No mailing library could be found. Please install Swiftmailer or PHPMailer.");
			}

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

	
}

?>