<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
/*********************************************************************************
 * SugarCRM is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004 - 2009 SugarCRM Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 * 
 * 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, see http://www.gnu.org/licenses or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * 
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
 * technical reasons, the Appropriate Legal Notices must display the words
 * "Powered by SugarCRM".
 ********************************************************************************/
/*********************************************************************************

 * Description:  TODO: To be written.
 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
 * All Rights Reserved.
 * Contributor(s): ______________________________________..
 ********************************************************************************/
require_once('include/phpmailer/class.phpmailer.php');
require_once('include/OutboundEmail/OutboundEmail.php');
require_once('modules/Administration/Administration.php');

class SugarPHPMailer extends PHPMailer {
	var $oe; // OutboundEmail
	var $protocol = "tcp://";
	var $preppedForOutbound = false;
	var $disclosureEnabled;
	var $disclosureText;

	/**
	 * Sole constructor
	 */
	function SugarPHPMailer() {
		global $locale;
		global $current_user;
		global $sugar_config;

		$admin = new Administration();
		$admin->retrieveSettings();

		if(isset($admin->settings['disclosure_enable']) && !empty($admin->settings['disclosure_enable'])) {
			$this->disclosureEnabled = true;
			$this->disclosureText = $admin->settings['disclosure_text'];
		}

		$this->oe = new OutboundEmail();
		$this->oe->getUserMailerSettings($current_user);

		$this->SetLanguage('en', 'include/phpmailer/language/');
		$this->PluginDir	= 'include/phpmailer/';
		$this->Mailer		= 'sendmail';
        // cn: i18n
        $this->CharSet		= $locale->getPrecedentPreference('default_email_charset');
		$this->Encoding		= 'quoted-printable';
        $this->IsHTML(false);  // default to plain-text email
        $this->Hostname = $sugar_config['host_name'];
        $this->WordWrap		= 996;
		// cn: gmail fix
		$this->protocol = ($this->oe->mail_smtpssl == 1) ? "ssl://" : $this->protocol;




	}


	/**
	 * Prefills outbound details
	 */
	function setMailer() {
		global $current_user;

		require_once("include/OutboundEmail/OutboundEmail.php");
		$oe = new OutboundEmail();
		$oe = $oe->getUserMailerSettings($current_user, $mailer_id, $ieId);

		// ssl or tcp - keeping outside isSMTP b/c a default may inadvertantly set ssl://
		$this->protocol = ($oe->mail_smtpssl) ? "ssl://" : "tcp://";

		if($oe->mail_sendtype == "SMTP") {
			$this->Mailer = "smtp";
			$this->Host = $oe->mail_smtpserver;
			$this->Port = $oe->mail_smtpport;

			if($oe->mail_smtpauth_req) {
				$this->SMTPAuth = TRUE;
				$this->Username = $oe->mail_smtpuser;
				$this->Password = $oe->mail_smtppass;
			}
		} else {
			$this->Mailer = "sendmail";
		}
	}

	/**
	 * Prefills mailer for system
	 */
	function setMailerForSystem() {
		require_once("include/OutboundEmail/OutboundEmail.php");
		$oe = new OutboundEmail();
		$oe = $oe->getSystemMailerSettings();

		// ssl or tcp - keeping outside isSMTP b/c a default may inadvertantly set ssl://
		$this->protocol = ($oe->mail_smtpssl) ? "ssl://" : "tcp://";

		if($oe->mail_sendtype == "SMTP") {
			$this->Mailer = "smtp";
			$this->Host = $oe->mail_smtpserver;
			$this->Port = $oe->mail_smtpport;

			if($oe->mail_smtpauth_req) {
				$this->SMTPAuth = TRUE;
				$this->Username = $oe->mail_smtpuser;
				$this->Password = $oe->mail_smtppass;
			}
		} else {
			$this->Mailer = "sendmail";
		}
	}

