";
/**
* @var string $emailRawSource
*/
public $emailRawSource;
/**
* @var string $link_action eg DetailView
*/
public $link_action;
/**
* @var SugarEmailAddress $emailAddress
*/
public $emailAddress;
/**
* @var array $attachments
*/
public $attachments = array();
/**
* @var bool $isDuplicate
*/
public $isDuplicate;
/**
* IMAP UID
*
* @var uid
*/
public $uid;
/**
* @var string $to
*/
public $to;
/**
* @var integer $flagged 0 === false, 1 === true
*/
public $flagged;
/**
* @var integer $answered 0 === false, 1 === true
*/
public $answered;
/**
* @var integer $seen 0 === false, 1 === true
*/
public $seen;
/**
* @var integer $draft 0 === false, 1 === true
*/
public $draft;
/**
* @var array $relationshipMap
*/
public $relationshipMap = array(
'Contacts' => 'emails_contacts_rel',
'Accounts' => 'emails_accounts_rel',
'Leads' => 'emails_leads_rel',
'Users' => 'emails_users_rel',
'Prospects' => 'emails_prospects_rel',
);
/**
* @var EmailUI $et
*/
public $et; // EmailUI object
/**
* @var string $imagePrefix prefix to use when importing inlinge images in emails
*/
public $imagePrefix;
/**
* Used for keeping track of field defs that have been modified
*
* @var array
*/
public $modifiedFieldDefs = array();
/**
* @var string $attachment_image
*/
public $attachment_image;
/**
* @var Link2
*/
public $cases;
/**
* @var string $category_id
*/
public $category_id;
/**
* orphaned on IMAP
*
* @var bool
*/
public $orphaned;
/**
* @var Link2 $notes
*/
public $notes;
/**
* sole constructor
*/
public function __construct()
{
global $current_user;
$this->cachePath = sugar_cached('modules/Emails');
parent::__construct();
$this->emailAddress = new SugarEmailAddress();
$this->imagePrefix = rtrim($GLOBALS['sugar_config']['site_url'], "/") . "/cache/images/";
}
/**
* @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
*/
public function Email()
{
$deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
if (isset($GLOBALS['log'])) {
$GLOBALS['log']->deprecated($deprecatedMessage);
} else {
trigger_error($deprecatedMessage, E_USER_DEPRECATED);
}
self::__construct();
}
/**
* assigns $this->ev with EmailUI
*/
public function email2init()
{
require_once('modules/Emails/EmailUI.php');
$this->et = new EmailUI();
}
/**
* @param $interface
* @return bool
*/
public 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 array ID of note associated with the attachment
*/
public function email2saveAttachment()
{
$email_uploads = "modules/Emails/{$GLOBALS['current_user']->id}";
$upload = new UploadFile('email_attachment');
if (!$upload->confirm_upload()) {
$err = $upload->get_upload_error();
if ($err) {
$GLOBALS['log']->error("Email Attachment could not be attached due to error: $err");
}
return array();
}
$guid = create_guid();
$fileName = $upload->create_stored_filename();
$GLOBALS['log']->debug("Email Attachment [$fileName]");
if ($upload->final_move($guid)) {
copy("upload://$guid", sugar_cached("$email_uploads/$guid"));
return array(
'guid' => $guid,
'name' => $GLOBALS['db']->quote($fileName),
'nameForDisplay' => $fileName
);
} else {
$GLOBALS['log']->debug("Email Attachment [$fileName] could not be moved to upload dir");
return array();
}
}
/**
* @param string $filename
* @return bool
*/
public 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 !== false) {
$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
*/
public function email2ParseAddresses($addresses)
{
$addresses = from_html($addresses);
$addresses = $this->et->unifyEmailString($addresses);
$pattern = '/@.*,/U';
preg_match_all($pattern, $addresses, $matchs);
if (!empty($matchs[0])) {
$total = $matchs[0];
foreach ($total as $match) {
$convertedPattern = str_replace(',', '::;::', $match);
$addresses = str_replace($match, $convertedPattern, $addresses);
} //foreach
}
$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'] = 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);
$pattern = '/@.*,/U';
preg_match_all($pattern, $addresses, $matchs);
if (!empty($matchs[0])) {
$total = $matchs[0];
foreach ($total as $match) {
$convertedPattern = str_replace(',', '::;::', $match);
$addresses = str_replace($match, $convertedPattern, $addresses);
} //foreach
}
$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
*/
public function email2GetMime($fileLocation)
{
if (!is_readable($fileLocation)) {
return 'application/octet-stream';
}
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;
}
/**
* @param $mailserver_url
* @param $port
* @param $ssltls
* @param $smtp_auth_req
* @param $smtp_username
* @param $smtppassword
* @param $fromaddress
* @param $toaddress
* @param string $mail_sendtype
* @param string $fromname
* @return array
*/
public function sendEmailTest(
$mailserver_url,
$port,
$ssltls,
$smtp_auth_req,
$smtp_username,
$smtppassword,
$fromaddress,
$toaddress,
$mail_sendtype = 'smtp',
$fromname = ''
) {
global $current_user, $app_strings;
$mod_strings = return_module_language($GLOBALS['current_language'], 'Emails'); //Called from EmailMan as well.
$mail = new SugarPHPMailer();
$mail->Mailer = strtolower($mail_sendtype);
if ($mail->Mailer == 'smtp') {
$mail->Host = $mailserver_url;
$mail->Port = $port;
if (isset($ssltls) && !empty($ssltls)) {
$mail->protocol = "ssl://";
if ($ssltls == 1) {
$mail->SMTPSecure = 'ssl';
} // if
if ($ssltls == 2) {
$mail->SMTPSecure = 'tls';
} // if
} else {
$mail->protocol = "tcp://";
}
if ($smtp_auth_req) {
$mail->SMTPAuth = true;
$mail->Username = $smtp_username;
$mail->Password = $smtppassword;
}
} else {
$mail->Mailer = 'sendmail';
}
$mail->Subject = from_html($mod_strings['LBL_TEST_EMAIL_SUBJECT']);
$mail->From = $fromaddress;
if ($fromname != '') {
$mail->FromName = html_entity_decode($fromname, ENT_QUOTES);
} else {
$mail->FromName = $current_user->name;
}
$mail->Sender = $mail->From;
$mail->AddAddress($toaddress);
$mail->Body = $mod_strings['LBL_TEST_EMAIL_BODY'];
$return = array();
if (!$mail->Send()) {
ob_clean();
$return['status'] = false;
$return['errorMessage'] = $app_strings['LBL_EMAIL_ERROR_PREPEND'] . $mail->ErrorInfo;
return $return;
} // if
$return['status'] = true;
return $return;
} // fn
/**
* @param $htmlData
* @return mixed
*/
public function decodeDuringSend($htmlData)
{
$htmlData = str_replace("sugarLessThan", "<", $htmlData);
$htmlData = str_replace("sugarGreaterThan", ">", $htmlData);
return $htmlData;
}
/**
* Returns true or false if this email is a draft.
*
* @param array $request
* @return bool True indicates this email is a draft.
*/
public function isDraftEmail($request)
{
return (isset($request['saveDraft']) || ($this->type == 'draft' && $this->status == 'draft'));
}
/**
*
* Sends Email for Email 2.0
*
* @param $request
* @return bool
*/
public function email2Send($request)
{
global $mod_strings;
global $app_strings;
global $current_user;
global $sugar_config;
global $locale;
global $timedate;
global $beanList;
global $beanFiles;
$OBCharset = $locale->getPrecedentPreference('default_email_charset');
/**********************************************************************
* 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']);
if (empty($mail->Host) && !$this->isDraftEmail($request)) {
$this->status = 'send_error';
if ($mail->oe->type == 'system') {
echo($app_strings['LBL_EMAIL_ERROR_PREPEND'] . $app_strings['LBL_EMAIL_INVALID_SYSTEM_OUTBOUND']);
} else {
echo($app_strings['LBL_EMAIL_ERROR_PREPEND'] . $app_strings['LBL_EMAIL_INVALID_PERSONAL_OUTBOUND']);
}
return false;
}
$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 = $_REQUEST['sendDescription'];
}
// end work-around
if ($this->isDraftEmail($request)) {
if ($this->type != 'draft' && $this->status != 'draft') {
$this->id = create_guid();
$this->new_with_id = true;
$this->date_entered = "";
} // 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();
if (isset($_REQUEST['parent_type']) && !empty($_REQUEST['parent_type']) &&
isset($_REQUEST['parent_id']) && !empty($_REQUEST['parent_id']) &&
($_REQUEST['parent_type'] == 'Accounts' ||
$_REQUEST['parent_type'] == 'Contacts' ||
$_REQUEST['parent_type'] == 'Leads' ||
$_REQUEST['parent_type'] == 'Users' ||
$_REQUEST['parent_type'] == 'Prospects')
) {
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
}
foreach ($toAddresses as $addrMeta) {
$addr = $addrMeta['email'];
$beans = $sea->getBeansByEmailAddress($addr);
foreach ($beans as $bean) {
if (!isset($object_arr[$bean->module_dir])) {
$object_arr[$bean->module_dir] = $bean->id;
}
}
}
/* 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);
$this->description = html_entity_decode($this->description, ENT_COMPAT, 'UTF-8');
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);
$this->description = $this->decodeDuringSend($this->description);
/* from account */
$replyToAddress = $current_user->emailAddress->getReplyToAddress($current_user, true);
$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();
// Personal Account doesn't have reply To Name and Reply To Address. So add those columns on UI
// After adding remove below code
// code to remove
if ($ie->is_personal) {
if (empty($replyToAddress)) {
$replyToAddress = $current_user->emailAddress->getReplyToAddress($current_user, true);
} // if
if (empty($replyToName)) {
$replyToName = $defaults['name'];
} // if
//Personal accounts can have a reply_address, which should
//overwrite the users set default.
if (!empty($storedOptions['reply_to_addr'])) {
$replyToAddress = $storedOptions['reply_to_addr'];
}
}
// end of code to remove
$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, $locale->translateCharsetMIME(trim($replyToName), 'UTF-8', $OBCharset));
} else {
$mail->AddReplyTo($mail->From, $locale->translateCharsetMIME(trim($mail->FromName), 'UTF-8', $OBCharset));
} // else
$emailAddressCollection = array(); // used in linking to beans below
// handle to/cc/bcc
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'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
$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'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
$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'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
$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}";
$fileGUID = preg_replace('/[^a-z0-9\-]/', "", substr($file, 0, 36));
$fileLocation = $this->et->userCacheDir . "/{$fileGUID}";
$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;
$note->file_mime_type = $this->email2GetMime($fileLocation);
$dest = "upload://{$note->id}";
if (!copy($fileLocation, $dest)) {
$GLOBALS['log']->debug("EMAIL 2.0: could not copy attachment file to $fileLocation => $dest");
}
$note->save();
}
}
}
}
/* handle sugar documents */
if (!empty($request['documents'])) {
$exDocs = explode("::", $request['documents']);
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;
$docGUID = preg_replace('/[^a-z0-9\-]/', "", $docRev->id);
$fileLocation = "upload://{$docGUID}";
$mime_type = $docRev->file_mime_type;
$mail->AddAttachment($fileLocation,
$locale->translateCharsetMIME(trim($filename), 'UTF-8', $OBCharset), '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;
$dest = "upload://{$note->id}";
if (!copy($fileLocation, $dest)) {
$GLOBALS['log']->debug("EMAIL 2.0: could not copy SugarDocument revision file $fileLocation => $dest");
}
$note->save();
}
}
}
}
/* handle template attachments */
if (!empty($request['templateAttachments'])) {
$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;
$noteGUID = preg_replace('/[^a-z0-9\-]/', "", $note->id);
$fileLocation = "upload://{$noteGUID}";
$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) {
$this->saveTempNoteAttachments($filename, $fileLocation, $mime_type);
}
} // if
} // if
} else {
//$fileLocation = $this->et->userCacheDir."/{$file}";
$fileGUID = preg_replace('/[^a-z0-9\-]/', "", substr($noteId, 0, 36));
$fileLocation = $this->et->userCacheDir . "/{$fileGUID}";
//$fileLocation = $this->et->userCacheDir."/{$noteId}";
$filename = substr($noteId, 36,
strlen($noteId)); // strip GUID for PHPMailer class to name outbound file
$mail->AddAttachment($fileLocation,
$locale->translateCharsetMIME(trim($filename), 'UTF-8', $OBCharset), 'base64',
$this->email2GetMime($fileLocation));
//If we are saving an email we were going to forward we need to save the attachments as well.
if ((($this->type == 'draft') && !empty($this->id))
|| (isset($request['saveToSugar']) && $request['saveToSugar'] == 1)
) {
$mimeType = $this->email2GetMime($fileLocation);
$this->saveTempNoteAttachments($filename, $fileLocation, $mimeType);
} // if
}
}
}
}
/**********************************************************************
* 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();
$mail->Body = $this->decodeDuringSend($mail->Body);
$mail->AltBody = $this->decodeDuringSend($mail->AltBody);
if (!$mail->Send()) {
$this->status = 'send_error';
ob_clean();
echo($app_strings['LBL_EMAIL_ERROR_PREPEND'] . $mail->ErrorInfo);
return false;
}
}
if ((!(empty($orignialId) || isset($request['saveDraft']) || ($this->type == 'draft' && $this->status == 'draft'))) &&
(($_REQUEST['composeType'] == 'reply') || ($_REQUEST['composeType'] == 'replyAll') || ($_REQUEST['composeType'] == 'replyCase')) && ($orignialId != $this->id)
) {
$originalEmail = new Email();
$originalEmail->retrieve($orignialId);
$originalEmail->reply_to_status = 1;
$originalEmail->save();
$this->reply_to_status = 0;
} // if
if ($_REQUEST['composeType'] == 'reply' || $_REQUEST['composeType'] == 'replyCase') {
if (isset($_REQUEST['ieId']) && isset($_REQUEST['mbox'])) {
$emailFromIe = new InboundEmail();
$emailFromIe->retrieve($_REQUEST['ieId']);
$emailFromIe->mailbox = $_REQUEST['mbox'];
if (isset($emailFromIe->id) && $emailFromIe->is_personal) {
if ($emailFromIe->isPop3Protocol()) {
$emailFromIe->mark_answered($this->uid, 'pop3');
} elseif ($emailFromIe->connectMailserver() == 'true') {
$emailFromIe->markEmails($this->uid, 'answered');
$emailFromIe->mark_answered($this->uid);
}
}
}
}
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;
$this->date_sent = $timedate->now();
///////////////////////////////////////////////////////////////////
//// 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')) {
} else {
$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
//// LINK EMAIL TO SUGARBEANS BASED ON EMAIL ADDY
///////////////////////////////////////////////////////////////////
$this->save();
}
if (!empty($request['fromAccount'])) {
if (isset($ie->id) && !$ie->isPop3Protocol() && $mail->oe->mail_smtptype != 'gmail') {
$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 config-specified separated name and addresses to be used in compose email screen for
* contacts or leads from listview
* By default, use comma, but allow for non-standard delimiters as specified in email_address_separator
*
* @param $module string module name
* @param $idsArray array of record ids to get the email address for
* @return string (config-specified) delimited list of email addresses
*/
public function getNamePlusEmailAddressesForCompose($module, $idsArray)
{
global $locale;
$result = array();
foreach ($idsArray as $id) {
// Load bean
$bean = BeanFactory::getBean($module, $id);
// Got a bean
if (!empty($bean)) {
// For CE, just get primary e-mail address
$emailAddress = $bean->email1;
// If we have an e-mail address loaded
if (!empty($emailAddress)) {
// Use bean name by default
$fullName = $bean->name;
// Depending on module, format the name
if (in_array($module, array('Users', 'Employees'))) {
$fullName = from_html(
$locale->getLocaleFormattedName(
$bean->first_name,
$bean->last_name,
'',
$bean->title
)
);
} else {
if (SugarModule::get($module)->moduleImplements('Person')) {
$fullName = from_html(
$locale->getLocaleFormattedName(
$bean->first_name,
$bean->last_name,
$bean->salutation,
$bean->title
)
);
}
}
// Make e-mail address in format "Name <@email>"
$result[$bean->id] = $fullName . " <" . from_html($emailAddress) . ">";
}
}
}
// Broken out of method to facilitate unit testing
return $this->_arrayToDelimitedString($result);
}
/**
* @param Array $arr - list of strings
* @return string the list of strings delimited by email_address_separator
*/
function _arrayToDelimitedString($arr)
{
// bug 51804: outlook does not respect the correct email address separator (',') , so let
// clients override the default.
$separator = (isset($GLOBALS['sugar_config']['email_address_separator']) &&
!empty($GLOBALS['sugar_config']['email_address_separator'])) ?
$GLOBALS['sugar_config']['email_address_separator'] :
',';
return join($separator, array_values($arr));
}
/**
* Overrides
*/
///////////////////////////////////////////////////////////////////////////
//// SAVERS
/**
* @param bool $check_notify
* @return bool|string
*/
public function save($check_notify = false)
{
global $current_user;
$id = 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->from_addr_name = $this->cleanEmails($this->from_addr_name);
$this->to_addrs_names = $this->cleanEmails($this->to_addrs_names);
$this->cc_addrs_names = $this->cleanEmails($this->cc_addrs_names);
$this->bcc_addrs_names = $this->cleanEmails($this->bcc_addrs_names);
$this->reply_to_addr = $this->cleanEmails($this->reply_to_addr);
$this->description = SugarCleaner::cleanHtml($this->description);
if(empty($this->description_html)) {
$this->description_html = $this->description;
$this->description_html = nl2br($this->description_html);
}
$this->description_html = SugarCleaner::cleanHtml($this->description_html, true);
$this->raw_source = SugarCleaner::cleanHtml($this->raw_source, true);
$this->saveEmailText();
$this->saveEmailAddresses();
if (empty($this->assigned_user_id)) {
$this->assigned_user_id = $current_user->id;
}
$GLOBALS['log']->debug('-------------------------------> Email called save()');
// handle legacy concatenation of date and time fields
//Bug 39503 - SugarBean is not setting date_sent when seconds missing
if (empty($this->date_sent)) {
global $timedate;
$date_sent_obj = $timedate->fromUser($timedate->merge_date_time($this->date_start, $this->time_start),
$current_user);
if (!empty($date_sent_obj) && ($date_sent_obj instanceof SugarDateTime)) {
$this->date_sent = $date_sent_obj->asDb();
}
}
$id = parent::save($check_notify);
if (!empty($this->parent_type) && !empty($this->parent_id)) {
if (!empty($this->fetched_row) && !empty($this->fetched_row['parent_id']) && !empty($this->fetched_row['parent_type'])) {
if ($this->fetched_row['parent_id'] != $this->parent_id || $this->fetched_row['parent_type'] != $this->parent_type) {
$mod = strtolower($this->fetched_row['parent_type']);
$rel = array_key_exists($mod,
$this->field_defs) ? $mod : $mod . "_activities_emails"; //Custom modules rel name
if ($this->load_relationship($rel)) {
$this->$rel->delete($this->id, $this->fetched_row['parent_id']);
}
}
}
$mod = strtolower($this->parent_type);
$rel = array_key_exists($mod,
$this->field_defs) ? $mod : $mod . "_activities_emails"; //Custom modules rel name
if ($this->load_relationship($rel)) {
$this->$rel->add($this->parent_id);
}
}
}
$GLOBALS['log']->debug('-------------------------------> Email save() done');
return $id;
}
/**
* Helper function to save temporary attachments assocaited to an email as note.
*
* @param string $filename
* @param string $fileLocation
* @param string $mimeType
*/
public function saveTempNoteAttachments($filename, $fileLocation, $mimeType)
{
$tmpNote = new Note();
$tmpNote->id = create_guid();
$tmpNote->new_with_id = true;
$tmpNote->parent_id = $this->id;
$tmpNote->parent_type = $this->module_dir;
$tmpNote->name = $filename;
$tmpNote->filename = $filename;
$tmpNote->file_mime_type = $mimeType;
$noteFile = "upload://{$tmpNote->id}";
if (!copy($fileLocation, $noteFile)) {
$GLOBALS['log']->fatal("EMAIL 2.0: could not copy SugarDocument revision file $fileLocation => $noteFile");
}
$tmpNote->save();
}
/**
* Handles normalization of Email Addressess
*/
public 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;
}
protected $email_to_text = array(
"email_id" => "id",
"description" => "description",
"description_html" => "description_html",
"raw_source" => "raw_source",
"from_addr" => "from_addr_name",
"reply_to_addr" => "reply_to_addr",
"to_addrs" => "to_addrs_names",
"cc_addrs" => "cc_addrs_names",
"bcc_addrs" => "bcc_addrs_names",
);
function cleanEmails($emails)
{
if (empty($emails)) {
return '';
}
$emails = str_replace(array(",", ";"), "::", from_html($emails));
$addrs = explode("::", $emails);
$res = array();
foreach ($addrs as $addr) {
$parts = $this->emailAddress->splitEmailAddress($addr);
if (empty($parts["email"])) {
continue;
}
if (!empty($parts["name"])) {
$res[] = "{$parts['name']} <{$parts['email']}>";
} else {
$res[] .= $parts["email"];
}
}
return implode(", ", $res);
}
protected function saveEmailText()
{
$emailText = SugarModule::get("EmailText")->loadBean();
foreach ($this->email_to_text as $textfield => $mailfield) {
$emailText->{$textfield} = $this->{$mailfield};
}
$emailText->email_id = $this->id;
if (!$this->new_with_id) {
$this->db->update($emailText);
} else {
$this->db->insert($emailText);
}
}
///////////////////////////////////////////////////////////////////////////
//// RETRIEVERS
public function retrieve($id = -1, $encoded = true, $deleted = true)
{
// cn: bug 11915, return SugarBean's retrieve() call bean instead of $this
$email = parent::retrieve($id, $encoded, $deleted);
if ($email) {
$email->retrieveEmailText();
//$ret->raw_source = SugarCleaner::cleanHtml($ret->raw_source);
$email->description = $email->description;
if(empty($email->description_html)) {
$email->description_html = $email->description;
$email->description_html = nl2br($email->description_html);
}
//$ret->description_html = SugarCleaner::cleanHtml($ret->description_html);
$email->retrieveEmailAddresses();
$email->date_start = '';
$email->time_start = '';
$dateSent = explode(' ', $email->date_sent);
if (!empty($dateSent)) {
$email->date_start = $dateSent[0];
if (isset($dateSent[1])) {
$email->time_start = $dateSent[1];
}
}
}
return $email;
}
/**
* Retrieves email addresses from GUIDs
*/
public 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
*/
public 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, 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'];
}
/**
* @param string $id
*/
public function delete($id = '')
{
if (empty($id)) {
$id = $this->id;
}
$id = $this->db->quote($id);
$q = "UPDATE emails SET deleted = 1 WHERE id = '{$id}'";
$qt = "UPDATE emails_text SET deleted = 1 WHERE email_id = '{$id}'";
$qf = "UPDATE folders_rel SET deleted = 1 WHERE polymorphic_id = '{$id}' AND polymorphic_module = 'Emails'";
$qn = "UPDATE notes SET deleted = 1 WHERE parent_id = '{$id}' AND parent_type = 'Emails'";
$this->db->query($q);
$this->db->query($qt);
$this->db->query($qf);
$this->db->query($qn);
}
/**
* creates the standard "Forward" info at the top of the forwarded message
* @return string
*/
public 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 = "
";
$ret .= $this->replyDelimiter . "{$mod_strings['LBL_FROM']} {$from} ";
$ret .= $this->replyDelimiter . "{$mod_strings['LBL_DATE_SENT']} {$this->date_sent} ";
$ret .= $this->replyDelimiter . "{$mod_strings['LBL_TO']} {$this->to_addrs} ";
$ret .= $this->replyDelimiter . "{$mod_strings['LBL_CC']} {$this->cc_addrs} ";
$ret .= $this->replyDelimiter . "{$mod_strings['LBL_SUBJECT']} {$subject} ";
$ret .= $this->replyDelimiter . " ";
return $ret;
//return from_html($ret);
}
/**
* retrieves Notes that belong to this Email and stuffs them into the "attachments" attribute
*/
public function getNotes($id, $duplicate = false)
{
if (!class_exists('Note')) {
}
$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();
$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
*/
public function getReplyHeader()
{
global $mod_strings;
global $current_user;
$from = str_replace(array(">", "<", ">", "<"), array(")", "(", ")", "("), $this->from_name);
$ret = " {$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
*/
public function quotePlainTextEmail($text)
{
$quoted = "\n";
// plain-text
$desc = nl2br(trim($text));
$exDesc = explode(' ', $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
*/
public function quoteHtmlEmail($text)
{
$text = trim(from_html($text));
if (empty($text)) {
return '';
}
$out = "
{$text}
";
return $out;
}
/**
* "quotes" (i.e., "> my text yadda" the HTML part of an email
* @param string $text HTML text to quote
* @return string
*/
public function quoteHtmlEmailForNewEmailUI($text)
{
$text = trim($text);
if (empty($text)) {
return '';
}
$text = str_replace("\n", " ", $text);
$out = "
{$text}
";
return $out;
}
/**
* Ensures that the user is able to send outbound emails
*/
public 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
*/
public function js_set_archived()
{
global $mod_strings;
$script = '
';
return $script;
}
/**
* replaces the javascript in utils.php - more specialized
* @param string $type
* @param string $group
* @param string $assigned_user_id
* @return string
*/
public 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 = '
';
return $the_script;
}
/**
* @return string
*/
public function pickOneButton()
{
global $theme;
global $mod_strings;
$out = '';
return $out;
}
/**
* Determines what Editor (HTML or Plain-text) the current_user uses;
* @return string Editor type
*/
public 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
*/
public 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,}/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" 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;
}
/**
* @param $arr
* @return array
*/
public 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
*/
public function handleAttachments()
{
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->date_entered = '';
$noteTemplate->save();
$noteFile = new UploadFile();
$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();
$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
///////////////////////////////////////////////////////////////////////////
}
/**
* Handles file attachments with multiple files
*/
public function handleMultipleFileAttachments()
{
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->date_entered = '';
$noteTemplate->save();
$noteFile = new UploadFile();
$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 = (array)$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"]['name'][$i])) {
$GLOBALS['log']->debug("Email Attachment {$i} does not exist.");
continue;
}
if ($_FILES['email_attachment']['error'][$i] != 0 && $_FILES['email_attachment']['error'][$i] != 4) {
$GLOBALS['log']->debug('Email Attachment could not be attach due to error: ' . $filesError[$_FILES['email_attachment']['error'][$i]]);
continue;
}
$note = new Note();
$note->parent_id = $this->id;
$note->parent_type = $this->module_dir;
$upload_file = new UploadMultipleFiles('email_attachment', $i);
if (empty($upload_file)) {
continue;
}
if (isset($_FILES['email_attachment']['name'][$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 ((array)$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 < $max_files_upload; $i++) {
if (isset($_REQUEST['documentId' . $i]) && !empty($_REQUEST['documentId' . $i])) {
$doc = new Document();
$docRev = new DocumentRevision();
$docNote = new Note();
$noteFile = new UploadFile();
$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 $str to be normalized
* @return string
*/
public 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
*/
public 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
*/
public 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") {
//Set mail send type information
$mail->Mailer = "smtp";
$mail->Host = $oe->mail_smtpserver;
$mail->Port = $oe->mail_smtpport;
if ($oe->mail_smtpssl == 1) {
$mail->SMTPSecure = 'ssl';
} // if
if ($oe->mail_smtpssl == 2) {
$mail->SMTPSecure = 'tls';
} // if
if ($oe->mail_smtpauth_req) {
$mail->SMTPAuth = true;
$mail->Username = $oe->mail_smtpuser;
$mail->Password = $oe->mail_smtppass;
}
} else {
$mail->Mailer = "sendmail";
}
$mail->oe = $oe;
return $mail;
}
/**
* Preps SugarPHPMailer object for HTML or Plain text sends
* @param SugarPHPMailer $mail
* @return Email
*/
public function handleBody($mail)
{
global $current_user;
// User preferences should takee precedence over everything else
$emailSettings = $current_user->getPreference('emailSettings', 'Emails');
$alwaysSendEmailsInPlainText = $emailSettings['sendPlainText'] === '1';
$sendEmailsInPlainText = false;
if(isset($_REQUEST['is_only_plain_text']) && $_REQUEST['is_only_plain_text'] === 'true') {
$sendEmailsInPlainText = true;
}
if($alwaysSendEmailsInPlainText === true) {
// plain text only
$this->handleBodyInPlainTextFormat($mail);
} else if($alwaysSendEmailsInPlainText === false && $sendEmailsInPlainText === true) {
$this->handleBodyInPlainTextFormat($mail);
} else {
$this->handleBodyInHTMLformat($mail);
}
// 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;
}
}
return $mail;
}
/**
* Retrieve function from handlebody() to unit test easily
* @param SugarPHPMailer $mail
*/
public function handleBodyInHTMLformat($mail)
{
global $sugar_config;
// 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;
$mail->replaceImageByRegex("(?:{$sugar_config['site_url']})?/?cache/images/", sugar_cached("images/"));
//Replace any embeded images using the secure entryPoint for src url.
$mail->replaceImageByRegex("(?:{$sugar_config['site_url']})?/?index.php[?]entryPoint=download&(?:amp;)?[^\"]+?id=",
"upload://", true);
$mail->Body = from_html($mail->Body);
}
/**
* Sends Email
* @return bool True on success
*/
public function send()
{
global $mod_strings, $app_strings;
global $current_user;
global $sugar_config;
global $locale;
$OBCharset = $locale->getPrecedentPreference('default_email_charset');
$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'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
}
foreach ($this->cc_addrs_arr as $addr_arr) {
if (empty($addr_arr['display'])) {
$mail->AddCC($addr_arr['email'], "");
} else {
$mail->AddCC($addr_arr['email'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
}
foreach ($this->bcc_addrs_arr as $addr_arr) {
if (empty($addr_arr['display'])) {
$mail->AddBCC($addr_arr['email'], "");
} else {
$mail->AddBCC($addr_arr['email'],
$locale->translateCharsetMIME(trim($addr_arr['display']), 'UTF-8', $OBCharset));
}
}
$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, $locale->translateCharsetMIME(trim($ReplyToName), 'UTF-8', $OBCharset));
//$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 = "file://" . $note->file->temp_file_location;
$filename = $note->file->original_file_name;
$mime_type = $note->file->mime_type;
} else { // attachment coming from template/forward
$file_location = "upload://{$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 = "upload://$note->id";
$mime_type = $note->file_mime_type;
}
// strip out the "Email attachment label if exists
$filename = str_replace($mod_strings['LBL_EMAIL_ATTACHMENT'] . ': ', '', $filename);
$file_ext = pathinfo($filename, PATHINFO_EXTENSION);
//is attachment in our list of bad files extensions? If so, append .txt to file location
//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, $locale->translateCharsetMIME(trim($filename), 'UTF-8', $OBCharset),
'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);
$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($app_strings['LBL_EMAIL_ERROR_PREPEND'] . $mail->ErrorInfo);
return false;
}
/**
* @return string[]
*/
public function listviewACLHelper()
{
$array_assign = parent::listviewACLHelper();
$is_owner = false;
$in_group = false; //SECURITY GROUPS
if (!empty($this->parent_name)) {
if (!empty($this->parent_name_owner)) {
global $current_user;
$is_owner = $current_user->id == $this->parent_name_owner;
}
/* BEGIN - SECURITY GROUPS */
//parent_name_owner not being set for whatever reason so we need to figure this out
else {
if (!empty($this->parent_type) && !empty($this->parent_id)) {
global $current_user;
$parent_bean = BeanFactory::getBean($this->parent_type, $this->parent_id);
if ($parent_bean !== false) {
$is_owner = $current_user->id == $parent_bean->assigned_user_id;
}
}
}
require_once("modules/SecurityGroups/SecurityGroup.php");
$in_group = SecurityGroup::groupHasAccess($this->parent_type, $this->parent_id, 'view');
/* END - SECURITY GROUPS */
}
/* BEGIN - SECURITY GROUPS */
/**
* if(!ACLController::moduleSupportsACL($this->parent_type) || ACLController::checkAccess($this->parent_type, 'view', $is_owner)){
*/
if (!ACLController::moduleSupportsACL($this->parent_type) || ACLController::checkAccess($this->parent_type,
'view', $is_owner, 'module', $in_group)
) {
/* END - SECURITY GROUPS */
$array_assign['PARENT'] = 'a';
} else {
$array_assign['PARENT'] = 'span';
}
$is_owner = false;
$in_group = false; //SECURITY GROUPS
if (!empty($this->contact_name)) {
if (!empty($this->contact_name_owner)) {
global $current_user;
$is_owner = $current_user->id == $this->contact_name_owner;
}
/* BEGIN - SECURITY GROUPS */
//contact_name_owner not being set for whatever reason so we need to figure this out
else {
global $current_user;
$parent_bean = BeanFactory::getBean('Contacts', $this->contact_id);
if ($parent_bean !== false) {
$is_owner = $current_user->id == $parent_bean->assigned_user_id;
}
}
require_once("modules/SecurityGroups/SecurityGroup.php");
$in_group = SecurityGroup::groupHasAccess('Contacts', $this->contact_id, 'view');
/* END - SECURITY GROUPS */
}
/* BEGIN - SECURITY GROUPS */
/**
* if(ACLController::checkAccess('Contacts', 'view', $is_owner)) {
*/
if (ACLController::checkAccess('Contacts', 'view', $is_owner, 'module', $in_group)) {
/* END - SECURITY GROUPS */
$array_assign['CONTACT'] = 'a';
} else {
$array_assign['CONTACT'] = 'span';
}
return $array_assign;
}
/**
* @return array
*/
public 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;
}
/**
* @param string $order_by
* @param string $where
* @param array $filter
* @param array $params
* @param int $show_deleted
* @param string $join_type
* @param bool $return_array
* @param null $parentbean
* @param bool $singleSelect
* @param bool $ifListForExport
* @return string
*/
public function create_new_list_query(
$order_by,
$where,
$filter = array(),
$params = array(),
$show_deleted = 0,
$join_type = '',
$return_array = false,
$parentbean = null,
$singleSelect = false,
$ifListForExport = false
) {
if ($return_array) {
return parent::create_new_list_query($order_by, $where, $filter, $params, $show_deleted, $join_type,
$return_array, $parentbean, $singleSelect);
}
$custom_join = $this->getCustomJoin();
$query = "SELECT " . $this->table_name . ".*, users.user_name as assigned_user_name\n";
$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";
}
$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;
} // fn
/**
* fill_in_additional_list_fields
*/
public function fill_in_additional_list_fields()
{
global $timedate, $mod_strings;
$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);
if ($row) {
$this->attachment_image = SugarThemeRegistry::current()->getImage(
'attachment',
'',
null,
null,
'.gif',
translate('LBL_ATTACHMENT', 'Emails')
);
} else {
$this->attachment_image = '';
}
///////////////////////////////////////////////////////////////////////
if (empty($this->contact_id) && !empty($this->parent_id) && !empty($this->parent_type) && $this->parent_type === 'Contacts' && !empty($this->parent_name)) {
$this->contact_id = $this->parent_id;
$this->contact_name = $this->parent_name;
}
}
/**
* fill_in_additional_detail_fields
*/
public 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, '');
//if ($this->parent_type == 'Contacts') {
$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.bean_module = 'Contacts' AND emails_beans.deleted=0 AND contacts.deleted=0";
if (!empty($this->parent_id) && $this->parent_type == 'Contacts') {
$query .= " AND contacts.id= '" . $this->parent_id . "' ";
} else {
if (!empty($_REQUEST['record']) && !empty($_REQUEST['module']) && $_REQUEST['module'] == 'Contacts') {
$query .= " AND contacts.id= '" . $_REQUEST['record'] . "' ";
}
}
$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) {
$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 = $mod_strings['LBL_NO_SUBJECT'];
}
$this->fill_in_additional_parent_fields();
}
/**
* @param string $order_by
* @param string $where
* @return string
*/
public function create_export_query($order_by, $where)
{
$contact_required = stristr($where, "contacts");
$custom_join = $this->getCustomJoin(true, true, $where);
if ($contact_required) {
$query = "SELECT emails.*, contacts.first_name, contacts.last_name";
$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.*';
$query .= $custom_join['select'];
$query .= ' FROM emails ';
$where_auto = "emails.deleted=0";
}
$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;
}
/**
* @return array
*/
public 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();
$this->retrieveEmailText();
$email_fields['FROM_ADDR'] = $this->from_addr_name;
$email_fields['FROM_ADDR_NAME'] = $this->from_addr_name;
$email_fields['TO_ADDRS'] = $this->to_addrs;
$email_fields['TO_ADDRS_NAMES'] = $this->to_addrs_names;
$mod_strings = return_module_language($GLOBALS['current_language'],
'Emails'); // hard-coding for Home screen ListView
if ($this->status != 'replied') {
$email_fields['QUICK_REPLY'] = '' . $mod_strings['LNK_QUICK_REPLY'] . '';
$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'] = '' . SugarThemeRegistry::current()->getImage('CreateCases',
'border="0"', null, null, ".gif",
$mod_strings['LBL_CREATE_CASES']) . $mod_strings['LBL_CREATE_CASE'] . '';
break;
case 'sales':
$email_fields['CREATE_RELATED'] = '' . SugarThemeRegistry::current()->getImage('CreateLeads',
'border="0"', null, null, ".gif",
$mod_strings['LBL_CREATE_LEADS']) . $mod_strings['LBL_CREATE_LEAD'] . '';
break;
case 'contact':
$email_fields['CREATE_RELATED'] = '' . SugarThemeRegistry::current()->getImage('CreateContacts',
'border="0"', null, null, ".gif",
$mod_strings['LBL_CREATE_CONTACTS']) . $mod_strings['LBL_CREATE_CONTACT'] . '';
break;
case 'bug':
$email_fields['CREATE_RELATED'] = '' . SugarThemeRegistry::current()->getImage('CreateBugs',
'border="0"', null, null, ".gif",
$mod_strings['LBL_CREATE_BUGS']) . $mod_strings['LBL_CREATE_BUG'] . '';
break;
case 'task':
$email_fields['CREATE_RELATED'] = '' . SugarThemeRegistry::current()->getImage('CreateTasks',
'border="0"', null, null, ".gif",
$mod_strings['LBL_CREATE_TASKS']) . $mod_strings['LBL_CREATE_TASK'] . '';
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) ? '' . $this->trimLongTo($this->to_addrs) . '' : $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;
}
$email_fields['CATEGORY_ID'] = empty ($this->category_id) ? "" : $app_list_strings['email_category_dom'][$this->category_id];
return $email_fields;
}
/**
* @return string
*/
public function quickCreateForm()
{
global $mod_strings, $app_strings, $currentModule, $current_language;
// Coming from the home page via Dashlets
if ($currentModule != 'Email') {
$mod_strings = return_module_language($current_language, 'Emails');
}
return $mod_strings['LBL_QUICK_CREATE'] . " " . SugarThemeRegistry::current()->getImage("advanced_search",
"border='0' align='absmiddle'", null, null, '.gif', $mod_strings['LBL_QUICK_CREATE']) . "";
}
/**
* Searches all imported emails and returns the result set as an array.
* @param string $sort
* @param string $direction
* @return array
*/
public function searchImportedEmails($sort = '', $direction = '')
{
require_once('include/TimeDate.php');
global $timedate;
global $current_user;
global $beanList;
global $sugar_config;
global $app_strings;
$emailSettings = $current_user->getPreference('emailSettings', 'Emails');
// cn: default to a low number until user specifies otherwise
if (empty($emailSettings['showNumInList'])) {
$pageSize = 20;
} else {
$pageSize = $emailSettings['showNumInList'];
}
if (isset($_REQUEST['start']) && isset($_REQUEST['limit'])) {
$page = ceil($_REQUEST['start'] / $_REQUEST['limit']) + 1;
} else {
$page = 1;
}
//Determine sort ordering
//Sort ordering parameters in the request do not coincide with actual column names
//so we need to remap them.
$hrSortLocal = array(
'flagged' => 'type',
'status' => 'reply_to_status',
'from' => 'emails_text.from_addr',
'subject' => 'name',
'date' => 'date_sent',
'AssignedTo' => 'assigned_user_id',
'flagged' => 'flagged'
);
$sort = !empty($_REQUEST['sort']) ? $this->db->getValidDBName($_REQUEST['sort']) : "";
$direction = !empty($_REQUEST['dir']) && in_array(strtolower($_REQUEST['dir']),
array("asc", "desc")) ? $_REQUEST['dir'] : "";
$order = (!empty($sort) && !empty($direction)) ? " ORDER BY {$hrSortLocal[$sort]} {$direction}" : "";
//Get our main query.
$fullQuery = $this->_genereateSearchImportedEmailsQuery();
//Perform a count query needed for pagination.
$countQuery = $this->create_list_count_query($fullQuery);
$count_rs = $this->db->query($countQuery, false, 'Error executing count query for imported emails search');
$count_row = $this->db->fetchByAssoc($count_rs);
$total_count = ($count_row != null) ? $count_row['c'] : 0;
$start = ($page - 1) * $pageSize;
//Execute the query
$rs = $this->db->limitQuery($fullQuery . $order, $start, $pageSize);
$return = array();
while ($a = $this->db->fetchByAssoc($rs)) {
$temp = array();
$temp['flagged'] = (is_null($a['flagged']) || $a['flagged'] == '0') ? '' : 1;
$temp['status'] = (is_null($a['reply_to_status']) || $a['reply_to_status'] == '0') ? '' : 1;
$temp['subject'] = $a['name'];
$temp['date'] = $timedate->to_display_date_time($a['date_sent']);
$temp['uid'] = $a['id'];
$temp['ieId'] = $a['mailbox_id'];
$temp['site_url'] = $sugar_config['site_url'];
$temp['seen'] = ($a['status'] == 'unread') ? 0 : 1;
$temp['type'] = $a['type'];
$temp['mbox'] = 'sugar::Emails';
$temp['hasAttach'] = $this->doesImportedEmailHaveAttachment($a['id']);
//To and from addresses may be stored in emails_text, if nothing is found, revert to
//regular email addresses.
$temp['to_addrs'] = preg_replace('/[\x00-\x08\x0B-\x1F]/', '', $a['to_addrs']);
$temp['from'] = preg_replace('/[\x00-\x08\x0B-\x1F]/', '', $a['from_addr']);
if (empty($temp['from']) || empty($temp['to_addrs'])) {
//Retrieve email addresses seperatly.
$tmpEmail = new Email();
$tmpEmail->id = $a['id'];
$tmpEmail->retrieveEmailAddresses();
$temp['from'] = $tmpEmail->from_addr;
$temp['to_addrs'] = $tmpEmail->to_addrs;
}
$return[] = $temp;
}
$metadata = array();
$metadata['totalCount'] = $total_count;
$metadata['out'] = $return;
return $metadata;
}
/**
* Determine if an imported email has an attachment by examining the relationship to notes.
*
* @param string $id
* @return boolean
*/
function doesImportedEmailHaveAttachment($id)
{
$hasAttachment = false;
$query = "SELECT id FROM notes where parent_id='$id' AND parent_type='Emails' AND file_mime_type is not null AND deleted=0";
$rs = $this->db->limitQuery($query, 0, 1);
$row = $this->db->fetchByAssoc($rs);
if (!empty($row['id'])) {
$hasAttachment = true;
}
return (int)$hasAttachment;
}
/**
* Generate the query used for searching imported emails.
*
* @return String Query to be executed.
*/
function _genereateSearchImportedEmailsQuery()
{
global $timedate;
$additionalWhereClause = $this->_generateSearchImportWhereClause();
$query = array();
$fullQuery = "";
$query['select'] = "emails.id , emails.mailbox_id, emails.name, emails.date_sent, emails.status, emails.type, emails.flagged, emails.reply_to_status,
emails_text.from_addr, emails_text.to_addrs FROM emails ";
$query['joins'] = " JOIN emails_text on emails.id = emails_text.email_id ";
//Handle from and to addr joins
if (!empty($_REQUEST['from_addr'])) {
$from_addr = $this->db->quote(strtolower($_REQUEST['from_addr']));
$query['joins'] .= "INNER JOIN emails_email_addr_rel er_from ON er_from.email_id = emails.id AND er_from.deleted = 0 INNER JOIN email_addresses ea_from ON ea_from.id = er_from.email_address_id
AND er_from.address_type='from' AND emails_text.from_addr LIKE '%" . $from_addr . "%'";
}
if (!empty($_REQUEST['to_addrs'])) {
$to_addrs = $this->db->quote(strtolower($_REQUEST['to_addrs']));
$query['joins'] .= "INNER JOIN emails_email_addr_rel er_to ON er_to.email_id = emails.id AND er_to.deleted = 0 INNER JOIN email_addresses ea_to ON ea_to.id = er_to.email_address_id
AND er_to.address_type='to' AND ea_to.email_address LIKE '%" . $to_addrs . "%'";
}
$query['where'] = " WHERE (emails.type= 'inbound' OR emails.type='archived' OR emails.type='out') AND emails.deleted = 0 ";
if (!empty($additionalWhereClause)) {
$query['where'] .= "AND $additionalWhereClause";
}
//If we are explicitly looking for attachments. Do not use a distinct query as the to_addr is defined
//as a text which equals clob in oracle and the distinct query can not be executed correctly.
$addDistinctKeyword = "";
if (!empty($_REQUEST['attachmentsSearch']) && $_REQUEST['attachmentsSearch'] == 1) //1 indicates yes
{
$query['where'] .= " AND EXISTS ( SELECT id FROM notes n WHERE n.parent_id = emails.id AND n.deleted = 0 AND n.filename is not null )";
} else {
if (!empty($_REQUEST['attachmentsSearch']) && $_REQUEST['attachmentsSearch'] == 2) {
$query['where'] .= " AND NOT EXISTS ( SELECT id FROM notes n WHERE n.parent_id = emails.id AND n.deleted = 0 AND n.filename is not null )";
}
}
$fullQuery = "SELECT " . $query['select'] . " " . $query['joins'] . " " . $query['where'];
return $fullQuery;
}
/**
* Generate the where clause for searching imported emails.
* @return array|string
*/
public function _generateSearchImportWhereClause()
{
global $timedate;
//The clear button was removed so if a user removes the asisgned user name, do not process the id.
if (empty($_REQUEST['assigned_user_name']) && !empty($_REQUEST['assigned_user_id'])) {
unset($_REQUEST['assigned_user_id']);
}
$availableSearchParam = array(
'name' => array('table_name' => 'emails'),
'data_parent_id_search' => array('table_name' => 'emails', 'db_key' => 'parent_id', 'opp' => '='),
'assigned_user_id' => array('table_name' => 'emails', 'opp' => '=')
);
$additionalWhereClause = array();
foreach ($availableSearchParam as $key => $properties) {
if (!empty($_REQUEST[$key])) {
$db_key = isset($properties['db_key']) ? $properties['db_key'] : $key;
$searchValue = $this->db->quote($_REQUEST[$key]);
$opp = isset($properties['opp']) ? $properties['opp'] : 'like';
if ($opp == 'like') {
$searchValue = "%" . $searchValue . "%";
}
$additionalWhereClause[] = "{$properties['table_name']}.$db_key $opp '$searchValue' ";
}
}
$isDateFromSearchSet = !empty($_REQUEST['searchDateFrom']);
$isdateToSearchSet = !empty($_REQUEST['searchDateTo']);
$bothDateRangesSet = $isDateFromSearchSet & $isdateToSearchSet;
//Hanlde date from and to separately
if ($bothDateRangesSet) {
$dbFormatDateFrom = $timedate->to_db_date($_REQUEST['searchDateFrom'], false);
$dbFormatDateFrom = db_convert("'" . $dbFormatDateFrom . "'", 'datetime');
$dbFormatDateTo = $timedate->to_db_date($_REQUEST['searchDateTo'], false);
$dbFormatDateTo = db_convert("'" . $dbFormatDateTo . "'", 'datetime');
$additionalWhereClause[] = "( emails.date_sent >= $dbFormatDateFrom AND
emails.date_sent <= $dbFormatDateTo )";
} elseif ($isdateToSearchSet) {
$dbFormatDateTo = $timedate->to_db_date($_REQUEST['searchDateTo'], false);
$dbFormatDateTo = db_convert("'" . $dbFormatDateTo . "'", 'datetime');
$additionalWhereClause[] = "emails.date_sent <= $dbFormatDateTo ";
} elseif ($isDateFromSearchSet) {
$dbFormatDateFrom = $timedate->to_db_date($_REQUEST['searchDateFrom'], false);
$dbFormatDateFrom = db_convert("'" . $dbFormatDateFrom . "'", 'datetime');
$additionalWhereClause[] = "emails.date_sent >= $dbFormatDateFrom ";
}
$additionalWhereClause = implode(" AND ", $additionalWhereClause);
return $additionalWhereClause;
}
/**
*
* takes a long TO: string of emails and returns the first appended by an elipse
* @param string $str
* @return string
*/
public function trimLongTo($str)
{
if (strpos($str, ',')) {
$exStr = explode(',', $str);
return $exStr[0] . '...';
} elseif (strpos($str, ';')) {
$exStr = explode(';', $str);
return $exStr[0] . '...';
} else {
return $str;
}
}
/**
* @return string
*/
public function get_summary_text()
{
return $this->name;
}
/**
* @param string $where
* @return string
*/
public 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 = '';
return $out;
}
/**
* @return string
*/
public 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 = '