3319 lines
104 KiB
PHP
Executable File
3319 lines
104 KiB
PHP
Executable File
<?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:
|
|
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights
|
|
* Reserved. Contributor(s): ______________________________________..
|
|
*********************************************************************************/
|
|
require_once('include/SugarPHPMailer.php');
|
|
require_once('include/SugarEmailAddress/SugarEmailAddress.php');
|
|
require_once('include/Pear/HTML_Safe/Safe.php');
|
|
|
|
class Email extends SugarBean {
|
|
/* SugarBean schema */
|
|
var $id;
|
|
var $date_entered;
|
|
var $date_modified;
|
|
var $assigned_user_id;
|
|
var $assigned_user_name;
|
|
var $modified_user_id;
|
|
var $created_by;
|
|
|
|
|
|
|
|
var $deleted;
|
|
var $from_addr;
|
|
var $reply_to_addr;
|
|
var $to_addrs;
|
|
var $cc_addrs;
|
|
var $bcc_addrs;
|
|
var $message_id;
|
|
|
|
/* Bean Attributes */
|
|
var $name;
|
|
var $type = 'archived';
|
|
var $date_sent;
|
|
var $status;
|
|
var $intent;
|
|
var $mailbox_id;
|
|
var $from_name;
|
|
|
|
var $reply_to_status;
|
|
var $reply_to_name;
|
|
var $reply_to_email;
|
|
var $description;
|
|
var $description_html;
|
|
var $raw_source;
|
|
var $parent_id;
|
|
var $parent_type;
|
|
|
|
/* link attributes */
|
|
var $parent_name;
|
|
|
|
|
|
/* legacy */
|
|
var $date_start; // legacy
|
|
var $time_start; // legacy
|
|
var $from_addr_name;
|
|
var $to_addrs_arr;
|
|
var $cc_addrs_arr;
|
|
var $bcc_addrs_arr;
|
|
var $to_addrs_ids;
|
|
var $to_addrs_names;
|
|
var $to_addrs_emails;
|
|
var $cc_addrs_ids;
|
|
var $cc_addrs_names;
|
|
var $cc_addrs_emails;
|
|
var $bcc_addrs_ids;
|
|
var $bcc_addrs_names;
|
|
var $bcc_addrs_emails;
|
|
var $contact_id;
|
|
var $contact_name;
|
|
|
|
/* Archive Email attrs */
|
|
var $duration_hours;
|
|
|
|
|
|
|
|
var $new_schema = true;
|
|
var $table_name = 'emails';
|
|
var $module_dir = 'Emails';
|
|
var $object_name = 'Email';
|
|
var $db;
|
|
|
|
/* private attributes */
|
|
var $rolloverStyle = "<style>div#rollover {position: relative;float: left;margin: none;text-decoration: none;}div#rollover a:hover {padding: 0;text-decoration: none;}div#rollover a span {display: none;}div#rollover a:hover span {text-decoration: none;display: block;width: 250px;margin-top: 5px;margin-left: 5px;position: absolute;padding: 10px;color: #333; border: 1px solid #ccc; background-color: #fff; font-size: 12px;z-index: 1000;}</style>\n";
|
|
var $default_email_subject_values = array('Follow-up on proposal', 'Initial discussion', 'Review needs', 'Discuss pricing', 'Demo', 'Introduce all players', );
|
|
var $cachePath = 'cache/modules/Emails';
|
|
var $cacheFile = 'robin.cache.php';
|
|
var $replyDelimiter = "> ";
|
|
var $emailDescription;
|
|
var $emailDescriptionHTML;
|
|
var $emailRawSource;
|
|
var $link_action;
|
|
var $emailAddress;
|
|
var $attachments = array();
|
|
|
|
/* to support Email 2.0 */
|
|
var $isDuplicate;
|
|
var $uid;
|
|
var $to;
|
|
var $flagged;
|
|
var $answered;
|
|
var $seen;
|
|
var $draft;
|
|
var $relationshipMap = array(
|
|
'Contacts' => 'emails_contacts_rel',
|
|
'Accounts' => 'emails_accounts_rel',
|
|
'Leads' => 'emails_leads_rel',
|
|
'Users' => 'emails_users_rel',
|
|
'Prospects' => 'emails_prospects_rel',
|
|
);
|
|
|
|
/* public */
|
|
var $et; // EmailUI object
|
|
|
|
/**
|
|
* sole constructor
|
|
*/
|
|
function Email() {
|
|
parent::SugarBean();
|
|
|
|
|
|
|
|
|
|
$this->safe = new HTML_Safe();
|
|
$this->safe->clear();
|
|
$this->emailAddress = new SugarEmailAddress();
|
|
}
|
|
|
|
function email2init() {
|
|
require_once('modules/Emails/EmailUI.php');
|
|
$this->et = new EmailUI();
|
|
}
|
|
function bean_implements($interface){
|
|
switch($interface){
|
|
case 'ACL': return true;
|
|
default: return false;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Presaves one attachment for new email 2.0 spec
|
|
* DOES NOT CREATE A NOTE
|
|
* @return string ID of note associated with the attachment
|
|
*/
|
|
function email2saveAttachment() {
|
|
global $sugar_config;
|
|
|
|
$filesError = array(
|
|
0 => 'UPLOAD_ERR_OK - There is no error, the file uploaded with success.',
|
|
1 => 'UPLOAD_ERR_INI_SIZE - The uploaded file exceeds the upload_max_filesize directive in php.ini.',
|
|
2 => 'UPLOAD_ERR_FORM_SIZE - The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
|
|
3 => 'UPLOAD_ERR_PARTIAL - The uploaded file was only partially uploaded.',
|
|
4 => 'UPLOAD_ERR_NO_FILE - No file was uploaded.',
|
|
5 => 'UNKNOWN ERROR',
|
|
6 => 'UPLOAD_ERR_NO_TMP_DIR - Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.',
|
|
7 => 'UPLOAD_ERR_CANT_WRITE - Failed to write file to disk. Introduced in PHP 5.1.0.',
|
|
);
|
|
|
|
// cn: Bug 5995 - rudimentary error checking
|
|
if($_FILES['email_attachment']['error'] != 0 && $_FILES['email_attachment']['error'] != 4) {
|
|
$GLOBALS['log']->debug('Email Attachment could not be attach due to error: '.$filesError[$_FILES['email_attachment']['error']]);
|
|
return array();
|
|
}
|
|
|
|
if(isset($_FILES['email_attachment']) && is_uploaded_file($_FILES['email_attachment']['tmp_name'])) {
|
|
$guid = create_guid();
|
|
$cleanAttachmentFileName = from_html($_FILES['email_attachment']['name']);
|
|
$GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] ");
|
|
$cleanAttachmentFileName = str_replace("\\", "", $cleanAttachmentFileName);
|
|
$GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] ");
|
|
$destination = clean_path("{$this->et->userCacheDir}/{$guid}{$cleanAttachmentFileName}");
|
|
$badExt = $this->safeAttachmentName($cleanAttachmentFileName);
|
|
if ($badExt) {
|
|
$destination = $destination . ".txt";
|
|
} // if
|
|
$fileName = $badExt ? $cleanAttachmentFileName . ".txt" : $cleanAttachmentFileName;
|
|
if(move_uploaded_file($_FILES['email_attachment']['tmp_name'], $destination)) {
|
|
return array(
|
|
'guid' => $guid,
|
|
'name' => $GLOBALS['db']->helper->escape_quote($fileName),
|
|
'nameForDisplay' => $fileName
|
|
);
|
|
} else {
|
|
$GLOBALS['log']->debug("Email Attachment [ {$cleanAttachmentFileName} ] could not be moved to cache dir");
|
|
return array();
|
|
}
|
|
}
|
|
}
|
|
|
|
function safeAttachmentName($filename) {
|
|
global $sugar_config;
|
|
$badExtension = false;
|
|
//get position of last "." in file name
|
|
$file_ext_beg = strrpos($filename, ".");
|
|
$file_ext = "";
|
|
|
|
//get file extension
|
|
if($file_ext_beg > 0) {
|
|
$file_ext = substr($filename, $file_ext_beg + 1);
|
|
}
|
|
|
|
//check to see if this is a file with extension located in "badext"
|
|
foreach($sugar_config['upload_badext'] as $badExt) {
|
|
if(strtolower($file_ext) == strtolower($badExt)) {
|
|
//if found, then append with .txt and break out of lookup
|
|
$filename = $filename . ".txt";
|
|
$badExtension = true;
|
|
break; // no need to look for more
|
|
} // if
|
|
} // foreach
|
|
|
|
return $badExtension;
|
|
} // fn
|
|
|
|
/**
|
|
* takes output from email 2.0 to/cc/bcc fields and returns appropriate arrays for usage by PHPMailer
|
|
* @param string addresses
|
|
* @return array
|
|
*/
|
|
function email2ParseAddresses($addresses) {
|
|
$addresses = from_html($addresses);
|
|
$addresses = str_replace(",", ";", $addresses);
|
|
$exAddr = explode(";", $addresses);
|
|
|
|
$ret = array();
|
|
$clean = array("<", ">");
|
|
$dirty = array("<", ">");
|
|
|
|
foreach($exAddr as $addr) {
|
|
$name = '';
|
|
|
|
$addr = str_replace($dirty, $clean, $addr);
|
|
|
|
if((strpos($addr, "<") === false) && (strpos($addr, ">") === false)) {
|
|
$address = $addr;
|
|
} else {
|
|
$address = substr($addr, strpos($addr, "<") + 1, strpos($addr, ">") - 1 - strpos($addr, "<"));
|
|
$name = substr($addr, 0, strpos($addr, "<"));
|
|
}
|
|
|
|
$addrTemp = array();
|
|
$addrTemp['email'] = str_replace(" ","",trim($address));
|
|
$addrTemp['display'] = trim($name);
|
|
$ret[] = $addrTemp;
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* takes output from email 2.0 to/cc/bcc fields and returns appropriate arrays for usage by PHPMailer
|
|
* @param string addresses
|
|
* @return array
|
|
*/
|
|
function email2ParseAddressesForAddressesOnly($addresses) {
|
|
$addresses = from_html($addresses);
|
|
$addresses = str_replace(",", ";", $addresses);
|
|
$exAddr = explode(";", $addresses);
|
|
|
|
$ret = array();
|
|
$clean = array("<", ">");
|
|
$dirty = array("<", ">");
|
|
|
|
foreach($exAddr as $addr) {
|
|
$name = '';
|
|
|
|
$addr = str_replace($dirty, $clean, $addr);
|
|
|
|
if(strpos($addr, "<") && strpos($addr, ">")) {
|
|
$address = substr($addr, strpos($addr, "<") + 1, strpos($addr, ">") - 1 - strpos($addr, "<"));
|
|
} else {
|
|
$address = $addr;
|
|
}
|
|
|
|
$ret[] = trim($address);
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Determines MIME-type encoding as possible.
|
|
* @param string $fileLocation relative path to file
|
|
* @return string MIME-type
|
|
*/
|
|
function email2GetMime($fileLocation) {
|
|
if(function_exists('mime_content_type')) {
|
|
$mime = mime_content_type($fileLocation);
|
|
} elseif(function_exists('ext2mime')) {
|
|
$mime = ext2mime($fileLocation);
|
|
} else {
|
|
$mime = 'application/octet-stream';
|
|
}
|
|
return $mime;
|
|
}
|
|
|
|
|
|
function decodeDuringSend($htmlData) {
|
|
$htmlData = str_replace("sugarLessThan", "<", $htmlData);
|
|
$htmlData = str_replace("sugarGreaterThan", ">", $htmlData);
|
|
return $htmlData;
|
|
}
|
|
/**
|
|
* Sends Email for Email 2.0
|
|
*/
|
|
function email2Send($request) {
|
|
require_once("modules/EmailTemplates/EmailTemplate.php");
|
|
require_once("modules/InboundEmail/InboundEmail.php");
|
|
require_once("modules/Notes/Note.php");
|
|
global $mod_strings;
|
|
global $current_user;
|
|
global $sugar_config;
|
|
global $locale;
|
|
global $timedate;
|
|
global $beanList;
|
|
global $beanFiles;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$i=0;
|
|
while($i<100){
|
|
$i++;
|
|
$cnt_to_id=$request['contacts_to_id_'.($i-1)];
|
|
if($request['contacts_to_name_'.($i-1)])$cnt_to[$cnt_to_id]['name']=$request['contacts_to_name_'.($i-1)];
|
|
else continue;
|
|
|
|
$j=-1;
|
|
while($j<100){
|
|
$j++;
|
|
if($request['contacts_to_email_check_'.($i-1).'_'.$j]){
|
|
$cnt_to[$cnt_to_id]['addrs'][]=$request['contacts_to_email_check_'.($i-1).'_'.$j];
|
|
$em_to.=$request['contacts_to_email_check_'.($i-1).'_'.$j]."; ";
|
|
}
|
|
}
|
|
}
|
|
$i=0;
|
|
while($i<100){
|
|
$i++;
|
|
$cnt_cc_id=$request['contacts_cc_id_'.($i-1)];
|
|
if($request['contacts_cc_name_'.($i-1)])$cnt_cc[$cnt_cc_id]['name']=$request['contacts_cc_name_'.($i-1)];
|
|
else continue;
|
|
|
|
$j=-1;
|
|
while($j<100){
|
|
$j++;
|
|
if($request['contacts_cc_email_check_'.($i-1).'_'.$j]){
|
|
$cnt_cc[$cnt_cc_id]['addrs'][]=$request['contacts_cc_email_check_'.($i-1).'_'.$j];
|
|
$em_cc.=$request['contacts_cc_email_check_'.($i-1).'_'.$j]."; ";
|
|
}
|
|
}
|
|
}
|
|
$i=0;
|
|
while($i<100){
|
|
$i++;
|
|
$cnt_bcc_id=$request['contacts_bcc_id_'.($i-1)];
|
|
if($request['contacts_bcc_name_'.($i-1)])$cnt_bcc[$cnt_bcc_id]['name']=$request['contacts_bcc_name_'.($i-1)];
|
|
else continue;
|
|
|
|
$j=-1;
|
|
while($j<100){
|
|
$j++;
|
|
if($request['contacts_bcc_email_check_'.($i-1).'_'.$j]){
|
|
$cnt_bcc[$cnt_bcc_id]['addrs'][]=$request['contacts_bcc_email_check_'.($i-1).'_'.$j];
|
|
$em_bcc.=$request['contacts_bcc_email_check_'.($i-1).'_'.$j]."; ";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*$i=0;
|
|
while($i!=100){
|
|
//print "i in<br>";
|
|
$i++;
|
|
//account
|
|
$acc_id=$request['account_id_'.$i];
|
|
if($request['account_name_'.$i])$acc[$acc_id]['name']=$request['account_name_'.$i];
|
|
else continue;
|
|
|
|
$j=-1;
|
|
while($j!=100){
|
|
//print "j in<br>";
|
|
$j++;
|
|
if($request['account_email_check_'.$i.'_'.$j]){
|
|
//print "em<br>";
|
|
$acc[$acc_id]['addrs'][]=$request['account_email_check_'.$i.'_'.$j];
|
|
$em.=$request['account_email_check_'.$i.'_'.$j]."; ";
|
|
}
|
|
}
|
|
//cnt
|
|
/*$j=-1;
|
|
while($j!=100){
|
|
//print "j in<br>";
|
|
$j++;
|
|
$cnt_id=$request['contact_id_'.$i.'_'.$j];
|
|
if($request['contact_name_'.$i.'_'.$j] && $request['contact_id_'.$i.'_'.$j]){
|
|
$cnt[$cnt_id]['name']=$request['contact_name_'.$i.'_'.$j];
|
|
$n=1;
|
|
while($n!=100){
|
|
//print "n in<br>";
|
|
$n++;
|
|
if($request['contact_email_check_'.$i.'_'.$j.'_'.$n]){
|
|
//print "em<br>";
|
|
$cnt[$cnt_id]['addrs'][]=$request['contact_email_check_'.$i.'_'.$j.'_'.$n];
|
|
$em.=$request['contact_email_check_'.$i.'_'.$j.'_'.$n]."; ";
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
//acc
|
|
/*$j=-1;
|
|
while($j!=100){
|
|
//print "j in<br>";
|
|
$j++;
|
|
$ac_id=$request['acc_id_'.$i.'_'.$j];
|
|
if($request['acc_name_'.$i.'_'.$j] && $request['acc_id_'.$i.'_'.$j]){
|
|
$ac[$ac_id]['name']=$request['acc_name_'.$i.'_'.$j];
|
|
$n=1;
|
|
while($n!=100){
|
|
//print "n in<br>";
|
|
$n++;
|
|
if($request['acc_email_check_'.$i.'_'.$j.'_'.$n]){
|
|
//print "em<br>";
|
|
$ac[$ac_id]['addrs'][]=$request['acc_email_check_'.$i.'_'.$j.'_'.$n];
|
|
$em.=$request['acc_email_check_'.$i.'_'.$j.'_'.$n]."; ";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$acc[$acc_id]['contacts']=$cnt;
|
|
$acc[$acc_id]['accounts']=$ac;*/
|
|
//}
|
|
|
|
|
|
//print $em;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Sugar Email PREP
|
|
*/
|
|
/* preset GUID */
|
|
|
|
$orignialId = "";
|
|
if(!empty($this->id)) {
|
|
$orignialId = $this->id;
|
|
} // if
|
|
|
|
if(empty($this->id)) {
|
|
$this->id = create_guid();
|
|
$this->new_with_id = true;
|
|
}
|
|
|
|
/* satisfy basic HTML email requirements */
|
|
$this->name = $request['sendSubject'];
|
|
$this->description_html = '<html><body>'.$request['sendDescription'].'</body></html>';
|
|
|
|
/**********************************************************************
|
|
* PHPMAILER PREP
|
|
*/
|
|
$mail = new SugarPHPMailer();
|
|
$mail = $this->setMailer($mail, '', $_REQUEST['fromAccount']);
|
|
|
|
$subject = $this->name;
|
|
$mail->Subject = from_html($this->name);
|
|
|
|
// work-around legacy code in SugarPHPMailer
|
|
if($_REQUEST['setEditor'] == 1) {
|
|
$_REQUEST['description_html'] = $_REQUEST['sendDescription'];
|
|
$this->description_html = $_REQUEST['description_html'];
|
|
} else {
|
|
$this->description_html = '';
|
|
$this->description = $this->decodeDuringSend($_REQUEST['sendDescription']);
|
|
}
|
|
// end work-around
|
|
|
|
if (isset($request['saveDraft']) || ($this->type == 'draft' && $this->status == 'draft')) {
|
|
if($this->type != 'draft' && $this->status != 'draft') {
|
|
$this->id = create_guid();
|
|
$this->new_with_id = true;
|
|
} // if
|
|
$q1 = "update emails_email_addr_rel set deleted = 1 WHERE email_id = '{$this->id}'";
|
|
$r1 = $this->db->query($q1);
|
|
} // if
|
|
|
|
if (isset($request['saveDraft'])) {
|
|
$this->type = 'draft';
|
|
$this->status = 'draft';
|
|
$forceSave = true;
|
|
} else {
|
|
/* Apply Email Templates */
|
|
// do not parse email templates if the email is being saved as draft....
|
|
$toAddresses = $this->email2ParseAddresses($_REQUEST['sendTo']);
|
|
$sea = new SugarEmailAddress();
|
|
$object_arr = array();
|
|
|
|
foreach($toAddresses as $addrMeta) {
|
|
$addr = $addrMeta['email'];
|
|
$beans = $sea->getBeansByEmailAddress($addr);
|
|
foreach($beans as $bean) {
|
|
$object_arr[$bean->module_dir] = $bean->id;
|
|
}
|
|
}
|
|
|
|
if( isset($_REQUEST['parent_type']) && !empty($_REQUEST['parent_type']) &&
|
|
isset($_REQUEST['parent_id']) && !empty($_REQUEST['parent_id']) ) {
|
|
if(isset($beanList[$_REQUEST['parent_type']]) && !empty($beanList[$_REQUEST['parent_type']])) {
|
|
$className = $beanList[$_REQUEST['parent_type']];
|
|
if(isset($beanFiles[$className]) && !empty($beanFiles[$className])) {
|
|
if(!class_exists($className)) {
|
|
require_once($beanFiles[$className]);
|
|
}
|
|
$bean = new $className();
|
|
$bean->retrieve($_REQUEST['parent_id']);
|
|
$object_arr[$bean->module_dir] = $bean->id;
|
|
} // if
|
|
} // if
|
|
} // if
|
|
|
|
if (!empty($object_arr)) {
|
|
ksort($object_arr);
|
|
} // if
|
|
|
|
/* template parsing */
|
|
if (empty($object_arr)) {
|
|
$object_arr= array('Contacts' => '123');
|
|
}
|
|
$object_arr['Users'] = $current_user->id;
|
|
$this->description_html = EmailTemplate::parse_template($this->description_html, $object_arr);
|
|
$this->name = EmailTemplate::parse_template($this->name, $object_arr);
|
|
$this->description = EmailTemplate::parse_template($this->description, $object_arr);
|
|
$OBCharset = empty($request['sendCharset'])?$locale->getPrecedentPreference('default_email_charset'):$request['sendCharset'];
|
|
$this->description = html_entity_decode($this->description,ENT_COMPAT,$OBCharset);
|
|
if($this->type != 'draft' && $this->status != 'draft') {
|
|
$this->id = create_guid();
|
|
$this->date_entered = "";
|
|
$this->new_with_id = true;
|
|
$this->type = 'out';
|
|
$this->status = 'sent';
|
|
}
|
|
}
|
|
|
|
if(isset($_REQUEST['parent_type']) && empty($_REQUEST['parent_type']) &&
|
|
isset($_REQUEST['parent_id']) && empty($_REQUEST['parent_id']) ) {
|
|
$this->parent_id = "";
|
|
$this->parent_type = "";
|
|
} // if
|
|
|
|
|
|
$mail->Subject = $this->name;
|
|
$mail = $this->handleBody($mail);
|
|
$mail->Subject = $this->name;
|
|
|
|
$this->description_html = from_html($this->description_html);
|
|
$this->description_html = $this->decodeDuringSend($this->description_html);
|
|
|
|
/* from account */
|
|
$replyToAddress = $current_user->emailAddress->getReplyToAddress($current_user);
|
|
$replyToName = "";
|
|
if(empty($request['fromAccount'])) {
|
|
$defaults = $current_user->getPreferredEmail();
|
|
$mail->From = $defaults['email'];
|
|
$mail->FromName = $defaults['name'];
|
|
$replyToName = $mail->FromName;
|
|
//$replyToAddress = $current_user->emailAddress->getReplyToAddress($current_user);
|
|
} else {
|
|
// passed -> user -> system default
|
|
$ie = new InboundEmail();
|
|
$ie->retrieve($request['fromAccount']);
|
|
$storedOptions = unserialize(base64_decode($ie->stored_options));
|
|
$fromName = "";
|
|
$fromAddress = "";
|
|
$replyToName = "";
|
|
$replyToAddress = "";
|
|
if (!empty($storedOptions)) {
|
|
$fromAddress = $storedOptions['from_addr'];
|
|
$fromName = from_html($storedOptions['from_name']);
|
|
$replyToAddress = (isset($storedOptions['reply_to_addr']) ? $storedOptions['reply_to_addr'] : "");
|
|
$replyToName = (isset($storedOptions['reply_to_name']) ? from_html($storedOptions['reply_to_name']) : "");
|
|
} // if
|
|
$defaults = $current_user->getPreferredEmail();
|
|
if ($ie->is_personal) {
|
|
if (empty($replyToAddress)) {
|
|
$replyToAddress = $current_user->emailAddress->getReplyToAddress($current_user);
|
|
} // if
|
|
if (empty($replyToName)) {
|
|
$replyToName = $defaults['name'];
|
|
} // if
|
|
}
|
|
$mail->From = (!empty($fromAddress)) ? $fromAddress : $defaults['email'];
|
|
$mail->FromName = (!empty($fromName)) ? $fromName : $defaults['name'];
|
|
$replyToName = (!empty($replyToName)) ? $replyToName : $mail->FromName;
|
|
}
|
|
|
|
$mail->Sender = $mail->From; /* set Return-Path field in header to reduce spam score in emails sent via Sugar's Email module */
|
|
if (!empty($replyToAddress)) {
|
|
$mail->AddReplyTo($replyToAddress, $replyToName);
|
|
} else {
|
|
$mail->AddReplyTo($mail->From, $mail->FromName);
|
|
} // else
|
|
|
|
$emailAddressCollection = array(); // used in linking to beans below
|
|
// handle to/cc/bcc
|
|
//print $request['sendTo'].$em;
|
|
foreach($this->email2ParseAddresses($request['sendTo']) as $addr_arr) {
|
|
if(empty($addr_arr['email'])) continue;
|
|
|
|
if(empty($addr_arr['display'])) {
|
|
$mail->AddAddress($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddAddress($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
$emailAddressCollection[] = $addr_arr['email'];
|
|
}
|
|
|
|
foreach($this->email2ParseAddresses($request['sendCc']) as $addr_arr) {
|
|
if(empty($addr_arr['email'])) continue;
|
|
|
|
if(empty($addr_arr['display'])) {
|
|
$mail->AddCC($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddCC($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
$emailAddressCollection[] = $addr_arr['email'];
|
|
}
|
|
foreach($this->email2ParseAddresses($request['sendBcc']) as $addr_arr) {
|
|
if(empty($addr_arr['email'])) continue;
|
|
|
|
if(empty($addr_arr['display'])) {
|
|
$mail->AddBCC($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddBCC($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
$emailAddressCollection[] = $addr_arr['email'];
|
|
}
|
|
|
|
|
|
/* parse remove attachments array */
|
|
$removeAttachments = array();
|
|
if(!empty($request['templateAttachmentsRemove'])) {
|
|
$exRemove = explode("::", $request['templateAttachmentsRemove']);
|
|
|
|
foreach($exRemove as $file) {
|
|
$removeAttachments = substr($file, 0, 36);
|
|
}
|
|
}
|
|
|
|
/* handle attachments */
|
|
if(!empty($request['attachments'])) {
|
|
$exAttachments = explode("::", $request['attachments']);
|
|
|
|
foreach($exAttachments as $file) {
|
|
$file = trim(from_html($file));
|
|
$file = str_replace("\\", "", $file);
|
|
if(!empty($file)) {
|
|
$fileLocation = $this->et->userCacheDir."/{$file}";
|
|
$filename = substr($file, 36, strlen($file)); // strip GUID for PHPMailer class to name outbound file
|
|
|
|
$mail->AddAttachment($fileLocation, $filename, 'base64', $this->email2GetMime($fileLocation));
|
|
//$mail->AddAttachment($fileLocation, $filename, 'base64');
|
|
|
|
// only save attachments if we're archiving or drafting
|
|
if((($this->type == 'draft') && !empty($this->id)) || (isset($request['saveToSugar']) && $request['saveToSugar'] == 1)) {
|
|
$note = new Note();
|
|
$note->id = create_guid();
|
|
$note->new_with_id = true; // duplicating the note with files
|
|
$note->parent_id = $this->id;
|
|
$note->parent_type = $this->module_dir;
|
|
$note->name = $filename;
|
|
$note->filename = $filename;
|
|
$noteFile = "{$sugar_config['upload_dir']}{$note->id}";
|
|
$note->file_mime_type = $this->email2GetMime($noteFile);
|
|
|
|
|
|
|
|
|
|
if(!copy($fileLocation, $noteFile)) {
|
|
$GLOBALS['log']->debug("EMAIL 2.0: could not copy attachment file to cache/upload [ {$fileLocation} ]");
|
|
}
|
|
|
|
$note->save();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* handle sugar documents */
|
|
if(!empty($request['documents'])) {
|
|
$exDocs = explode("::", $request['documents']);
|
|
|
|
require_once('modules/Documents/Document.php');
|
|
require_once('modules/DocumentRevisions/DocumentRevision.php');
|
|
|
|
foreach($exDocs as $docId) {
|
|
$docId = trim($docId);
|
|
if(!empty($docId)) {
|
|
$doc = new Document();
|
|
$docRev = new DocumentRevision();
|
|
$doc->retrieve($docId);
|
|
$docRev->retrieve($doc->document_revision_id);
|
|
|
|
$filename = $docRev->filename;
|
|
$fileLocation = "{$sugar_config['upload_dir']}{$docRev->id}";
|
|
$mime_type = $docRev->file_mime_type;
|
|
$mail->AddAttachment($fileLocation, $filename, 'base64', $mime_type);
|
|
|
|
// only save attachments if we're archiving or drafting
|
|
if((($this->type == 'draft') && !empty($this->id)) || (isset($request['saveToSugar']) && $request['saveToSugar'] == 1)) {
|
|
$note = new Note();
|
|
$note->id = create_guid();
|
|
$note->new_with_id = true; // duplicating the note with files
|
|
$note->parent_id = $this->id;
|
|
$note->parent_type = $this->module_dir;
|
|
$note->name = $filename;
|
|
$note->filename = $filename;
|
|
$note->file_mime_type = $mime_type;
|
|
|
|
|
|
|
|
$noteFile = "{$sugar_config['upload_dir']}{$note->id}";
|
|
|
|
if(!copy($fileLocation, $noteFile)) {
|
|
$GLOBALS['log']->debug("EMAIL 2.0: could not copy SugarDocument revision file to cache/upload [ {$fileLocation} ]");
|
|
}
|
|
|
|
$note->save();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* handle template attachments */
|
|
if(!empty($request['templateAttachments'])) {
|
|
require_once("modules/Notes/Note.php");
|
|
$exNotes = explode("::", $request['templateAttachments']);
|
|
foreach($exNotes as $noteId) {
|
|
$noteId = trim($noteId);
|
|
if(!empty($noteId)) {
|
|
$note = new Note();
|
|
$note->retrieve($noteId);
|
|
if (!empty($note->id)) {
|
|
$filename = $note->filename;
|
|
$fileLocation = "{$sugar_config['upload_dir']}{$note->id}";
|
|
$mime_type = $note->file_mime_type;
|
|
if (!$note->embed_flag) {
|
|
$mail->AddAttachment($fileLocation, $filename, 'base64', $mime_type);
|
|
// only save attachments if we're archiving or drafting
|
|
if((($this->type == 'draft') && !empty($this->id)) || (isset($request['saveToSugar']) && $request['saveToSugar'] == 1)) {
|
|
|
|
if ($note->parent_id != $this->id) {
|
|
$note1 = new Note();
|
|
$note1->id = create_guid();
|
|
$note1->new_with_id = true; // duplicating the note with files
|
|
$note1->parent_id = $this->id;
|
|
$note1->parent_type = $this->module_dir;
|
|
$note1->name = $filename;
|
|
$note1->filename = $filename;
|
|
$note1->file_mime_type = $mime_type;
|
|
|
|
|
|
|
|
$noteFile = "{$sugar_config['upload_dir']}{$note1->id}";
|
|
if(!copy($fileLocation, $noteFile)) {
|
|
$GLOBALS['log']->debug("EMAIL 2.0: could not copy SugarDocument revision file to cache/upload [ {$fileLocation} ]");
|
|
}
|
|
$note1->save();
|
|
} // if
|
|
} // if
|
|
|
|
} // if
|
|
} else {
|
|
$fileLocation = $this->et->userCacheDir."/{$noteId}";
|
|
$filename = substr($noteId, 36, strlen($noteId)); // strip GUID for PHPMailer class to name outbound file
|
|
|
|
$mail->AddAttachment($fileLocation, $filename, 'base64', $this->email2GetMime($fileLocation));
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* Final Touches
|
|
*/
|
|
/* save email to sugar? */
|
|
$forceSave = false;
|
|
|
|
if($this->type == 'draft' && !isset($request['saveDraft'])) {
|
|
// sending a draft email
|
|
$this->type = 'out';
|
|
$this->status = 'sent';
|
|
$forceSave = true;
|
|
} elseif(isset($request['saveDraft'])) {
|
|
$this->type = 'draft';
|
|
$this->status = 'draft';
|
|
$forceSave = true;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SEND EMAIL (finally!)
|
|
*/
|
|
$mailSent = false;
|
|
|
|
|
|
|
|
if ($this->type != 'draft') {
|
|
$mail->prepForOutbound($request['sendCharset']);
|
|
if (!$mail->Send()) {
|
|
$this->status = 'send_error';
|
|
echo("Error emailing:".$mail->ErrorInfo);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ((!(empty($orignialId) || isset($request['saveDraft']) || ($this->type == 'draft' && $this->status == 'draft'))) &&
|
|
(($_REQUEST['composeType'] == 'reply') || ($_REQUEST['composeType'] == 'replyCase')) && ($orignialId != $this->id)) {
|
|
$originalEmail = new Email();
|
|
$originalEmail->retrieve($orignialId);
|
|
$originalEmail->reply_to_status = 1;
|
|
$originalEmail->save();
|
|
} // if
|
|
|
|
|
|
if( $forceSave ||
|
|
$this->type == 'draft' ||
|
|
(isset($request['saveToSugar']) && $request['saveToSugar'] == 1)) {
|
|
|
|
// saving a draft OR saving a sent email
|
|
$decodedFromName = mb_decode_mimeheader($mail->FromName);
|
|
$this->from_addr = "{$decodedFromName} <{$mail->From}>";
|
|
$this->from_addr_name = $this->from_addr;
|
|
$this->to_addrs = $_REQUEST['sendTo'];
|
|
$this->to_addrs_names = $_REQUEST['sendTo'];
|
|
$this->cc_addrs = $_REQUEST['sendCc'];
|
|
$this->cc_addrs_names = $_REQUEST['sendCc'];
|
|
$this->bcc_addrs = $_REQUEST['sendBcc'];
|
|
$this->bcc_addrs_names = $_REQUEST['sendBcc'];
|
|
|
|
|
|
|
|
$this->assigned_user_id = $current_user->id;
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//// SAVE RAW MESSAGE
|
|
// cn: bug 10250 - MySQL requires certain settings to get the SQL buffer > 1Mb
|
|
if(isset($sugar_config['email_outbound_save_raw']) && $sugar_config['email_outbound_save_raw'] == true) {
|
|
$mail->SetMessageType();
|
|
$raw = $mail->CreateHeader();
|
|
$raw .= $mail->CreateBody();
|
|
$this->raw_source = to_html($raw);
|
|
}
|
|
//// END SAVE RAW MESSAGE
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
//require_once("modules/InboundEmail/InboundEmail.php");
|
|
//$conv = InboundEmail::getUnixHeaderDate('');
|
|
|
|
$this->date_sent = $timedate->convert_to_gmt_datetime('now');
|
|
$this->date_sent = $timedate->to_display_date_time($this->date_sent);
|
|
///////////////////////////////////////////////////////////////////
|
|
//// LINK EMAIL TO SUGARBEANS BASED ON EMAIL ADDY
|
|
|
|
if( isset($_REQUEST['parent_type']) && !empty($_REQUEST['parent_type']) &&
|
|
isset($_REQUEST['parent_id']) && !empty($_REQUEST['parent_id']) ) {
|
|
$this->parent_id = $_REQUEST['parent_id'];
|
|
$this->parent_type = $_REQUEST['parent_type'];
|
|
$q = "SELECT count(*) c FROM emails_beans WHERE email_id = '{$this->id}' AND bean_id = '{$_REQUEST['parent_id']}' AND bean_module = '{$_REQUEST['parent_type']}'";
|
|
$r = $this->db->query($q);
|
|
$a = $this->db->fetchByAssoc($r);
|
|
if($a['c'] <= 0) {
|
|
if(isset($beanList[$_REQUEST['parent_type']]) && !empty($beanList[$_REQUEST['parent_type']])) {
|
|
$className = $beanList[$_REQUEST['parent_type']];
|
|
if(isset($beanFiles[$className]) && !empty($beanFiles[$className])) {
|
|
if(!class_exists($className)) {
|
|
require_once($beanFiles[$className]);
|
|
}
|
|
$bean = new $className();
|
|
$bean->retrieve($_REQUEST['parent_id']);
|
|
if($bean->load_relationship('emails')) {
|
|
$bean->emails->add($this->id);
|
|
} // if
|
|
|
|
} // if
|
|
|
|
} // if
|
|
|
|
} // if
|
|
|
|
} else {
|
|
if(!class_exists('aCase')) {
|
|
require_once('modules/Cases/Case.php');
|
|
}
|
|
$c = new aCase();
|
|
if($caseId = InboundEmail::getCaseIdFromCaseNumber($mail->Subject, $c)) {
|
|
$c->retrieve($caseId);
|
|
$c->load_relationship('emails');
|
|
$c->emails->add($this->id);
|
|
$this->parent_type = "Cases";
|
|
$this->parent_id = $caseId;
|
|
} // if
|
|
|
|
} // else
|
|
|
|
/*
|
|
if(!empty($emailAddressCollection) && $this->type != 'draft') {
|
|
foreach($emailAddressCollection as $emailAddress) {
|
|
if(empty($emailAddress)) continue;
|
|
|
|
$beansCollection = $this->emailAddress->getBeansByEmailAddress($emailAddress);
|
|
|
|
foreach($beansCollection as $bean) {
|
|
if($bean->load_relationship('emails')) {
|
|
$bean->emails->add($this->id);
|
|
} else {
|
|
|
|
|
|
|
|
|
|
} // else
|
|
} // for
|
|
} // for
|
|
|
|
}*/
|
|
//// LINK EMAIL TO SUGARBEANS BASED ON EMAIL ADDY
|
|
///////////////////////////////////////////////////////////////////
|
|
$this->save();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(count($cnt_to)>0){
|
|
foreach($cnt_to as $key=>$value){
|
|
$email_to_id=create_guid();
|
|
mysql_query("insert into emails_beans(id,email_id,bean_id,bean_module,date_modified,deleted)
|
|
values('".create_guid()."','".$email_to_id."','".$key."','Contacts','".date("Y-m-d H:i:s")."','0')");
|
|
$email_to=new Email;
|
|
$email_to=$this;
|
|
$email_to->parent_type="Contacts";
|
|
$email_to->parent_id=$key;
|
|
$email_to->id=$email_to_id;
|
|
$email_to->assigned_user_id=$_SESSION['authenticated_user_id'];
|
|
$email_to->save();
|
|
}
|
|
}
|
|
if(count($cnt_cc)>0){
|
|
foreach($cnt_cc as $key=>$value){
|
|
$email_cc_id=create_guid();
|
|
mysql_query("insert into emails_beans(id,email_id,bean_id,bean_module,date_modified,deleted)
|
|
values('".create_guid()."','".$email_cc_id."','".$key."','Contacts','".date("Y-m-d H:i:s")."','0')");
|
|
$email_cc=new Email;
|
|
$email_cc=$this;
|
|
$email_cc->parent_type="Contacts";
|
|
$email_cc->parent_id=$key;
|
|
$email_cc->id=$email_cc_id;
|
|
$email_cc->assigned_user_id=$_SESSION['authenticated_user_id'];
|
|
$email_cc->save();
|
|
}
|
|
}
|
|
if(count($cnt_bcc)>0){
|
|
foreach($cnt_bcc as $key=>$value){
|
|
mysql_query("insert into emails_beans(id,email_id,bean_id,bean_module,date_modified,deleted)
|
|
values('".create_guid()."','".$this->id."','".$key."','Contacts','".date("Y-m-d H:i:s")."','0')");
|
|
$email_bcc=new Email;
|
|
$email_bcc=$this;
|
|
$email_bcc->parent_type="Contacts";
|
|
$email_bcc->parent_id=$key;
|
|
$email_bcc->id=create_guid();
|
|
$email_bcc->assigned_user_id=$_SESSION['authenticated_user_id'];
|
|
$email_bcc->save();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!empty($request['fromAccount'])) {
|
|
if (isset($ie->id) && !$ie->isPop3Protocol()) {
|
|
$sentFolder = $ie->get_stored_options("sentFolder");
|
|
if (!empty($sentFolder)) {
|
|
$data = $mail->CreateHeader() . "\r\n" . $mail->CreateBody() . "\r\n";
|
|
$ie->mailbox = $sentFolder;
|
|
if ($ie->connectMailserver() == 'true') {
|
|
$connectString = $ie->getConnectString($ie->getServiceString(), $ie->mailbox);
|
|
$returnData = imap_append($ie->conn,$connectString, $data, "\\Seen");
|
|
if (!$returnData) {
|
|
$GLOBALS['log']->debug("could not copy email to {$ie->mailbox} for {$ie->name}");
|
|
} // if
|
|
} else {
|
|
$GLOBALS['log']->debug("could not connect to mail serve for folder {$ie->mailbox} for {$ie->name}");
|
|
} // else
|
|
} else {
|
|
$GLOBALS['log']->debug("could not copy email to {$ie->mailbox} sent folder as its empty");
|
|
} // else
|
|
} // if
|
|
} // if
|
|
return true;
|
|
} // end email2send
|
|
|
|
/**
|
|
* Generates a comma sperated name and addresses to be used in compose email screen for contacts or leads
|
|
* from listview
|
|
*/
|
|
function getNamePlusEmailAddressesForCompose($table, $idsArray) {
|
|
global $locale;
|
|
global $db;
|
|
$table = strtolower($table);
|
|
$returndata = array();
|
|
$idsString = "";
|
|
foreach($idsArray as $id) {
|
|
if ($idsString != "") {
|
|
$idsString = $idsString . ",";
|
|
} // if
|
|
$idsString = $idsString . "'" . $id . "'";
|
|
} // foreach
|
|
$where = "({$table}.deleted = 0 AND {$table}.id in ({$idsString}))";
|
|
|
|
$selectColumn = "{$table}.first_name, {$table}.last_name, {$table}.salutation, {$table}.title";
|
|
if ($table == 'accounts') {
|
|
$selectColumn = "{$table}.name";
|
|
}
|
|
$query = "SELECT {$table}.id, {$selectColumn}, eabr.primary_address, ea.email_address";
|
|
$query .= " FROM {$table} ";
|
|
$query .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) ";
|
|
$query .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) ";
|
|
|
|
|
|
|
|
$query .= " WHERE ({$where}) ORDER BY eabr.primary_address DESC";
|
|
$r = $this->db->query($query);
|
|
|
|
while($a = $this->db->fetchByAssoc($r)) {
|
|
if (!isset($returndata[$a['id']])) {
|
|
if ($table == 'accounts') {
|
|
$returndata[$a['id']] = "{$a['name']} <".$a['email_address'].">";
|
|
} else {
|
|
$full_name = $locale->getLocaleFormattedName($a['first_name'], $a['last_name'], $a['salutation'], $a['title']);
|
|
$returndata[$a['id']] = "{$full_name} <".$a['email_address'].">";
|
|
} // else
|
|
}
|
|
}
|
|
|
|
return join(",", array_values($returndata));
|
|
}
|
|
|
|
/**
|
|
* Overrides
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// SAVERS
|
|
function save($check_notify = false) {
|
|
if($this->isDuplicate) {
|
|
$GLOBALS['log']->debug("EMAIL - tried to save a duplicate Email record");
|
|
} else {
|
|
|
|
if(empty($this->id)) {
|
|
$this->id = create_guid();
|
|
$this->new_with_id = true;
|
|
}
|
|
$this->saveEmailText();
|
|
$this->saveEmailAddresses();
|
|
|
|
$GLOBALS['log']->debug('-------------------------------> Email called save()');
|
|
|
|
// handle legacy concatenation of date and time fields
|
|
if(empty($this->date_sent)) $this->date_sent = $this->date_start." ".$this->time_start;
|
|
parent::save($check_notify);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles normalization of Email Addressess
|
|
*/
|
|
function saveEmailAddresses() {
|
|
// from, single address
|
|
$fromId = $this->emailAddress->getEmailGUID(from_html($this->from_addr));
|
|
if(!empty($fromId)){
|
|
$this->linkEmailToAddress($fromId, 'from');
|
|
}
|
|
|
|
// to, multiple
|
|
$replace = array(",",";");
|
|
$toaddrs = str_replace($replace, "::", from_html($this->to_addrs));
|
|
$exToAddrs = explode("::", $toaddrs);
|
|
|
|
if(!empty($exToAddrs)) {
|
|
foreach($exToAddrs as $toaddr) {
|
|
$toaddr = trim($toaddr);
|
|
if(!empty($toaddr)) {
|
|
$toId = $this->emailAddress->getEmailGUID($toaddr);
|
|
$this->linkEmailToAddress($toId, 'to');
|
|
}
|
|
}
|
|
}
|
|
|
|
// cc, multiple
|
|
$ccAddrs = str_replace($replace, "::", from_html($this->cc_addrs));
|
|
$exccAddrs = explode("::", $ccAddrs);
|
|
|
|
if(!empty($exccAddrs)) {
|
|
foreach($exccAddrs as $ccAddr) {
|
|
$ccAddr = trim($ccAddr);
|
|
if(!empty($ccAddr)) {
|
|
$ccId = $this->emailAddress->getEmailGUID($ccAddr);
|
|
$this->linkEmailToAddress($ccId, 'cc');
|
|
}
|
|
}
|
|
}
|
|
|
|
// bcc, multiple
|
|
$bccAddrs = str_replace($replace, "::", from_html($this->bcc_addrs));
|
|
$exbccAddrs = explode("::", $bccAddrs);
|
|
if(!empty($exbccAddrs)) {
|
|
foreach($exbccAddrs as $bccAddr) {
|
|
$bccAddr = trim($bccAddr);
|
|
if(!empty($bccAddr)) {
|
|
$bccId = $this->emailAddress->getEmailGUID($bccAddr);
|
|
$this->linkEmailToAddress($bccId, 'bcc');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function linkEmailToAddress($id, $type) {
|
|
// TODO: make this update?
|
|
$q1 = "SELECT * FROM emails_email_addr_rel WHERE email_id = '{$this->id}' AND email_address_id = '{$id}' AND address_type = '{$type}' AND deleted = 0";
|
|
$r1 = $this->db->query($q1);
|
|
$a1 = $this->db->fetchByAssoc($r1);
|
|
|
|
if(!empty($a1) && !empty($a1['id'])) {
|
|
return $a1['id'];
|
|
} else {
|
|
$guid = create_guid();
|
|
$q2 = "INSERT INTO emails_email_addr_rel VALUES('{$guid}', '{$this->id}', '{$type}', '{$id}', 0)";
|
|
$r2 = $this->db->query($q2);
|
|
}
|
|
|
|
return $guid;
|
|
}
|
|
|
|
|
|
function saveEmailText() {
|
|
$isOracle = ($this->db->dbType == "oci8") ? true : false;
|
|
if ($isOracle) {
|
|
|
|
|
|
|
|
} else {
|
|
$description = $this->db->quote(trim($this->description));
|
|
$description_html = $this->db->quoteForEmail(trim($this->description_html));
|
|
$raw_source = $this->db->quote(trim($this->raw_source));
|
|
$fromAddressName = $this->db->helper->escape_quote($this->from_addr_name);
|
|
$toAddressName = $this->db->helper->escape_quote($this->to_addrs_names);
|
|
$ccAddressName = $this->db->helper->escape_quote($this->cc_addrs_names);
|
|
$bccAddressName = $this->db->helper->escape_quote($this->bcc_addrs_names);
|
|
$replyToAddrName = $this->db->helper->escape_quote($this->reply_to_addr);
|
|
|
|
if(!$this->new_with_id) {
|
|
$q = "UPDATE emails_text SET from_addr = '{$fromAddressName}', to_addrs = '{$toAddressName}', cc_addrs = '{$ccAddressName}', bcc_addrs = '{$bccAddressName}', reply_to_addr = '{$replyToAddrName}', description = '{$description}', description_html = '{$description_html}', raw_source = '{$raw_source}' WHERE email_id = '{$this->id}'";
|
|
} else {
|
|
$q = "INSERT INTO emails_text (email_id, from_addr, to_addrs, cc_addrs, bcc_addrs, reply_to_addr, description, description_html, raw_source, deleted) VALUES('{$this->id}', '{$fromAddressName}', '{$toAddressName}', '{$ccAddressName}', '{$bccAddressName}', '{$replyToAddrName}', '{$description}', '{$description_html}', '{$raw_source}', 0)";
|
|
}
|
|
$this->db->query($q);
|
|
} // else
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// RETRIEVERS
|
|
function retrieve($id, $encoded=true, $deleted=true) {
|
|
// cn: bug 11915, return SugarBean's retrieve() call bean instead of $this
|
|
$ret = parent::retrieve($id, $encoded, $deleted);
|
|
|
|
if($ret) {
|
|
$ret->raw_source = to_html($ret->safeText(from_html($ret->raw_source)));
|
|
$ret->description = to_html($ret->safeText(from_html($ret->description)));
|
|
$ret->description_html = $ret->safeText($ret->description_html);
|
|
$ret->retrieveEmailText();
|
|
$ret->retrieveEmailAddresses();
|
|
|
|
$dateSent = explode(' ', $ret->date_sent);
|
|
if (!empty($dateSent)) {
|
|
$ret->date_start = $dateSent[0];
|
|
$ret->time_start = $dateSent[1];
|
|
} else {
|
|
$ret->date_start = '';
|
|
$ret->time_start = '';
|
|
} // else
|
|
// for Email 2.0
|
|
foreach($ret as $k => $v) {
|
|
$this->$k = $v;
|
|
}
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves email addresses from GUIDs
|
|
*/
|
|
function retrieveEmailAddresses() {
|
|
$return = array();
|
|
|
|
$q = "SELECT email_address, address_type
|
|
FROM emails_email_addr_rel eam
|
|
JOIN email_addresses ea ON ea.id = eam.email_address_id
|
|
WHERE eam.email_id = '{$this->id}' AND eam.deleted=0";
|
|
$r = $this->db->query($q);
|
|
|
|
while($a = $this->db->fetchByAssoc($r)) {
|
|
if(!isset($return[$a['address_type']])) {
|
|
$return[$a['address_type']] = array();
|
|
}
|
|
$return[$a['address_type']][] = $a['email_address'];
|
|
}
|
|
|
|
if(count($return) > 0) {
|
|
if(isset($return['from'])) {
|
|
$this->from_addr = implode(", ", $return['from']);
|
|
}
|
|
if(isset($return['to'])) {
|
|
$this->to_addrs = implode(", ", $return['to']);
|
|
}
|
|
if(isset($return['cc'])) {
|
|
$this->cc_addrs = implode(", ", $return['cc']);
|
|
}
|
|
if(isset($return['bcc'])) {
|
|
$this->bcc_addrs = implode(", ", $return['bcc']);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles longtext fields
|
|
*/
|
|
function retrieveEmailText() {
|
|
$q = "SELECT from_addr, reply_to_addr, to_addrs, cc_addrs, bcc_addrs, description, description_html, raw_source FROM emails_text WHERE email_id = '{$this->id}'";
|
|
$r = $this->db->query($q);
|
|
$a = $this->db->fetchByAssoc($r, -1, false);
|
|
|
|
$this->description = $a['description'];
|
|
$this->description_html = $a['description_html'];
|
|
$this->raw_source = $a['raw_source'];
|
|
$this->from_addr_name = $a['from_addr'];
|
|
$this->reply_to_addr = $a['reply_to_addr'];
|
|
$this->to_addrs_names = $a['to_addrs'];
|
|
$this->cc_addrs_names = $a['cc_addrs'];
|
|
$this->bcc_addrs_names = $a['bcc_addrs'];
|
|
}
|
|
|
|
function delete($id='') {
|
|
if(empty($id))
|
|
$id = $this->id;
|
|
|
|
$q = "UPDATE emails SET deleted = 1 WHERE id = '{$id}'";
|
|
$qt = "UPDATE emails_text SET deleted = 1 WHERE email_id = '{$id}'";
|
|
$r = $this->db->query($q);
|
|
$rt = $this->db->query($qt);
|
|
}
|
|
|
|
/**
|
|
* creates the standard "Forward" info at the top of the forwarded message
|
|
* @return string
|
|
*/
|
|
function getForwardHeader() {
|
|
global $mod_strings;
|
|
global $current_user;
|
|
|
|
//$from = str_replace(array(">","<"), array(")","("), $this->from_name);
|
|
$from = to_html($this->from_name);
|
|
$subject = to_html($this->name);
|
|
$ret = "<br /><br />";
|
|
$ret .= $this->replyDelimiter."{$mod_strings['LBL_FROM']} {$from}<br />";
|
|
$ret .= $this->replyDelimiter."{$mod_strings['LBL_DATE_SENT']} {$this->date_sent}<br />";
|
|
$ret .= $this->replyDelimiter."{$mod_strings['LBL_TO']} {$this->to_addrs}<br />";
|
|
$ret .= $this->replyDelimiter."{$mod_strings['LBL_CC']} {$this->cc_addrs}<br />";
|
|
$ret .= $this->replyDelimiter."{$mod_strings['LBL_SUBJECT']} {$subject}<br />";
|
|
$ret .= $this->replyDelimiter."<br />";
|
|
|
|
return $ret;
|
|
//return from_html($ret);
|
|
}
|
|
|
|
/**
|
|
* retrieves Notes that belong to this Email and stuffs them into the "attachments" attribute
|
|
*/
|
|
function getNotes($id, $duplicate=false) {
|
|
if(!class_exists('Note')) {
|
|
require_once('modules/Notes/Note.php');
|
|
}
|
|
|
|
$exRemoved = array();
|
|
if(isset($_REQUEST['removeAttachment'])) {
|
|
$exRemoved = explode('::', $_REQUEST['removeAttachment']);
|
|
}
|
|
|
|
$noteArray = array();
|
|
$q = "SELECT id FROM notes WHERE parent_id = '".$id."'";
|
|
$r = $this->db->query($q);
|
|
|
|
while($a = $this->db->fetchByAssoc($r)) {
|
|
if(!in_array($a['id'], $exRemoved)) {
|
|
$note = new Note();
|
|
$note->retrieve($a['id']);
|
|
|
|
// duplicate actual file when creating forwards
|
|
if($duplicate) {
|
|
if(!class_exists('UploadFile')) {
|
|
require_once('include/upload_file.php');
|
|
}
|
|
// save a brand new Note
|
|
$noteDupe->id = create_guid();
|
|
$noteDupe->new_with_id = true;
|
|
$noteDupe->parent_id = $this->id;
|
|
$noteDupe->parent_type = $this->module_dir;
|
|
|
|
$noteFile = new UploadFile('none');
|
|
$noteFile->duplicate_file($a['id'], $note->id, $note->filename);
|
|
|
|
$note->save();
|
|
}
|
|
// add Note to attachments array
|
|
$this->attachments[] = $note;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* creates the standard "Reply" info at the top of the forwarded message
|
|
* @return string
|
|
*/
|
|
function getReplyHeader() {
|
|
global $mod_strings;
|
|
global $current_user;
|
|
|
|
$from = str_replace(array(">","<", ">","<"), array(")","(",")","("), $this->from_name);
|
|
$ret = "<br>{$mod_strings['LBL_REPLY_HEADER_1']} {$this->date_start}, {$this->time_start}, {$from} {$mod_strings['LBL_REPLY_HEADER_2']}";
|
|
|
|
return from_html($ret);
|
|
}
|
|
|
|
/**
|
|
* Quotes plain-text email text
|
|
* @param string $text
|
|
* @return string
|
|
*/
|
|
function quotePlainTextEmail($text) {
|
|
$quoted = "\n";
|
|
|
|
// plain-text
|
|
$desc = nl2br(trim($text));
|
|
$exDesc = explode('<br />', $desc);
|
|
|
|
foreach($exDesc as $k => $line) {
|
|
$quoted .= '> '.trim($line)."\r";
|
|
}
|
|
|
|
return $quoted;
|
|
}
|
|
|
|
/**
|
|
* "quotes" (i.e., "> my text yadda" the HTML part of an email
|
|
* @param string $text HTML text to quote
|
|
* @return string
|
|
*/
|
|
function quoteHtmlEmail($text) {
|
|
$text = trim(from_html($text));
|
|
|
|
if(empty($text)) {
|
|
return '';
|
|
}
|
|
$out = "<div style='border-left:1px solid #00c; padding:5px; margin-left:10px;'>{$text}</div>";
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* "quotes" (i.e., "> my text yadda" the HTML part of an email
|
|
* @param string $text HTML text to quote
|
|
* @return string
|
|
*/
|
|
function quoteHtmlEmailForNewEmailUI($text) {
|
|
$text = trim($text);
|
|
|
|
if(empty($text)) {
|
|
return '';
|
|
}
|
|
$out = "<div style='border-left:1px solid #00c; padding:5px; margin-left:10px;'>{$text}</div>";
|
|
|
|
return $out;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// LEGACY CODE
|
|
/**
|
|
* Safes description text (both HTML and Plain Text) for display
|
|
* @param string str The text to safe
|
|
* @return string Safed text
|
|
*/
|
|
function safeText($str) {
|
|
// Safe_HTML
|
|
$this->safe->clear();
|
|
$ret = $this->safe->parse($str);
|
|
|
|
// Julian's XSS cleaner
|
|
$potentials = clean_xss($str, false);
|
|
|
|
if(is_array($potentials) && !empty($potentials)) {
|
|
//_ppl($potentials);
|
|
foreach($potentials as $bad) {
|
|
$ret = str_replace($bad, "", $ret);
|
|
}
|
|
}
|
|
|
|
// clean <HTML> and <BODY> tags
|
|
$html = '#<\\\\\?HTML[\w =\'\"\&]*>#sim';
|
|
$body = '#<\\\\\?BODY[\w =\'\"\&]*>#sim';
|
|
|
|
$ret = preg_replace($html, "", $ret);
|
|
$ret = preg_replace($body, "", $ret);
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Ensures that the user is able to send outbound emails
|
|
*/
|
|
function check_email_settings() {
|
|
global $current_user;
|
|
|
|
$mail_fromaddress = $current_user->emailAddress->getPrimaryAddress($current_user);
|
|
$replyToName = $current_user->getPreference('mail_fromname');
|
|
$mail_fromname = (!empty($replyToName)) ? $current_user->getPreference('mail_fromname') : $current_user->full_name;
|
|
|
|
if(empty($mail_fromaddress)) {
|
|
return false;
|
|
}
|
|
if(empty($mail_fromname)) {
|
|
return false;
|
|
}
|
|
|
|
$send_type = $current_user->getPreference('mail_sendtype') ;
|
|
if (!empty($send_type) && $send_type == "SMTP") {
|
|
$mail_smtpserver = $current_user->getPreference('mail_smtpserver');
|
|
$mail_smtpport = $current_user->getPreference('mail_smtpport');
|
|
$mail_smtpauth_req = $current_user->getPreference('mail_smtpauth_req');
|
|
$mail_smtpuser = $current_user->getPreference('mail_smtpuser');
|
|
$mail_smtppass = $current_user->getPreference('mail_smtppass');
|
|
if (empty($mail_smtpserver) ||
|
|
empty($mail_smtpport) ||
|
|
(!empty($mail_smtpauth_req) && ( empty($mail_smtpuser) || empty($mail_smtppass)))
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* outputs JS to set fields in the MassUpdate form in the "My Inbox" view
|
|
*/
|
|
function js_set_archived() {
|
|
global $mod_strings;
|
|
$script = '
|
|
<script type="text/javascript" language="JavaScript"><!-- Begin
|
|
function setArchived() {
|
|
var form = document.getElementById("MassUpdate");
|
|
var status = document.getElementById("mass_status");
|
|
var ok = false;
|
|
|
|
for(var i=0; i < form.elements.length; i++) {
|
|
if(form.elements[i].name == "mass[]") {
|
|
if(form.elements[i].checked == true) {
|
|
ok = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ok == true) {
|
|
var user = document.getElementById("mass_assigned_user_name");
|
|
var team = document.getElementById("team");
|
|
|
|
user.value = "";
|
|
for(var j=0; j<status.length; j++) {
|
|
if(status.options[j].value == "archived") {
|
|
status.options[j].selected = true;
|
|
status.selectedIndex = j; // for IE
|
|
}
|
|
}
|
|
|
|
form.submit();
|
|
} else {
|
|
alert("'.$mod_strings['ERR_ARCHIVE_EMAIL'].'");
|
|
}
|
|
|
|
}
|
|
// End --></script>';
|
|
return $script;
|
|
}
|
|
|
|
/**
|
|
* replaces the javascript in utils.php - more specialized
|
|
*/
|
|
function u_get_clear_form_js($type='', $group='', $assigned_user_id='') {
|
|
$uType = '';
|
|
$uGroup = '';
|
|
$uAssigned_user_id = '';
|
|
|
|
if(!empty($type)) { $uType = '&type='.$type; }
|
|
if(!empty($group)) { $uGroup = '&group='.$group; }
|
|
if(!empty($assigned_user_id)) { $uAssigned_user_id = '&assigned_user_id='.$assigned_user_id; }
|
|
|
|
$the_script = '
|
|
<script type="text/javascript" language="JavaScript"><!-- Begin
|
|
function clear_form(form) {
|
|
var newLoc = "index.php?action=" + form.action.value + "&module=" + form.module.value + "&query=true&clear_query=true'.$uType.$uGroup.$uAssigned_user_id.'";
|
|
if(typeof(form.advanced) != "undefined"){
|
|
newLoc += "&advanced=" + form.advanced.value;
|
|
}
|
|
document.location.href= newLoc;
|
|
}
|
|
// End --></script>';
|
|
return $the_script;
|
|
}
|
|
|
|
function pickOneButton() {
|
|
global $theme;
|
|
global $mod_strings;
|
|
$out = '<div class="listViewButtons"><input title="'.$mod_strings['LBL_BUTTON_GRAB_TITLE'].'"
|
|
accessKey="'.$mod_strings['LBL_BUTTON_GRAB_KEY'].'"
|
|
class="button"
|
|
type="button" name="button"
|
|
onClick="window.location=\'index.php?module=Emails&action=Grab\';"
|
|
style="margin-bottom:2px"
|
|
value=" '.$mod_strings['LBL_BUTTON_GRAB'].' "></div>';
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Determines what Editor (HTML or Plain-text) the current_user uses;
|
|
* @return string Editor type
|
|
*/
|
|
function getUserEditorPreference() {
|
|
global $sugar_config;
|
|
global $current_user;
|
|
|
|
$editor = '';
|
|
|
|
if(!isset($sugar_config['email_default_editor'])) {
|
|
$sugar_config = $current_user->setDefaultsInConfig();
|
|
}
|
|
|
|
$userEditor = $current_user->getPreference('email_editor_option');
|
|
$systemEditor = $sugar_config['email_default_editor'];
|
|
|
|
if($userEditor != '') {
|
|
$editor = $userEditor;
|
|
} else {
|
|
$editor = $systemEditor;
|
|
}
|
|
|
|
return $editor;
|
|
}
|
|
|
|
/**
|
|
* takes the mess we pass from EditView and tries to create some kind of order
|
|
* @param array addrs
|
|
* @param array addrs_ids (from contacts)
|
|
* @param array addrs_names (from contacts);
|
|
* @param array addrs_emails (from contacts);
|
|
* @return array Parsed assoc array to feed to PHPMailer
|
|
*/
|
|
function parse_addrs($addrs, $addrs_ids, $addrs_names, $addrs_emails) {
|
|
// cn: bug 9406 - enable commas to separate email addresses
|
|
$addrs = str_replace(",", ";", $addrs);
|
|
|
|
$ltgt = array('<','>');
|
|
$gtlt = array('<','>');
|
|
|
|
$return = array();
|
|
$addrs = str_replace($ltgt, '', $addrs);
|
|
$addrs_arr = explode(";",$addrs);
|
|
$addrs_arr = $this->remove_empty_fields($addrs_arr);
|
|
$addrs_ids_arr = explode(";",$addrs_ids);
|
|
$addrs_ids_arr = $this->remove_empty_fields($addrs_ids_arr);
|
|
$addrs_emails_arr = explode(";",$addrs_emails);
|
|
$addrs_emails_arr = $this->remove_empty_fields($addrs_emails_arr);
|
|
$addrs_names_arr = explode(";",$addrs_names);
|
|
$addrs_names_arr = $this->remove_empty_fields($addrs_names_arr);
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// HANDLE EMAILS HAND-WRITTEN
|
|
$contactRecipients = array();
|
|
$knownEmails = array();
|
|
|
|
foreach($addrs_arr as $i => $v) {
|
|
if(trim($v) == "")
|
|
continue; // skip any "blanks" - will always have 1
|
|
|
|
$recipient = array();
|
|
|
|
//// get the email to see if we're dealing with a dupe
|
|
//// what crappy coding
|
|
preg_match("/[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/i",$v, $match);
|
|
|
|
if(!empty($match[0]) && !in_array(trim($match[0]), $knownEmails)) {
|
|
$knownEmails[] = $match[0];
|
|
$recipient['email'] = $match[0];
|
|
|
|
//// handle the Display name
|
|
$display = trim(str_replace($match[0], '', $v));
|
|
|
|
//// only trigger a "displayName" <email@address> when necessary
|
|
if(isset($addrs_names_arr[$i])){
|
|
$recipient['display'] = $addrs_names_arr[$i];
|
|
}
|
|
else if(!empty($display)) {
|
|
$recipient['display'] = $display;
|
|
}
|
|
if(isset($addrs_ids_arr[$i]) && $addrs_emails_arr[$i] == $match[0]){
|
|
$recipient['contact_id'] = $addrs_ids_arr[$i];
|
|
}
|
|
$return[] = $recipient;
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
function remove_empty_fields(&$arr) {
|
|
$newarr = array();
|
|
|
|
foreach($arr as $field) {
|
|
$field = trim($field);
|
|
if(empty($field)) {
|
|
continue;
|
|
}
|
|
array_push($newarr,$field);
|
|
}
|
|
return $newarr;
|
|
}
|
|
|
|
/**
|
|
* handles attachments of various kinds when sending email
|
|
*/
|
|
function handleAttachments() {
|
|
require_once('modules/Documents/Document.php');
|
|
require_once('modules/DocumentRevisions/DocumentRevision.php');
|
|
require_once('modules/Notes/Note.php');
|
|
|
|
global $mod_strings;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// ATTACHMENTS FROM DRAFTS
|
|
if(($this->type == 'out' || $this->type == 'draft') && $this->status == 'draft' && isset($_REQUEST['record'])) {
|
|
$this->getNotes($_REQUEST['record']); // cn: get notes from OLD email for use in new email
|
|
}
|
|
//// END ATTACHMENTS FROM DRAFTS
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// ATTACHMENTS FROM FORWARDS
|
|
// Bug 8034 Jenny - Need the check for type 'draft' here to handle cases where we want to save
|
|
// forwarded messages as drafts. We still need to save the original message's attachments.
|
|
if(($this->type == 'out' || $this->type == 'draft') &&
|
|
isset($_REQUEST['origType']) && $_REQUEST['origType'] == 'forward' &&
|
|
isset($_REQUEST['return_id']) && !empty($_REQUEST['return_id'])
|
|
) {
|
|
$this->getNotes($_REQUEST['return_id'], true);
|
|
}
|
|
|
|
// cn: bug 8034 - attachments from forward/replies lost when saving in draft
|
|
if(isset($_REQUEST['prior_attachments']) && !empty($_REQUEST['prior_attachments']) && $this->new_with_id == true) {
|
|
$exIds = explode(",", $_REQUEST['prior_attachments']);
|
|
if(!isset($_REQUEST['template_attachment'])) {
|
|
$_REQUEST['template_attachment'] = array();
|
|
}
|
|
$_REQUEST['template_attachment'] = array_merge($_REQUEST['template_attachment'], $exIds);
|
|
}
|
|
//// END ATTACHMENTS FROM FORWARDS
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// ATTACHMENTS FROM TEMPLATES
|
|
// to preserve individual email integrity, we must dupe Notes and associated files
|
|
// for each outbound email - good for integrity, bad for filespace
|
|
if(isset($_REQUEST['template_attachment']) && !empty($_REQUEST['template_attachment'])) {
|
|
$removeArr = array();
|
|
$noteArray = array();
|
|
|
|
if(isset($_REQUEST['temp_remove_attachment']) && !empty($_REQUEST['temp_remove_attachment'])) {
|
|
$removeArr = $_REQUEST['temp_remove_attachment'];
|
|
}
|
|
|
|
|
|
foreach($_REQUEST['template_attachment'] as $noteId) {
|
|
if(in_array($noteId, $removeArr)) {
|
|
continue;
|
|
}
|
|
$noteTemplate = new Note();
|
|
$noteTemplate->retrieve($noteId);
|
|
$noteTemplate->id = create_guid();
|
|
$noteTemplate->new_with_id = true; // duplicating the note with files
|
|
$noteTemplate->parent_id = $this->id;
|
|
$noteTemplate->parent_type = $this->module_dir;
|
|
$noteTemplate->save();
|
|
|
|
|
|
|
|
|
|
$noteFile = new UploadFile('none');
|
|
$noteFile->duplicate_file($noteId, $noteTemplate->id, $noteTemplate->filename);
|
|
$noteArray[] = $noteTemplate;
|
|
}
|
|
$this->attachments = array_merge($this->attachments, $noteArray);
|
|
}
|
|
//// END ATTACHMENTS FROM TEMPLATES
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// ADDING NEW ATTACHMENTS
|
|
$max_files_upload = 10;
|
|
// Jenny - Bug 8211 Since attachments for drafts have already been processed,
|
|
// we don't need to re-process them.
|
|
if($this->status != "draft") {
|
|
$notes_list = array();
|
|
if(!empty($this->id) && !$this->new_with_id) {
|
|
$note = new Note();
|
|
$where = "notes.parent_id='{$this->id}'";
|
|
$notes_list = $note->get_full_list("", $where, true);
|
|
}
|
|
$this->attachments = array_merge($this->attachments, $notes_list);
|
|
}
|
|
// cn: Bug 5995 - rudimentary error checking
|
|
$filesError = array(
|
|
0 => 'UPLOAD_ERR_OK - There is no error, the file uploaded with success.',
|
|
1 => 'UPLOAD_ERR_INI_SIZE - The uploaded file exceeds the upload_max_filesize directive in php.ini.',
|
|
2 => 'UPLOAD_ERR_FORM_SIZE - The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
|
|
3 => 'UPLOAD_ERR_PARTIAL - The uploaded file was only partially uploaded.',
|
|
4 => 'UPLOAD_ERR_NO_FILE - No file was uploaded.',
|
|
5 => 'UNKNOWN ERROR',
|
|
6 => 'UPLOAD_ERR_NO_TMP_DIR - Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.',
|
|
7 => 'UPLOAD_ERR_CANT_WRITE - Failed to write file to disk. Introduced in PHP 5.1.0.',
|
|
);
|
|
|
|
for($i = 0; $i < $max_files_upload; $i++) {
|
|
// cn: Bug 5995 - rudimentary error checking
|
|
if (!isset($_FILES["email_attachment{$i}"])) {
|
|
$GLOBALS['log']->debug("Email Attachment {$i} does not exist.");
|
|
continue;
|
|
}
|
|
if($_FILES['email_attachment'.$i]['error'] != 0 && $_FILES['email_attachment'.$i]['error'] != 4) {
|
|
$GLOBALS['log']->debug('Email Attachment could not be attach due to error: '.$filesError[$_FILES['email_attachment'.$i]['error']]);
|
|
continue;
|
|
}
|
|
|
|
$note = new Note();
|
|
$note->parent_id = $this->id;
|
|
$note->parent_type = $this->module_dir;
|
|
$upload_file = new UploadFile('email_attachment'.$i);
|
|
|
|
if(empty($upload_file)) {
|
|
continue;
|
|
}
|
|
|
|
if(isset($_FILES['email_attachment'.$i]) && $upload_file->confirm_upload()) {
|
|
$note->filename = $upload_file->get_stored_file_name();
|
|
$note->file = $upload_file;
|
|
$note->name = $mod_strings['LBL_EMAIL_ATTACHMENT'].': '.$note->file->original_file_name;
|
|
|
|
|
|
|
|
|
|
$this->attachments[] = $note;
|
|
}
|
|
}
|
|
|
|
$this->saved_attachments = array();
|
|
foreach($this->attachments as $note) {
|
|
if(!empty($note->id)) {
|
|
array_push($this->saved_attachments, $note);
|
|
continue;
|
|
}
|
|
$note->parent_id = $this->id;
|
|
$note->parent_type = 'Emails';
|
|
$note->file_mime_type = $note->file->mime_type;
|
|
$note_id = $note->save();
|
|
|
|
$this->saved_attachments[] = $note;
|
|
|
|
$note->id = $note_id;
|
|
$note->file->final_move($note->id);
|
|
}
|
|
//// END NEW ATTACHMENTS
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// ATTACHMENTS FROM DOCUMENTS
|
|
for($i=0; $i<10; $i++) {
|
|
if(isset($_REQUEST['documentId'.$i]) && !empty($_REQUEST['documentId'.$i])) {
|
|
$doc = new Document();
|
|
$docRev = new DocumentRevision();
|
|
$docNote = new Note();
|
|
$noteFile = new UploadFile('none');
|
|
|
|
$doc->retrieve($_REQUEST['documentId'.$i]);
|
|
$docRev->retrieve($doc->document_revision_id);
|
|
|
|
$this->saved_attachments[] = $docRev;
|
|
|
|
// cn: bug 9723 - Emails with documents send GUID instead of Doc name
|
|
$docNote->name = $docRev->getDocumentRevisionNameForDisplay();
|
|
$docNote->filename = $docRev->filename;
|
|
$docNote->description = $doc->description;
|
|
$docNote->parent_id = $this->id;
|
|
$docNote->parent_type = 'Emails';
|
|
$docNote->file_mime_type = $docRev->file_mime_type;
|
|
$docId = $docNote = $docNote->save();
|
|
|
|
$noteFile->duplicate_file($docRev->id, $docId, $docRev->filename);
|
|
}
|
|
}
|
|
|
|
//// END ATTACHMENTS FROM DOCUMENTS
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//// REMOVE ATTACHMENTS
|
|
if(isset($_REQUEST['remove_attachment']) && !empty($_REQUEST['remove_attachment'])) {
|
|
foreach($_REQUEST['remove_attachment'] as $noteId) {
|
|
$q = 'UPDATE notes SET deleted = 1 WHERE id = \''.$noteId.'\'';
|
|
$this->db->query($q);
|
|
}
|
|
}
|
|
|
|
//this will remove attachments that have been selected to be removed from drafts.
|
|
if(isset($_REQUEST['removeAttachment']) && !empty($_REQUEST['removeAttachment'])) {
|
|
$exRemoved = explode('::', $_REQUEST['removeAttachment']);
|
|
foreach($exRemoved as $noteId) {
|
|
$q = 'UPDATE notes SET deleted = 1 WHERE id = \''.$noteId.'\'';
|
|
$this->db->query($q);
|
|
}
|
|
}
|
|
//// END REMOVE ATTACHMENTS
|
|
///////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
|
|
/**
|
|
* Determines if an email body (HTML or Plain) has a User signature already in the content
|
|
* @param array Array of signatures
|
|
* @return bool
|
|
*/
|
|
function hasSignatureInBody($sig) {
|
|
// strpos can't handle line breaks - normalize
|
|
$html = $this->removeAllNewlines($this->description_html);
|
|
$htmlSig = $this->removeAllNewlines($sig['signature_html']);
|
|
$plain = $this->removeAllNewlines($this->description);
|
|
$plainSig = $this->removeAllNewlines($sig['signature']);
|
|
|
|
// cn: bug 11621 - empty sig triggers notice error
|
|
if(!empty($htmlSig) && false !== strpos($html, $htmlSig)) {
|
|
return true;
|
|
} elseif(!empty($plainSig) && false !== strpos($plain, $plainSig)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* internal helper
|
|
* @param string String to be normalized
|
|
* @return string
|
|
*/
|
|
function removeAllNewlines($str) {
|
|
$bad = array("\r\n", "\n\r", "\n", "\r");
|
|
$good = array('', '', '', '');
|
|
|
|
return str_replace($bad, $good, strip_tags(br2nl(from_html($str))));
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Set navigation anchors to aid DetailView record navigation (VCR buttons)
|
|
* @param string uri The URI from the referring page (always ListView)
|
|
* @return array start Array of the URI broken down with a special "current_view" for My Inbox Navs
|
|
*/
|
|
function getStartPage($uri) {
|
|
if(strpos($uri, '&')) { // "&" to ensure that we can explode the GET vars - else we're gonna trigger a Notice error
|
|
$serial = substr($uri, (strpos($uri, '?')+1), strlen($uri));
|
|
$exUri = explode('&', $serial);
|
|
$start = array('module' => '', 'action' => '', 'group' => '', 'record' => '', 'type' => '');
|
|
|
|
foreach($exUri as $k => $pair) {
|
|
$exPair = explode('=', $pair);
|
|
$start[$exPair[0]] = $exPair[1];
|
|
}
|
|
|
|
// specific views for current_user
|
|
if(isset($start['assigned_user_id'])) {
|
|
$start['current_view'] = "{$start['action']}&module={$start['module']}&assigned_user_id={$start['assigned_user_id']}&type={$start['type']}";
|
|
}
|
|
|
|
return $start;
|
|
} else {
|
|
return array();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* preps SMTP info for email transmission
|
|
* @param object mail SugarPHPMailer object
|
|
* @param string mailer_id
|
|
* @param string ieId
|
|
* @return object mail SugarPHPMailer object
|
|
*/
|
|
function setMailer($mail, $mailer_id='', $ieId='') {
|
|
global $current_user;
|
|
|
|
require_once("include/OutboundEmail/OutboundEmail.php");
|
|
$oe = new OutboundEmail();
|
|
$oe = $oe->getInboundMailerSettings($current_user, $mailer_id, $ieId);
|
|
|
|
// ssl or tcp - keeping outside isSMTP b/c a default may inadvertantly set ssl://
|
|
$mail->protocol = ($oe->mail_smtpssl) ? "ssl://" : "tcp://";
|
|
|
|
if($oe->mail_sendtype == "SMTP") {
|
|
$mail->Mailer = "smtp";
|
|
$mail->Host = $oe->mail_smtpserver;
|
|
$mail->Port = $oe->mail_smtpport;
|
|
|
|
if($oe->mail_smtpauth_req) {
|
|
$mail->SMTPAuth = TRUE;
|
|
$mail->Username = $oe->mail_smtpuser;
|
|
$mail->Password = $oe->mail_smtppass;
|
|
}
|
|
} else {
|
|
$mail->Mailer = "sendmail";
|
|
}
|
|
|
|
return $mail;
|
|
}
|
|
|
|
/**
|
|
* preps SugarPHPMailer object for HTML or Plain text sends
|
|
* @param object SugarPHPMailer instance
|
|
*/
|
|
function handleBody($mail) {
|
|
global $current_user;
|
|
global $sugar_config;
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// HANDLE EMAIL FORMAT PREFERENCE
|
|
// the if() below is HIGHLY dependent on the Javascript unchecking the Send HTML Email box
|
|
// HTML email
|
|
if( (isset($_REQUEST['setEditor']) /* from Email EditView navigation */
|
|
&& $_REQUEST['setEditor'] == 1
|
|
&& trim($_REQUEST['description_html']) != '')
|
|
|| trim($this->description_html) != '' /* from email templates */
|
|
&& $current_user->getPreference('email_editor_option', 'global') !== 'plain' //user preference is not set to plain text
|
|
) {
|
|
// wp: if body is html, then insert new lines at 996 characters. no effect on client side
|
|
// due to RFC 2822 which limits email lines to 998
|
|
$mail->IsHTML(true);
|
|
$body = from_html(wordwrap($this->description_html, 996));
|
|
$mail->Body = $body;
|
|
|
|
// cn: bug 9725
|
|
// new plan is to use the selected type (html or plain) to fill the other
|
|
$plainText = from_html($this->description_html);
|
|
$plainText = strip_tags(br2nl($plainText));
|
|
$mail->AltBody = $plainText;
|
|
$this->description = $plainText;
|
|
|
|
// cn: bug 9709 - html email sent accidentally
|
|
// handle signatures fubar'ing the type
|
|
$sigs = $current_user->getDefaultSignature();
|
|
if(!empty($sigs)) {
|
|
$htmlSig = trim(str_replace(" ", "", strip_tags(from_html($sigs['signature_html']))));
|
|
$htmlBody = trim(str_replace(" ", "", strip_tags(from_html($this->description_html))));
|
|
|
|
if($htmlSig == $htmlBody) {
|
|
// found just a sig. ignore it.
|
|
$this->description_html = '';
|
|
$mail->IsHTML(false);
|
|
$mail->Body = wordwrap(from_html($this->description, 996));
|
|
}
|
|
}
|
|
|
|
$fileBasePath = "{$sugar_config['cache_dir']}images/";
|
|
$filePatternSearch = "{$sugar_config['cache_dir']}";
|
|
$filePatternSearch = str_replace("/", "\/", $filePatternSearch);
|
|
$filePatternSearch = $filePatternSearch . "images\/";
|
|
if(strpos($mail->Body, "\"{$fileBasePath}")) {
|
|
$matches = array();
|
|
preg_match_all("/{$filePatternSearch}.+?\"/i", $mail->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['cache_dir']}images/{$filename}");
|
|
$mime_type = "image/".strtolower(substr($filename, strrpos($filename, ".")+1, strlen($filename)));
|
|
|
|
if(file_exists($file_location)) {
|
|
$mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $mime_type);
|
|
}
|
|
}
|
|
|
|
//replace references to cache with cid tag
|
|
$mail->Body = str_replace($fileBasePath,'cid:',$mail->Body);
|
|
|
|
// remove bad img line from outbound email
|
|
$regex = '#<img[^>]+src[^=]*=\"\/([^>]*?[^>]*)>#sim';
|
|
$mail->Body = preg_replace($regex, '', $mail->Body);
|
|
}
|
|
$fileBasePath = "{$sugar_config['upload_dir']}";
|
|
$filePatternSearch = "{$sugar_config['upload_dir']}";
|
|
$filePatternSearch = str_replace("/", "\/", $filePatternSearch);
|
|
if(strpos($mail->Body, "\"{$fileBasePath}")) {
|
|
$matches = array();
|
|
preg_match_all("/{$filePatternSearch}.+?\"/i", $mail->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)) {
|
|
$mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64', $mime_type);
|
|
}
|
|
}
|
|
|
|
//replace references to cache with cid tag
|
|
$mail->Body = str_replace($fileBasePath,'cid:',$mail->Body);
|
|
|
|
// remove bad img line from outbound email
|
|
$regex = '#<img[^>]+src[^=]*=\"\/([^>]*?[^>]*)>#sim';
|
|
$mail->Body = preg_replace($regex, '', $mail->Body);
|
|
}
|
|
$mail->Body = $this->decodeDuringSend($mail->Body);
|
|
$mail->Body = from_html($mail->Body);
|
|
} else {
|
|
// plain text only
|
|
$this->description_html = '';
|
|
$mail->IsHTML(false);
|
|
$plainText = from_html($this->description);
|
|
$plainText = str_replace(" ", " ", $plainText);
|
|
$plainText = str_replace("</p>", "</p><br />", $plainText);
|
|
$plainText = strip_tags(br2nl($plainText));
|
|
$plainText = str_replace("&", "&", $plainText);
|
|
$plainText = str_replace("'", "'", $plainText);
|
|
$mail->Body = wordwrap($plainText, 996);
|
|
$this->description = $mail->Body;
|
|
}
|
|
|
|
// wp: if plain text version has lines greater than 998, use base64 encoding
|
|
foreach(explode("\n", ($mail->ContentType == "text/html") ? $mail->AltBody : $mail->Body) as $line) {
|
|
if(strlen($line) > 998) {
|
|
$mail->Encoding = 'base64';
|
|
break;
|
|
}
|
|
}
|
|
//// HANDLE EMAIL FORMAT PREFERENCE
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
return $mail;
|
|
}
|
|
|
|
/**
|
|
* Sends Email
|
|
* @return bool True on success
|
|
*/
|
|
function send() {
|
|
global $mod_strings;
|
|
global $current_user;
|
|
global $sugar_config;
|
|
global $locale;
|
|
|
|
$mail = new SugarPHPMailer();
|
|
|
|
foreach ($this->to_addrs_arr as $addr_arr) {
|
|
if ( empty($addr_arr['display'])) {
|
|
$mail->AddAddress($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddAddress($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
}
|
|
foreach ($this->cc_addrs_arr as $addr_arr) {
|
|
if ( empty($addr_arr['display'])) {
|
|
$mail->AddCC($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddCC($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
}
|
|
|
|
foreach ($this->bcc_addrs_arr as $addr_arr) {
|
|
if ( empty($addr_arr['display'])) {
|
|
$mail->AddBCC($addr_arr['email'], "");
|
|
} else {
|
|
$mail->AddBCC($addr_arr['email'], $addr_arr['display']);
|
|
}
|
|
}
|
|
|
|
$mail = $this->setMailer($mail);
|
|
|
|
// FROM ADDRESS
|
|
if(!empty($this->from_addr)) {
|
|
$mail->From = $this->from_addr;
|
|
} else {
|
|
$mail->From = $current_user->getPreference('mail_fromaddress');
|
|
$this->from_addr = $mail->From;
|
|
}
|
|
// FROM NAME
|
|
if(!empty($this->from_name)) {
|
|
$mail->FromName = $this->from_name;
|
|
} else {
|
|
$mail->FromName = $current_user->getPreference('mail_fromname');
|
|
$this->from_name = $mail->FromName;
|
|
}
|
|
|
|
//Reply to information for case create and autoreply.
|
|
if(!empty($this->reply_to_name)) {
|
|
$ReplyToName = $this->reply_to_name;
|
|
} else {
|
|
$ReplyToName = $mail->FromName;
|
|
}
|
|
if(!empty($this->reply_to_addr)) {
|
|
$ReplyToAddr = $this->reply_to_addr;
|
|
} else {
|
|
$ReplyToAddr = $mail->From;
|
|
}
|
|
$mail->Sender = $mail->From; /* set Return-Path field in header to reduce spam score in emails sent via Sugar's Email module */
|
|
$mail->AddReplyTo($ReplyToAddr,$ReplyToName);
|
|
|
|
//$mail->Subject = html_entity_decode($this->name, ENT_QUOTES, 'UTF-8');
|
|
$mail->Subject = $this->name;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// ATTACHMENTS
|
|
foreach($this->saved_attachments as $note) {
|
|
$mime_type = 'text/plain';
|
|
if($note->object_name == 'Note') {
|
|
if(!empty($note->file->temp_file_location) && is_file($note->file->temp_file_location)) { // brandy-new file upload/attachment
|
|
$file_location = $sugar_config['upload_dir'].$note->id;
|
|
$filename = $note->file->original_file_name;
|
|
$mime_type = $note->file->mime_type;
|
|
} else { // attachment coming from template/forward
|
|
$file_location = rawurldecode(UploadFile::get_file_path($note->filename,$note->id));
|
|
// cn: bug 9723 - documents from EmailTemplates sent with Doc Name, not file name.
|
|
$filename = !empty($note->filename) ? $note->filename : $note->name;
|
|
$mime_type = $note->file_mime_type;
|
|
}
|
|
} elseif($note->object_name == 'DocumentRevision') { // from Documents
|
|
$filePathName = $note->id;
|
|
// cn: bug 9723 - Emails with documents send GUID instead of Doc name
|
|
$filename = $note->getDocumentRevisionNameForDisplay();
|
|
$file_location = getcwd().'/cache/upload/'.$filePathName;
|
|
$mime_type = $note->file_mime_type;
|
|
}
|
|
|
|
// strip out the "Email attachment label if exists
|
|
$filename = str_replace($mod_strings['LBL_EMAIL_ATTACHMENT'].': ', '', $filename);
|
|
|
|
//is attachment in our list of bad files extensions? If so, append .txt to file location
|
|
//get position of last "." in file name
|
|
$file_ext_beg = strrpos($file_location,".");
|
|
$file_ext = "";
|
|
//get file extension
|
|
if($file_ext_beg >0){
|
|
$file_ext = substr($file_location, $file_ext_beg+1 );
|
|
}
|
|
//check to see if this is a file with extension located in "badext"
|
|
foreach($sugar_config['upload_badext'] as $badExt) {
|
|
if(strtolower($file_ext) == strtolower($badExt)) {
|
|
//if found, then append with .txt to filename and break out of lookup
|
|
//this will make sure that the file goes out with right extension, but is stored
|
|
//as a text in db.
|
|
$file_location = $file_location . ".txt";
|
|
break; // no need to look for more
|
|
}
|
|
}
|
|
$mail->AddAttachment($file_location, $filename, 'base64', $mime_type);
|
|
|
|
// embedded Images
|
|
if($note->embed_flag == true) {
|
|
$cid = $filename;
|
|
$mail->AddEmbeddedImage($file_location, $cid, $filename, 'base64',$mime_type);
|
|
}
|
|
}
|
|
//// END ATTACHMENTS
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
$mail = $this->handleBody($mail);
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// SAVE RAW MESSAGE
|
|
// cn: bug 10250 - MySQL requires certain settings to get the SQL buffer > 1Mb
|
|
if(isset($sugar_config['email_outbound_save_raw']) && $sugar_config['email_outbound_save_raw'] == true) {
|
|
$mail->SetMessageType();
|
|
$raw = $mail->CreateHeader();
|
|
$raw .= $mail->CreateBody();
|
|
$this->raw_source = to_html($raw);
|
|
}
|
|
//// END SAVE RAW MESSAGE
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
$GLOBALS['log']->debug('Email sending --------------------- ');
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// I18N TRANSLATION
|
|
$mail->prepForOutbound();
|
|
//// END I18N TRANSLATION
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
if($mail->Send()) {
|
|
///////////////////////////////////////////////////////////////////
|
|
//// INBOUND EMAIL HANDLING
|
|
// mark replied
|
|
if(!empty($_REQUEST['inbound_email_id'])) {
|
|
$ieMail = new Email();
|
|
$ieMail->retrieve($_REQUEST['inbound_email_id']);
|
|
$ieMail->status = 'replied';
|
|
$ieMail->save();
|
|
}
|
|
$GLOBALS['log']->debug(' --------------------- buh bye -- sent successful');
|
|
//// END INBOUND EMAIL HANDLING
|
|
///////////////////////////////////////////////////////////////////
|
|
return true;
|
|
}
|
|
$GLOBALS['log']->debug("Error emailing:".$mail->ErrorInfo);
|
|
return false;
|
|
}
|
|
|
|
|
|
function listviewACLHelper(){
|
|
$array_assign = parent::listviewACLHelper();
|
|
$is_owner = false;
|
|
if(!empty($this->parent_name)){
|
|
|
|
if(!empty($this->parent_name_owner)){
|
|
global $current_user;
|
|
$is_owner = $current_user->id == $this->parent_name_owner;
|
|
}
|
|
}
|
|
if(!ACLController::moduleSupportsACL($this->parent_type) || ACLController::checkAccess($this->parent_type, 'view', $is_owner)){
|
|
$array_assign['PARENT'] = 'a';
|
|
} else {
|
|
$array_assign['PARENT'] = 'span';
|
|
}
|
|
$is_owner = false;
|
|
if(!empty($this->contact_name)) {
|
|
if(!empty($this->contact_name_owner)) {
|
|
global $current_user;
|
|
$is_owner = $current_user->id == $this->contact_name_owner;
|
|
}
|
|
}
|
|
if(ACLController::checkAccess('Contacts', 'view', $is_owner)) {
|
|
$array_assign['CONTACT'] = 'a';
|
|
} else {
|
|
$array_assign['CONTACT'] = 'span';
|
|
}
|
|
|
|
return $array_assign;
|
|
}
|
|
|
|
function getSystemDefaultEmail() {
|
|
$email = array();
|
|
|
|
$r1 = $this->db->query('SELECT config.value FROM config WHERE name=\'fromaddress\'');
|
|
$r2 = $this->db->query('SELECT config.value FROM config WHERE name=\'fromname\'');
|
|
$a1 = $this->db->fetchByAssoc($r1);
|
|
$a2 = $this->db->fetchByAssoc($r2);
|
|
|
|
$email['email'] = $a1['value'];
|
|
$email['name'] = $a2['value'];
|
|
|
|
return $email;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fill_in_additional_list_fields() {
|
|
global $timedate;
|
|
$this->fill_in_additional_detail_fields();
|
|
|
|
$this->link_action = 'DetailView';
|
|
///////////////////////////////////////////////////////////////////////
|
|
//populate attachment_image, used to display attachment icon.
|
|
$query = "select 1 from notes where notes.parent_id = '$this->id' and notes.deleted = 0";
|
|
$result =$this->db->query($query,true," Error filling in additional list fields: ");
|
|
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
global $theme;
|
|
|
|
if ($row !=null) {
|
|
$this->attachment_image = get_image('themes/'.$theme.'/images/attachment',"","","");
|
|
} else {
|
|
$this->attachment_image = get_image('include/images/blank',"","","");
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
function fill_in_additional_detail_fields() {
|
|
global $app_list_strings,$mod_strings;
|
|
// Fill in the assigned_user_name
|
|
$this->assigned_user_name = get_assigned_user_name($this->assigned_user_id, '');
|
|
|
|
|
|
|
|
|
|
$query = "SELECT contacts.first_name, contacts.last_name, contacts.phone_work, contacts.id, contacts.assigned_user_id contact_name_owner, 'Contacts' contact_name_mod FROM contacts, emails_beans ";
|
|
$query .= "WHERE emails_beans.email_id='$this->id' AND emails_beans.bean_id=contacts.id AND emails_beans.deleted=0 AND contacts.deleted=0";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
$GLOBALS['log']->info($row);
|
|
|
|
if($row != null)
|
|
{
|
|
require_once("modules/Contacts/Contact.php");
|
|
$contact = new Contact();
|
|
$contact->retrieve($row['id']);
|
|
$this->contact_name = $contact->full_name;
|
|
$this->contact_phone = $row['phone_work'];
|
|
$this->contact_id = $row['id'];
|
|
$this->contact_email = $contact->emailAddress->getPrimaryAddress($contact);
|
|
$this->contact_name_owner = $row['contact_name_owner'];
|
|
$this->contact_name_mod = $row['contact_name_mod'];
|
|
$GLOBALS['log']->debug("Call($this->id): contact_name = $this->contact_name");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_phone = $this->contact_phone");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_id = $this->contact_id");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_email1 = $this->contact_email");
|
|
}
|
|
else {
|
|
$this->contact_name = '';
|
|
$this->contact_phone = '';
|
|
$this->contact_id = '';
|
|
$this->contact_email = '';
|
|
$this->contact_name_owner = '';
|
|
$this->contact_name_mod = '';
|
|
$GLOBALS['log']->debug("Call($this->id): contact_name = $this->contact_name");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_phone = $this->contact_phone");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_id = $this->contact_id");
|
|
$GLOBALS['log']->debug("Call($this->id): contact_email1 = $this->contact_email");
|
|
}
|
|
|
|
$this->created_by_name = get_assigned_user_name($this->created_by);
|
|
$this->modified_by_name = get_assigned_user_name($this->modified_user_id);
|
|
|
|
$this->link_action = 'DetailView';
|
|
|
|
if(!empty($this->type)) {
|
|
if($this->type == 'out' && $this->status == 'send_error') {
|
|
$this->type_name = $mod_strings['LBL_NOT_SENT'];
|
|
} else {
|
|
$this->type_name = $app_list_strings['dom_email_types'][$this->type];
|
|
}
|
|
|
|
if(($this->type == 'out' && $this->status == 'send_error') || $this->type == 'draft') {
|
|
$this->link_action = 'EditView';
|
|
}
|
|
}
|
|
|
|
//todo this isset( $app_list_strings['dom_email_status'][$this->status]) is hack for 3261.
|
|
if(!empty($this->status) && isset( $app_list_strings['dom_email_status'][$this->status])) {
|
|
$this->status_name = $app_list_strings['dom_email_status'][$this->status];
|
|
}
|
|
|
|
if ( empty($this->name ) && empty($_REQUEST['record'])) {
|
|
$this->name = '(no subject)';
|
|
}
|
|
|
|
$this->fill_in_additional_parent_fields();
|
|
}
|
|
|
|
function fill_in_additional_parent_fields() {
|
|
global $app_strings, $beanFiles, $beanList;
|
|
$this->parent_name_owner = '';
|
|
$this->parent_name_mod = $this->parent_type;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//// SPLIT INTO TWO TYPES:
|
|
//// 1. NAME IS CONCATENATION OF FIRST+LAST
|
|
//// 2. JUST NAME
|
|
|
|
if($this->parent_type == "Opportunities") {
|
|
require_once("modules/Opportunities/Opportunity.php");
|
|
$parent = new Opportunity();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Tasks") {
|
|
require_once("modules/Tasks/Task.php");
|
|
$parent = new Task();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Cases") {
|
|
require_once("modules/Cases/Case.php");
|
|
$parent = new aCase();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Bugs") {
|
|
require_once("modules/Bugs/Bug.php");
|
|
$parent = new Bug();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Project") {
|
|
require_once("modules/Project/Project.php");
|
|
$parent = new Project();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "ProjectTask") {
|
|
require_once("modules/ProjectTask/ProjectTask.php");
|
|
$parent = new ProjectTask();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Accounts") {
|
|
require_once("modules/Accounts/Account.php");
|
|
$parent = new Account();
|
|
$query = "SELECT name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
$result =$this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Leads") {
|
|
require_once("modules/Leads/Lead.php");
|
|
$parent = new Lead();
|
|
$query = "SELECT first_name, last_name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
|
|
$result =$this->db->query($query,true, "ERROR CREATING ADDITIONAL FIELDS");
|
|
|
|
|
|
// Get the id and the name.
|
|
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = '';
|
|
if ($row['first_name'] != '') $this->parent_name .= stripslashes($row['first_name']). ' ';
|
|
if ($row['last_name'] != '') $this->parent_name .= stripslashes($row['last_name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
elseif ($this->parent_type == "Contacts") {
|
|
require_once("modules/Contacts/Contact.php");
|
|
$parent = new Contact();
|
|
$query = "SELECT first_name, last_name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
|
|
$result =$this->db->query($query,true, "ERROR CREATING ADDITIONAL FIELDS");
|
|
|
|
|
|
// Get the id and the name.
|
|
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = '';
|
|
if ($row['first_name'] != '') $this->parent_name .= stripslashes($row['first_name']). ' ';
|
|
if ($row['last_name'] != '') $this->parent_name .= stripslashes($row['last_name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elseif ($this->parent_type == "Prospects") {
|
|
require_once("modules/Prospects/Prospect.php");
|
|
$parent = new Prospect();
|
|
$query = "SELECT first_name, last_name, assigned_user_id from $parent->table_name where id = '$this->parent_id'";
|
|
|
|
$result =$this->db->query($query,true, "ERROR CREATING ADDITIONAL FIELDS");
|
|
|
|
|
|
// Get the id and the name.
|
|
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
|
|
if($row != null)
|
|
{
|
|
$this->parent_name = '';
|
|
if ($row['first_name'] != '') $this->parent_name .= stripslashes($row['first_name']). ' ';
|
|
if ($row['last_name'] != '') $this->parent_name .= stripslashes($row['last_name']);
|
|
$this->parent_name_owner = stripslashes($row['assigned_user_id']);
|
|
}
|
|
}
|
|
//Custom history relationships
|
|
elseif (!empty($beanList[$this->parent_type])) {
|
|
$beanType = $beanList[$this->parent_type];
|
|
require_once($beanFiles[$beanType]);
|
|
$parent = new $beanType();
|
|
|
|
if (is_subclass_of($parent, 'Person')) {
|
|
$query = "SELECT first_name, last_name, assigned_user_id parent_name_owner from $parent->table_name where id = '$this->parent_id'";
|
|
}
|
|
else {
|
|
$query = "SELECT name ";
|
|
if(isset($parent->field_defs['assigned_user_id'])){
|
|
$query .= " , assigned_user_id parent_name_owner ";
|
|
}else{
|
|
$query .= " , created_by parent_name_owner ";
|
|
}
|
|
$query .= " from $parent->table_name where id = '$this->parent_id'";
|
|
}
|
|
|
|
$result = $this->db->query($query,true," Error filling in additional detail fields: ");
|
|
|
|
// Get the id and the name.
|
|
$row = $this->db->fetchByAssoc($result);
|
|
|
|
if ($row && !empty($row['parent_name_owner'])){
|
|
$this->parent_name_owner = $row['parent_name_owner'];
|
|
$this->parent_name_mod = $this->parent_type;
|
|
}
|
|
if (is_subclass_of($parent, 'Person') and $row != null)
|
|
{
|
|
$this->parent_name = '';
|
|
if ($row['first_name'] != '') $this->parent_name .= stripslashes($row['first_name']). ' ';
|
|
if ($row['last_name'] != '') $this->parent_name .= stripslashes($row['last_name']);
|
|
}
|
|
elseif($row != null)
|
|
{
|
|
$this->parent_name = stripslashes($row['name']);
|
|
}
|
|
else {
|
|
$this->parent_name = '';
|
|
}
|
|
}
|
|
else {
|
|
$this->parent_name = '';
|
|
}
|
|
}
|
|
|
|
function create_export_query(&$order_by, &$where) {
|
|
$contact_required = ereg("contacts", $where);
|
|
$custom_join = $this->custom_fields->getJOIN(true, true);
|
|
|
|
if($contact_required) {
|
|
$query = "SELECT emails.*, contacts.first_name, contacts.last_name";
|
|
|
|
|
|
|
|
if($custom_join) {
|
|
$query .= $custom_join['select'];
|
|
}
|
|
|
|
$query .= " FROM contacts, emails, emails_contacts ";
|
|
$where_auto = "emails_contacts.contact_id = contacts.id AND emails_contacts.email_id = emails.id AND emails.deleted=0 AND contacts.deleted=0";
|
|
} else {
|
|
$query = 'SELECT emails.*';
|
|
|
|
|
|
|
|
if($custom_join) {
|
|
$query .= $custom_join['select'];
|
|
}
|
|
|
|
$query .= ' FROM emails ';
|
|
$where_auto = "emails.deleted=0";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if($custom_join){
|
|
$query .= $custom_join['join'];
|
|
}
|
|
|
|
if($where != "")
|
|
$query .= "where $where AND ".$where_auto;
|
|
else
|
|
$query .= "where ".$where_auto;
|
|
|
|
if($order_by != "")
|
|
$query .= " ORDER BY $order_by";
|
|
else
|
|
$query .= " ORDER BY emails.name";
|
|
return $query;
|
|
}
|
|
|
|
|
|
function create_list_query($order_by, $where, $show_deleted = 0) {
|
|
$custom_join = $this->custom_fields->getJOIN();
|
|
|
|
$query = "SELECT ".$this->table_name.".*, users.user_name as assigned_user_name\n";
|
|
|
|
if($custom_join){
|
|
$query .= $custom_join['select'];
|
|
}
|
|
$query .= " FROM emails\n";
|
|
if ($where != "" && (strpos($where, "contacts.first_name") > 0)) {
|
|
$query .= " LEFT JOIN emails_beans ON emails.id = emails_beans.email_id\n";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$query .= " LEFT JOIN users ON emails.assigned_user_id=users.id \n";
|
|
if ($where != "" && (strpos($where, "contacts.first_name") > 0)) {
|
|
|
|
$query .= " JOIN contacts ON contacts.id= emails_beans.bean_id AND emails_beans.bean_module='Contacts' and contacts.deleted=0 \n";
|
|
}
|
|
|
|
if($custom_join){
|
|
$query .= $custom_join['join'];
|
|
}
|
|
|
|
if($show_deleted == 0) {
|
|
$where_auto = " emails.deleted=0 \n";
|
|
}else if($show_deleted == 1){
|
|
$where_auto = " emails.deleted=1 \n";
|
|
}
|
|
|
|
if($where != "")
|
|
$query .= "WHERE $where AND ".$where_auto;
|
|
else
|
|
$query .= "WHERE ".$where_auto;
|
|
|
|
if($order_by != "")
|
|
$query .= " ORDER BY $order_by";
|
|
else
|
|
$query .= " ORDER BY date_sent DESC";
|
|
|
|
return $query;
|
|
}
|
|
|
|
function create_new_list_queryy($order_by, $where, $show_deleted = 0) {
|
|
$custom_join = $this->custom_fields->getJOIN();
|
|
|
|
$query['select'] = "SELECT ".$this->table_name.".*, users.user_name as assigned_user_name\n";
|
|
|
|
if($custom_join){
|
|
$query['select'] .= $custom_join['select'];
|
|
}
|
|
$query['from'] .= " FROM emails\n";
|
|
if ($where != "" && (strpos($where, "contacts.first_name") > 0)) {
|
|
$query['from'] .= " LEFT JOIN emails_beans ON emails.id = emails_beans.email_id\n";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$query['from'] .= " LEFT JOIN users ON emails.assigned_user_id=users.id \n";
|
|
if ($where != "" && (strpos($where, "contacts.first_name") > 0)) {
|
|
|
|
$query['from'] .= " JOIN contacts ON contacts.id= emails_beans.bean_id AND emails_beans.bean_module='Contacts' and contacts.deleted=0 \n";
|
|
}
|
|
|
|
if($custom_join){
|
|
$query['from'] .= $custom_join['join'];
|
|
}
|
|
|
|
if($show_deleted == 0) {
|
|
$where_auto = " emails.deleted=0 \n";
|
|
}else if($show_deleted == 1){
|
|
$where_auto = " emails.deleted=1 \n";
|
|
}
|
|
|
|
if($where != "")
|
|
$query['where'] .= "WHERE $where AND ".$where_auto;
|
|
else
|
|
$query['where'] .= "WHERE ".$where_auto;
|
|
|
|
if($order_by != "")
|
|
$query['order_by'] .= " ORDER BY $order_by";
|
|
else
|
|
$query['order_by'] .= " ORDER BY date_sent DESC";
|
|
echo $query['select'].' '.$query['from'].' '.$query['where'].' '.$query['order_by'].'<br>';
|
|
return $query;
|
|
}
|
|
|
|
function get_list_view_data() {
|
|
global $app_list_strings;
|
|
global $theme;
|
|
global $current_user;
|
|
global $timedate;
|
|
global $mod_strings;
|
|
|
|
$email_fields = $this->get_list_view_array();
|
|
$mod_strings = return_module_language($GLOBALS['current_language'], 'Emails'); // hard-coding for Home screen ListView
|
|
|
|
if($this->status != 'replied') {
|
|
$email_fields['QUICK_REPLY'] = '<a class="listViewTdLinkS1" href="index.php?module=Emails&action=Compose&inbound_email_id='.$this->id.'">'.$mod_strings['LNK_QUICK_REPLY'].'</a>';
|
|
$email_fields['STATUS'] = ($email_fields['REPLY_TO_STATUS'] == 1 ? $mod_strings['LBL_REPLIED'] : $email_fields['STATUS']);
|
|
} else {
|
|
$email_fields['QUICK_REPLY'] = $mod_strings['LBL_REPLIED'];
|
|
}
|
|
if(!empty($this->parent_type)) {
|
|
$email_fields['PARENT_MODULE'] = $this->parent_type;
|
|
} else {
|
|
switch($this->intent) {
|
|
case 'support':
|
|
$email_fields['CREATE_RELATED'] = '<a href="index.php?module=Cases&action=EditView&inbound_email_id='.$this->id.'" class="listViewTdLinkS1"><img border="0" src="themes/'.$theme.'/images/CreateCases.gif">'.$mod_strings['LBL_CREATE_CASE'].'</a>';
|
|
break;
|
|
|
|
case 'sales':
|
|
$email_fields['CREATE_RELATED'] = '<a href="index.php?module=Leads&action=EditView&inbound_email_id='.$this->id.'" class="listViewTdLinkS1"><img border="0" src="themes/'.$theme.'/images/CreateLeads.gif">'.$mod_strings['LBL_CREATE_LEAD'].'</a>';
|
|
break;
|
|
|
|
case 'contact':
|
|
$email_fields['CREATE_RELATED'] = '<a href="index.php?module=Contacts&action=EditView&inbound_email_id='.$this->id.'" class="listViewTdLinkS1"><img border="0" src="themes/'.$theme.'/images/CreateContacts.gif">'.$mod_strings['LBL_CREATE_CONTACT'].'</a>';
|
|
break;
|
|
|
|
case 'bug':
|
|
$email_fields['CREATE_RELATED'] = '<a href="index.php?module=Bugs&action=EditView&inbound_email_id='.$this->id.'" class="listViewTdLinkS1"><img border="0" src="themes/'.$theme.'/images/CreateBugs.gif">'.$mod_strings['LBL_CREATE_BUG'].'</a>';
|
|
break;
|
|
|
|
case 'task':
|
|
$email_fields['CREATE_RELATED'] = '<a href="index.php?module=Tasks&action=EditView&inbound_email_id='.$this->id.'" class="listViewTdLinkS1"><img border="0" src="themes/'.$theme.'/images/CreateTasks.gif">'.$mod_strings['LBL_CREATE_TASK'].'</a>';
|
|
break;
|
|
|
|
case 'bounce':
|
|
break;
|
|
|
|
case 'pick':
|
|
// break;
|
|
|
|
case 'info':
|
|
//break;
|
|
|
|
default:
|
|
$email_fields['CREATE_RELATED'] = $this->quickCreateForm();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//BUG 17098 - MFH changed $this->from_addr to $this->to_addrs
|
|
$email_fields['CONTACT_NAME'] = empty($this->contact_name) ? '</a>'.$this->trimLongTo($this->to_addrs).'<a>' : $this->contact_name;
|
|
$email_fields['CONTACT_ID'] = empty($this->contact_id) ? '' : $this->contact_id;
|
|
$email_fields['ATTACHMENT_IMAGE'] = $this->attachment_image;
|
|
$email_fields['LINK_ACTION'] = $this->link_action;
|
|
|
|
if(isset($this->type_name))
|
|
$email_fields['TYPE_NAME'] = $this->type_name;
|
|
|
|
return $email_fields;
|
|
}
|
|
|
|
function quickCreateForm() {
|
|
global $mod_strings, $app_strings, $image_path, $currentModule, $current_language, $theme;
|
|
|
|
// Coming from the home page via Dashlets
|
|
if($currentModule != 'Email')
|
|
$mod_strings = return_module_language($current_language, 'Emails');
|
|
return "<a id='$this->id' onclick='return quick_create_overlib(\"{$this->id}\", \"{$theme}\");' href=\"#\" class=\"listViewPaginationLinkS1\">".get_image($image_path."advanced_search","alt='".$mod_strings['LBL_QUICK_CREATE']."' border='0' align='absmiddle'")." ".$mod_strings['LBL_QUICK_CREATE']."</a>";
|
|
}
|
|
|
|
|
|
/**
|
|
* takes a long TO: string of emails and returns the first appended by an
|
|
* elipse
|
|
*/
|
|
function trimLongTo($str) {
|
|
if(strpos($str, ',')) {
|
|
$exStr = explode(',', $str);
|
|
return $exStr[0].'...';
|
|
} elseif(strpos($str, ';')) {
|
|
$exStr = explode(';', $str);
|
|
return $exStr[0].'...';
|
|
} else {
|
|
return $str;
|
|
}
|
|
}
|
|
|
|
function get_summary_text() {
|
|
return $this->name;
|
|
}
|
|
|
|
|
|
|
|
function distributionForm($where) {
|
|
global $app_list_strings;
|
|
global $app_strings;
|
|
global $mod_strings;
|
|
global $theme;
|
|
global $current_user;
|
|
|
|
$distribution = get_select_options_with_id($app_list_strings['dom_email_distribution'], '');
|
|
$_SESSION['distribute_where'] = $where;
|
|
|
|
$out = '
|
|
<form name="Distribute" id="Distribute">';
|
|
$out .= get_form_header($mod_strings['LBL_DIST_TITLE'], '', false);
|
|
$out .= '
|
|
<table cellpadding="0" cellspacing="0" width="100%" border="0">
|
|
<tr>
|
|
<td>
|
|
<script type="text/javascript">
|
|
|
|
|
|
function checkDeps(form) {
|
|
return;
|
|
}
|
|
|
|
function mySubmit() {
|
|
var assform = document.getElementById("Distribute");
|
|
var select = document.getElementById("userSelect");
|
|
var assign1 = assform.r1.checked;
|
|
var assign2 = assform.r2.checked;
|
|
var dist = assform.dm.value;
|
|
var assign = false;
|
|
var users = false;
|
|
var rules = false;
|
|
var warn1 = "'.$mod_strings['LBL_WARN_NO_USERS'].'";
|
|
var warn2 = "";
|
|
|
|
if(assign1 || assign2) {
|
|
assign = true;
|
|
|
|
}
|
|
|
|
for(i=0; i<select.options.length; i++) {
|
|
if(select.options[i].selected == true) {
|
|
users = true;
|
|
warn1 = "";
|
|
}
|
|
}
|
|
|
|
if(dist != "") {
|
|
rules = true;
|
|
} else {
|
|
warn2 = "'.$mod_strings['LBL_WARN_NO_DIST'].'";
|
|
}
|
|
|
|
if(assign && users && rules) {
|
|
|
|
if(document.getElementById("r1").checked) {
|
|
var mu = document.getElementById("MassUpdate");
|
|
var grabbed = "";
|
|
|
|
for(i=0; i<mu.elements.length; i++) {
|
|
if(mu.elements[i].type == "checkbox" && mu.elements[i].checked && mu.elements[i].name.value != "massall") {
|
|
if(grabbed != "") { grabbed += "::"; }
|
|
grabbed += mu.elements[i].value;
|
|
}
|
|
}
|
|
var formgrab = document.getElementById("grabbed");
|
|
formgrab.value = grabbed;
|
|
}
|
|
assform.submit();
|
|
} else {
|
|
alert("'.$mod_strings['LBL_ASSIGN_WARN'].'" + "\n" + warn1 + "\n" + warn2);
|
|
}
|
|
}
|
|
|
|
function submitDelete() {
|
|
if(document.getElementById("r1").checked) {
|
|
var mu = document.getElementById("MassUpdate");
|
|
var grabbed = "";
|
|
|
|
for(i=0; i<mu.elements.length; i++) {
|
|
if(mu.elements[i].type == "checkbox" && mu.elements[i].checked && mu.elements[i].name != "massall") {
|
|
if(grabbed != "") { grabbed += "::"; }
|
|
grabbed += mu.elements[i].value;
|
|
}
|
|
}
|
|
var formgrab = document.getElementById("grabbed");
|
|
formgrab.value = grabbed;
|
|
}
|
|
if(grabbed == "") {
|
|
alert("'.$mod_strings['LBL_MASS_DELETE_ERROR'].'");
|
|
} else {
|
|
document.getElementById("Distribute").submit();
|
|
}
|
|
}
|
|
|
|
</script>
|
|
<input type="hidden" name="module" value="Emails">
|
|
<input type="hidden" name="action" id="action">
|
|
<input type="hidden" name="grabbed" id="grabbed">
|
|
|
|
<table cellpadding="1" cellspacing="0" width="100%" border="0" class="tabForm">
|
|
<tr height="20">
|
|
<td scope="col" width="40%" class="dataLabel" NOWRAP align="center">
|
|
'.$mod_strings['LBL_ASSIGN_SELECTED_RESULTS_TO'].' ';
|
|
$out .= $this->userSelectTable();
|
|
$out .= '</td>
|
|
<td scope="col" width="15%" class="dataLabel" NOWRAP align="left">
|
|
'.$mod_strings['LBL_USING_RULES'].'
|
|
<select name="distribute_method" id="dm" onChange="checkDeps(this.form);">'.$distribution.'</select>
|
|
</td>
|
|
|
|
<td scope="col" width="50%" class="dataLabel" NOWRAP align="right">
|
|
<input title="'.$mod_strings['LBL_BUTTON_DISTRIBUTE_TITLE'].'"
|
|
id="dist_button"
|
|
accessKey="'.$mod_strings['LBL_BUTTON_DISTRIBUTE_KEY'].'"
|
|
class="button" onClick="AjaxObject.detailView.handleAssignmentDialogAssignAction();"
|
|
type="button" name="button"
|
|
value=" '.$mod_strings['LBL_BUTTON_DISTRIBUTE'].' ">';
|
|
|
|
$out .= '
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</form>';
|
|
return $out;
|
|
}
|
|
|
|
function userSelectTable() {
|
|
global $theme;
|
|
global $mod_strings;
|
|
|
|
$colspan = 1;
|
|
$setTeamUserFunction = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get users
|
|
$r = $this->db->query("SELECT users.id, users.user_name, users.first_name, users.last_name FROM users WHERE deleted=0 AND status = 'Active' AND is_group=0 ORDER BY users.last_name, users.first_name");
|
|
|
|
$userTable = '<table cellpadding="0" cellspacing="0" border="0">';
|
|
$userTable .= '<tr><td colspan="2"><b>'.$mod_strings['LBL_USER_SELECT'].'</b></td></tr>';
|
|
$userTable .= '<tr><td><input type="checkbox" style="border:0px solid #000000" onClick="toggleAll(this); setCheckMark(); checkDeps(this.form);"></td> <td>'.$mod_strings['LBL_TOGGLE_ALL'].'</td></tr>';
|
|
$userTable .= '<tr><td colspan="2"><select style="visibility:hidden;" name="users[]" id="userSelect" multiple size="12">';
|
|
|
|
while($a = $this->db->fetchByAssoc($r)) {
|
|
$userTable .= '<option value="'.$a['id'].'" id="'.$a['id'].'">'.$a['first_name'].' '.$a['last_name'].'</option>';
|
|
}
|
|
$userTable .= '</select></td></tr>';
|
|
$userTable .= '</table>';
|
|
|
|
$out = '<script type="text/javascript">';
|
|
$out .= $setTeamUserFunction;
|
|
$out .= '
|
|
function setCheckMark() {
|
|
var select = document.getElementById("userSelect");
|
|
|
|
for(i=0 ; i<select.options.length; i++) {
|
|
if(select.options[i].selected == true) {
|
|
document.getElementById("checkMark").style.display="";
|
|
return;
|
|
}
|
|
}
|
|
|
|
document.getElementById("checkMark").style.display="none";
|
|
return;
|
|
}
|
|
|
|
function showUserSelect() {
|
|
var targetTable = document.getElementById("user_select");
|
|
targetTable.style.visibility="visible";
|
|
var userSelectTable = document.getElementById("userSelect");
|
|
userSelectTable.style.visibility="visible";
|
|
return;
|
|
}
|
|
function hideUserSelect() {
|
|
var targetTable = document.getElementById("user_select");
|
|
targetTable.style.visibility="hidden";
|
|
var userSelectTable = document.getElementById("userSelect");
|
|
userSelectTable.style.visibility="hidden";
|
|
return;
|
|
}
|
|
function toggleAll(toggle) {
|
|
if(toggle.checked) {
|
|
var stat = true;
|
|
} else {
|
|
var stat = false;
|
|
}
|
|
var form = document.getElementById("userSelect");
|
|
for(i=0; i<form.options.length; i++) {
|
|
form.options[i].selected = stat;
|
|
}
|
|
}
|
|
|
|
|
|
</script>
|
|
<span id="showUsersDiv" style="position:relative;">
|
|
<a href="#" id="showUsers" onClick="javascript:showUserSelect();">
|
|
<img border="0" src="themes/default/images/Users.gif"></a>
|
|
<a href="#" id="showUsers" onClick="javascript:showUserSelect();">
|
|
<span style="display:none;" id="checkMark"><img border="0" src="themes/'.$theme.'/images/check_inline.gif"></span>
|
|
</a>
|
|
|
|
|
|
<div id="user_select" style="width:200px;position:absolute;left:2;top:2;visibility:hidden;z-index:1000;">
|
|
<table cellpadding="0" cellspacing="0" border="0" class="listView">
|
|
<tr height="20">
|
|
<td class="listViewThS1" colspan="'.$colspan.'" id="hiddenhead" onClick="hideUserSelect();" onMouseOver="this.style.border = \'outset red 1px\';" onMouseOut="this.style.border = \'inset white 0px\';this.style.borderBottom = \'inset red 1px\';">
|
|
<a href="#" onClick="javascript:hideUserSelect();"><img border="0" src="themes/'.$theme.'/images/close.gif"></a>
|
|
'.$mod_strings['LBL_USER_SELECT'].'
|
|
</td>
|
|
</tr>
|
|
<tr>';
|
|
//<td valign="middle" height="30" class="listViewThS1" colspan="'.$colspan.'" id="hiddenhead" onClick="hideUserSelect();" onMouseOver="this.style.border = \'outset red 1px\';" onMouseOut="this.style.border = \'inset white 0px\';this.style.borderBottom = \'inset red 1px\';">
|
|
|
|
|
|
|
|
|
|
|
|
$out .= ' <td style="padding:5px" class="oddListRowS1" bgcolor="#fdfdfd" valign="top" align="left" style="left:0;top:0;">
|
|
'.$userTable.'
|
|
</td>
|
|
</tr>
|
|
</table></div>
|
|
</span>';
|
|
return $out;
|
|
}
|
|
|
|
function checkInbox($type) {
|
|
global $theme;
|
|
global $mod_strings;
|
|
$out = '<div class="listViewButtons"><input title="'.$mod_strings['LBL_BUTTON_CHECK_TITLE'].'"
|
|
accessKey="'.$mod_strings['LBL_BUTTON_CHECK_KEY'].'"
|
|
class="button"
|
|
type="button" name="button"
|
|
onClick="window.location=\'index.php?module=Emails&action=Check&type='.$type.'\';"
|
|
style="margin-bottom:2px"
|
|
value=" '.$mod_strings['LBL_BUTTON_CHECK'].' "></div>';
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Guesses Primary Parent id from From: email address. Cascades guesses from Accounts to Contacts to Leads to
|
|
* Users. This will not affect the many-to-many relationships already constructed as this is, at best,
|
|
* informational linking.
|
|
*/
|
|
function fillPrimaryParentFields() {
|
|
if(empty($this->from_addr))
|
|
return;
|
|
|
|
$GLOBALS['log']->debug("*** Email trying to guess Primary Parent from address [ {$this->from_addr} ]");
|
|
|
|
$tables = array('accounts');
|
|
$ret = array();
|
|
// loop through types to get hits
|
|
foreach($tables as $table) {
|
|
$q = "SELECT name, id FROM {$table} WHERE email1 = '{$this->from_addr}' OR email2 = '{$this->from_addr}' AND deleted = 0";
|
|
$r = $this->db->query($q);
|
|
while($a = $this->db->fetchByAssoc($r)) {
|
|
if(!empty($a['name']) && !empty($a['id'])) {
|
|
$this->parent_type = ucwords($table);
|
|
$this->parent_id = $a['id'];
|
|
$this->parent_name = $a['name'];
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // end class def
|