    /**
     * Initiates a connection to an SMTP server.  Returns false if the
     * operation failed.
     * @access private
     * @return bool
     */
    function SmtpConnect() {
    	if(!class_exists('SMTP')) {
    		include($this->PluginDir.'class.smtp.php');
    	}
        if($this->smtp == NULL) { $this->smtp = new SMTP(); }

        $this->smtp->do_debug = $this->SMTPDebug;
        $hosts = explode(";", $this->Host);
        $index = 0;
        $connection = ($this->smtp->Connected());

        // Retry while there is no connection
        while($index < count($hosts) && $connection == false)
        {
            if(strstr($hosts[$index], ":"))
                list($host, $port) = explode(":", $hosts[$index]);
            else
            {
                $host = $this->protocol.$hosts[$index]; // cn: to enable gmail over ssl
                $port = $this->Port;
            }

            if($this->smtp->Connect($host, $port, $this->Timeout))
            {
                if ($this->Helo != '')
                    $this->smtp->Hello($this->Helo);
                else
                    $this->smtp->Hello($this->ServerHostname());

                if($this->SMTPAuth)
                {
                    if(!$this->smtp->Authenticate($this->Username,
                                                  $this->Password))
                    {
                        $this->SetError($this->Lang("authenticate"));
                        $this->smtp->Reset();
                        $connection = false;
                    }
                }
                $connection = true;
            }
            $index++;
        }
        if(!$connection)
            $this->SetError($this->Lang("connect_host"));

        return $connection;
    }


    /**
     * Attaches all fs, string, and binary attachments to the message.
     * Returns an empty string on failure.
     * @access private
     * @return string
     */
    function AttachAll() {
        // Return text of body
        $mime = array();

        // Add all attachments
        for($i = 0; $i < count($this->attachment); $i++) {
            // Check for string attachment
            $bString = $this->attachment[$i][5];
            if ($bString) {
                $string = $this->attachment[$i][0];
            } else {
				$path = $this->attachment[$i][0];
            }

			// cn: overriding parent class' method to perform encode on the following
            $filename    = $this->EncodeHeader(trim($this->attachment[$i][1]));
            $name        = $this->EncodeHeader(trim($this->attachment[$i][2]));
            $encoding    = $this->attachment[$i][3];
            $type        = $this->attachment[$i][4];
            $disposition = $this->attachment[$i][6];
            $cid         = $this->attachment[$i][7];

            $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
            $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
            $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);

            if($disposition == "inline") {
                $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
            }

            $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE);

            // Encode as string attachment
            if($bString) {
                $mime[] = $this->EncodeString($string, $encoding);
                if($this->IsError()) { return ""; }
                $mime[] = $this->LE.$this->LE;
            } else {
                $mime[] = $this->EncodeFile($path, $encoding);

                if($this->IsError()) {
                	return "";
                }
                $mime[] = $this->LE.$this->LE;
            }
        }
        $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);

        return join("", $mime);
    }

	/**
	 * handles Charset translation for all visual parts of the email.
	 * @param string charset Default = ''
	 */
	function prepForOutbound() {
		global $locale;

		if($this->preppedForOutbound == false) {
			$this->preppedForOutbound = true; // flag so we don't redo this
			$OBCharset = $locale->getPrecedentPreference('default_email_charset');

			// handle disclosure
			if($this->disclosureEnabled) {
				$this->Body .= "<br />&nbsp;<br />{$this->disclosureText}";
				$this->AltBody .= "\r\r{$this->disclosureText}";
			}

			// body text
			$this->Body		= from_html($locale->translateCharset(trim($this->Body), 'UTF-8', $OBCharset));
			$this->AltBody		= from_html($locale->translateCharset(trim($this->AltBody), 'UTF-8', $OBCharset));
            $subjectUTF8		= from_html(trim($this->Subject));
            $subject			= $locale->translateCharset($subjectUTF8, 'UTF-8', $OBCharset);
            $this->Subject		= $locale->translateCharset($subjectUTF8, 'UTF-8', $OBCharset);

			// HTML email RFC compliance
			if($this->ContentType == "text/html") {
				if(strpos($this->Body, '<html') === false) {
					$head=<<<eoq
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset={$OBCharset}" />
<title>{$subject}</title>
</head>
<body>
eoq;
					$this->Body = $head.$this->Body."</body></html>";
				}
			}

			// Headers /////////////////////////////////
			// the below is done in PHPMailer::CreateHeader();
			//$this->Subject			= $locale->translateCharsetMIME(trim($this->Subject), 'UTF-8', $locale->getPrecedentPreference('default_email_charset'));
			$this->FromName		= $locale->translateCharset(trim($this->FromName), 'UTF-8', $OBCharset);
			foreach($this->ReplyTo as $k => $v) {
				$this->ReplyTo[$k][1] = $locale->translateCharset(trim($v[1]), 'UTF-8', $OBCharset);
			}
			// TO: fields
			foreach($this->to as $k => $toArr) {
				$this->to[$k][1]	= $locale->translateCharset(trim($toArr[1]), 'UTF-8', $OBCharset);
			}
			// CC: fields
			foreach($this->cc as $k => $ccAddr) {
				$this->cc[$k][1]	= $locale->translateCharset(trim($ccAddr[1]), 'UTF-8', $OBCharset);
			}
			// BCC: fields
			foreach($this->bcc as $k => $bccAddr) {
				$this->bcc[$k][1]	= $locale->translateCharset(trim($bccAddr[1]), 'UTF-8', $OBCharset);
			}

			// attachment names
			/*
			 * $this->attachment[$cur][1] = $filename;
			 * $this->attachment[$cur][2] = $name;
			 */
			foreach($this->attachment as $k => $attachment) {
				$this->attachment[$k][1] = $locale->translateCharset(trim($this->attachment[$k][1]), 'UTF-8', $OBCharset);
				$this->attachment[$k][2] = $locale->translateCharset(trim($this->attachment[$k][2]), 'UTF-8', $OBCharset);
			}
		}
	}

	/**
	 * @param notes	array of note beans
	 */
	function handleAttachments($notes) {
		global $sugar_config;

        //replace references to cache/images with cid tag
        $this->Body = str_replace('cache/images/','cid:',$this->Body);

		if (empty($notes)) {
				return;
		}
		// cn: bug 4864 - reusing same SugarPHPMailer class, need to clear attachments
		$this->ClearAttachments();
		require_once('include/upload_file.php');

        $fileBasePath = "{$sugar_config['upload_dir']}";
		$filePatternSearch = "{$sugar_config['upload_dir']}";
		$filePatternSearch = str_replace("/", "\/", $filePatternSearch);
		if(strpos($this->Body, "\"{$fileBasePath}")) {
			$matches = array();
			preg_match_all("/{$filePatternSearch}.+?\"/i", $this->Body, $matches);
			foreach($matches[0] as $match) {
				$filename = str_replace($fileBasePath, '', $match);
				$filename = urldecode(substr($filename, 0, -1));
				$cid = $filename;
				$file_location = clean_path(getcwd()."/{$sugar_config['upload_dir']}{$filename}");
				$mime_type = "image/".strtolower(substr($filename, strrpos($filename, ".")+1, strlen($filename)));
				if(file_exists($file_location)) {
					$this->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $mime_type);
				}
			}
            //replace references to cache with cid tag
            $this->Body = str_replace($fileBasePath,'cid:',$this->Body);
		}
		foreach($notes as $note) {
				$mime_type = 'text/plain';
				$file_location = '';
				$filename = '';

				if($note->object_name == 'Note') {
					if (! empty($note->file->temp_file_location) && is_file($note->file->temp_file_location)) {
						$file_location = $note->file->temp_file_location;
						$filename = $note->file->original_file_name;
						$mime_type = $note->file->mime_type;
					} else {
						$file_location = rawurldecode(UploadFile::get_file_path($note->filename,$note->id));
						$filename = $note->id.$note->filename;
						$mime_type = $note->file_mime_type;
					}
				} elseif($note->object_name == 'DocumentRevision') { // from Documents
					$filename = $note->id.$note->filename;
					$file_location = getcwd().'/cache/upload/'.$filename;
					$mime_type = $note->file_mime_type;
				}

				$filename = substr($filename, 36, strlen($filename)); // strip GUID	for PHPMailer class to name outbound file
				if (!$note->embed_flag) {
					$this->AddAttachment($file_location, $filename, 'base64', $mime_type);
				} // else
			}
	}

	/**
	 * overloads class.phpmailer's SetError() method so that we can log errors in sugarcrm.log
	 *
	 */
	function SetError($msg) {
		$GLOBALS['log']->fatal("SugarPHPMailer encountered an error: {$msg}");
		parent::SetError($msg);
	}
} // end class definition
