div#rollover {position: relative;float: left;margin: none;text-decoration: none;}div#rollover a:hover {padding: 0;}div#rollover a span {display: none;}div#rollover a:hover span {text-decoration: none;display: block;width: 250px;margin-top: 5px;margin-left: 5px;position: absolute;padding: 10px;color: #333; border: 1px solid #ccc; background-color: #fff; font-size: 12px;z-index: 1000;}\n"; var $groupCss = ""; var $cacheTimeouts = array( 'messages' => 86400, // 24 hours 'folders' => 300, // 5 mins 'attachments' => 86400, // 24 hours ); var $userCacheDir = ''; var $coreDynamicFolderQuery = "SELECT emails.id polymorphic_id, 'Emails' polymorphic_module FROM emails JOIN emails_text on emails.id = emails_text.email_id WHERE (type = '::TYPE::' OR status = '::STATUS::') AND assigned_user_id = '::USER_ID::' AND emails.deleted = '0'"; /** * Sole constructor */ function EmailUI() { global $sugar_config; global $current_user; $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); if(!empty($folderStateSerial)) { $this->folderStates = unserialize($folderStateSerial); } $this->smarty = new Sugar_Smarty(); $this->folder = new SugarFolder(); $this->userCacheDir = sugar_cached("modules/Emails/{$current_user->id}"); $this->db = DBManagerFactory::getInstance(); } /////////////////////////////////////////////////////////////////////////// //// CORE /** * Renders the frame for emails */ function displayEmailFrame() { require_once("include/OutboundEmail/OutboundEmail.php"); global $app_strings, $app_list_strings; global $mod_strings; global $sugar_config; global $current_user; global $locale; global $timedate; global $theme; global $sugar_version; global $sugar_flavor; global $current_language; global $server_unique_key; $this->preflightUserCache(); $ie = new InboundEmail(); // focus listView $list = array( 'mbox' => 'Home', 'ieId' => '', 'name' => 'Home', 'unreadChecked' => 0, 'out' => array(), ); $this->_generateComposeConfigData('email_compose'); //Check quick create module access $QCAvailableModules = $this->_loadQuickCreateModules(); //Get the quickSearch js needed for assigned user id on Search Tab require_once('include/QuickSearchDefaults.php'); $qsd = new QuickSearchDefaults(); $qsd->setFormName('advancedSearchForm'); $quicksearchAssignedUser = "if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}"; $quicksearchAssignedUser .= "sqs_objects['advancedSearchForm_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";"; $qsd->setFormName('Distribute'); $quicksearchAssignedUser .= "sqs_objects['Distribute_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";"; $this->smarty->assign('quickSearchForAssignedUser', $quicksearchAssignedUser); /////////////////////////////////////////////////////////////////////// //// BASIC ASSIGNS $this->smarty->assign("currentUserId",$current_user->id); $this->smarty->assign("CURRENT_USER_EMAIL",$current_user->email1); $this->smarty->assign("currentUserName",$current_user->name); $this->smarty->assign('yuiPath', 'modules/Emails/javascript/yui-ext/'); $this->smarty->assign('app_strings', $app_strings); $this->smarty->assign('mod_strings', $mod_strings); $this->smarty->assign('theme', $theme); $this->smarty->assign('sugar_config', $sugar_config); $this->smarty->assign('is_admin', $current_user->is_admin); $this->smarty->assign('sugar_version', $sugar_version); $this->smarty->assign('sugar_flavor', $sugar_flavor); $this->smarty->assign('current_language', $current_language); $this->smarty->assign('server_unique_key', $server_unique_key); $this->smarty->assign('qcModules', json_encode($QCAvailableModules)); $extAllDebugValue = "ext-all.js"; $this->smarty->assign('extFileName', $extAllDebugValue); // settings: general $e2UserPreferences = $this->getUserPrefsJS(); $emailSettings = $e2UserPreferences['emailSettings']; /////////////////////////////////////////////////////////////////////// //// USER SETTINGS // settings: accounts $cuDatePref = $current_user->getUserDateTimePreferences(); $this->smarty->assign('dateFormat', $cuDatePref['date']); $this->smarty->assign('dateFormatExample', str_replace(array("Y", "m", "d"), array("yyyy", "mm", "dd"), $cuDatePref['date'])); $this->smarty->assign('calFormat', $timedate->get_cal_date_format()); $this->smarty->assign('TIME_FORMAT', $timedate->get_user_time_format()); $ieAccounts = $ie->retrieveByGroupId($current_user->id); $ieAccountsOptions = "\n"; foreach($ieAccounts as $k => $v) { $disabled = (!$v->is_personal) ? "DISABLED" : ""; $group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : ""; $ieAccountsOptions .= "\n"; } $this->smarty->assign('ieAccounts', $ieAccountsOptions); $this->smarty->assign('rollover', $this->rolloverStyle); $protocol = filterInboundEmailPopSelection($app_list_strings['dom_email_server_type']); $this->smarty->assign('PROTOCOL', get_select_options_with_id($protocol, '')); $this->smarty->assign('MAIL_SSL_OPTIONS', get_select_options_with_id($app_list_strings['email_settings_for_ssl'], '')); $this->smarty->assign('ie_mod_strings', return_module_language($current_language, 'InboundEmail')); $charsetSelectedValue = isset($emailSettings['defaultOutboundCharset']) ? $emailSettings['defaultOutboundCharset'] : false; if (!$charsetSelectedValue) { $charsetSelectedValue = $current_user->getPreference('default_export_charset', 'global'); if (!$charsetSelectedValue) { $charsetSelectedValue = $locale->getPrecedentPreference('default_email_charset'); } } $charset = array( 'options' => $locale->getCharsetSelect(), 'selected' => $charsetSelectedValue, ); $this->smarty->assign('charset', $charset); $emailCheckInterval = array('options' => $app_strings['LBL_EMAIL_CHECK_INTERVAL_DOM'], 'selected' => $emailSettings['emailCheckInterval']); $this->smarty->assign('emailCheckInterval', $emailCheckInterval); $this->smarty->assign('attachmentsSearchOptions', $app_list_strings['checkbox_dom']); $this->smarty->assign('sendPlainTextChecked', ($emailSettings['sendPlainText'] == 1) ? 'CHECKED' : ''); $this->smarty->assign('showNumInList', get_select_options_with_id($app_list_strings['email_settings_num_dom'], $emailSettings['showNumInList'])); //// END USER SETTINGS /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// //// SIGNATURES $prependSignature = ($current_user->getPreference('signature_prepend')) ? 'true' : 'false'; $defsigID = $current_user->getPreference('signature_default'); $this->smarty->assign('signatures', $current_user->getSignatures(false, $defsigID)); $this->smarty->assign('signaturesSettings', $current_user->getSignatures(false, $defsigID, false)); $signatureButtons = $current_user->getSignatureButtons('SUGAR.email2.settings.createSignature', !empty($defsigID)); if (!empty($defsigID)) { $signatureButtons = $signatureButtons . '  '; } else { $signatureButtons = $signatureButtons . ''; } $this->smarty->assign('signatureButtons', $signatureButtons); $this->smarty->assign('signaturePrepend', $prependSignature == 'true' ? 'CHECKED' : ''); //// END SIGNATURES /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// //// EMAIL TEMPLATES $email_templates_arr = $this->getEmailTemplatesArray(); natcasesort($email_templates_arr); $this->smarty->assign('EMAIL_TEMPLATE_OPTIONS', get_select_options_with_id($email_templates_arr, '')); //// END EMAIL TEMPLATES /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// //// FOLDERS & TreeView $this->smarty->assign('groupUserOptions', $ie->getGroupsWithSelectOptions(array('' => $app_strings['LBL_EMAIL_CREATE_NEW']))); $tree = $this->getMailboxNodes(); // preloaded folder $preloadFolder = 'lazyLoadFolder = '; $focusFolderSerial = $current_user->getPreference('focusFolder', 'Emails'); if(!empty($focusFolderSerial)) { $focusFolder = unserialize($focusFolderSerial); //$focusFolder['ieId'], $focusFolder['folder'] $preloadFolder .= json_encode($focusFolder).";"; } else { $preloadFolder .= "new Object();"; } //// END FOLDERS /////////////////////////////////////////////////////////////////////// $out = ""; $out .= $this->smarty->fetch("modules/Emails/templates/_baseEmail.tpl"); $out .= $tree->generate_header(); $out .= $tree->generateNodesNoInit(true, 'email2treeinit'); $out .=<< var loader = new YAHOO.util.YUILoader({ require : [ "layout", "element", "tabview", "menu", "cookie", "sugarwidgets" ], loadOptional: true, skin: { base: 'blank', defaultSkin: '' }, onSuccess: email2init, allowRollup: true, base: "include/javascript/yui/build/" }); loader.addModule({ name :"sugarwidgets", type : "js", fullpath: "include/javascript/sugarwidgets/SugarYUIWidgets.js", varName: "YAHOO.SUGAR", requires: ["datatable", "dragdrop", "treeview", "tabview", "calendar"] }); loader.insert(); {$preloadFolder}; eoq; return $out; } /** * Generate the frame needed for the quick compose email UI. This frame is loaded dynamically * by an ajax call. * * @return JSON An object containing html markup and js script variables. */ function displayQuickComposeEmailFrame() { $this->preflightUserCache(); $this->_generateComposeConfigData('email_compose_light'); $javascriptOut = $this->smarty->fetch("modules/Emails/templates/_baseConfigData.tpl"); $divOut = $this->smarty->fetch("modules/Emails/templates/overlay.tpl"); $divOut .= $this->smarty->fetch("modules/Emails/templates/addressSearchContent.tpl"); $outData = array('jsData' => $javascriptOut,'divData'=> $divOut); $out = json_encode($outData); return $out; } /** * Load the modules from the metadata file and include in a custom one if it exists * * @return array */ protected function _loadQuickCreateModules() { $QCAvailableModules = array(); $QCModules = array(); include('modules/Emails/metadata/qcmodulesdefs.php'); if (file_exists('custom/modules/Emails/metadata/qcmodulesdefs.php')) { include('custom/modules/Emails/metadata/qcmodulesdefs.php'); } foreach($QCModules as $module) { $seed = SugarModule::get($module)->loadBean(); if ( ( $seed instanceOf SugarBean ) && $seed->ACLAccess('edit') ) { $QCAvailableModules[] = $module; } } return $QCAvailableModules; } /** * Given an email link url (eg. index.php?action=Compose&parent_type=Contacts...) break up the * request components and create a compose package that can be used by the quick compose UI. The * result is typically passed into the js call SUGAR.quickCompose.init which initalizes the quick compose * UI. * * @param String $emailLinkUrl * @return JSON Object containing the composePackage and full link url */ function generateComposePackageForQuickCreateFromComposeUrl($emailLinkUrl, $lazyLoad=false) { $composeData = explode("&",$emailLinkUrl); $a_composeData = array(); foreach ($composeData as $singleRequest) { $tmp = explode("=",$singleRequest); $a_composeData[$tmp[0]] = urldecode($tmp[1]); } return $this->generateComposePackageForQuickCreate($a_composeData,$emailLinkUrl, $lazyLoad); } /** * Generate the composePackage for the quick compose email UI. The package contains * key/value pairs generated by the Compose.php file which are then set into the * quick compose email UI (eg. to addr, parent id, parent type, etc) * * @param Array $composeData Associative array read and processed by generateComposeDataPackage. * @param String $fullLinkUrl A link that contains all pertinant information so the user can be * directed to the full compose screen if needed * @param SugarBean $bean Optional - the parent object bean with data * @return JSON Object containg composePackage and fullLinkUrl */ function generateComposePackageForQuickCreate($composeData,$fullLinkUrl, $lazyLoad=false, $bean = null) { $_REQUEST['forQuickCreate'] = true; if(!$lazyLoad){ require_once('modules/Emails/Compose.php'); $composePackage = generateComposeDataPackage($composeData,FALSE, $bean); }else{ $composePackage = $composeData; } // JSON object is passed into the function defined within the a href onclick event // which is delimeted by '. Need to escape all single quotes and &, <, > // but not double quotes since json would escape them foreach ($composePackage as $key => $singleCompose) { if (is_string($singleCompose)) $composePackage[$key] = str_replace(" ", " ", from_html($singleCompose)); } $quickComposeOptions = array('fullComposeUrl' => $fullLinkUrl,'composePackage' => $composePackage); $j_quickComposeOptions = JSON::encode($quickComposeOptions, false ,true); return $j_quickComposeOptions; } /** * Generate the config data needed for the Full Compose UI and the Quick Compose UI. The set of config data * returned is the minimum set needed by the quick compose UI. * * @param String $type Drives which tinyMCE options will be included. */ function _generateComposeConfigData($type = "email_compose_light" ) { global $app_list_strings,$current_user, $app_strings, $mod_strings,$current_language,$locale; //Link drop-downs $parent_types = $app_list_strings['record_type_display']; $disabled_parent_types = ACLController::disabledModuleList($parent_types, false, 'list'); foreach($disabled_parent_types as $disabled_parent_type) { unset($parent_types[$disabled_parent_type]); } asort($parent_types); $linkBeans = json_encode(get_select_options_with_id($parent_types, '')); //TinyMCE Config require_once("include/SugarTinyMCE.php"); $tiny = new SugarTinyMCE(); $tinyConf = $tiny->getConfig($type); //Generate Language Packs $lang = "var app_strings = new Object();\n"; foreach($app_strings as $k => $v) { if(strpos($k, 'LBL_EMAIL_') !== false) { $lang .= "app_strings.{$k} = '{$v}';\n"; } } //Get the email mod strings but don't use the global variable as this may be overridden by //other modules when the quick create is rendered. $email_mod_strings = return_module_language($current_language,'Emails'); $modStrings = "var mod_strings = new Object();\n"; foreach($email_mod_strings as $k => $v) { $v = str_replace("'", "\'", $v); $modStrings .= "mod_strings.{$k} = '{$v}';\n"; } $lang .= "\n\n{$modStrings}\n"; //Grab the Inboundemail language pack $ieModStrings = "var ie_mod_strings = new Object();\n"; $ie_mod_strings = return_module_language($current_language,'InboundEmail'); foreach($ie_mod_strings as $k => $v) { $v = str_replace("'", "\'", $v); $ieModStrings .= "ie_mod_strings.{$k} = '{$v}';\n"; } $lang .= "\n\n{$ieModStrings}\n"; $this->smarty->assign('linkBeans', $linkBeans); $this->smarty->assign('linkBeansOptions', $parent_types); $this->smarty->assign('tinyMCE', $tinyConf); $this->smarty->assign('lang', $lang); $this->smarty->assign('app_strings', $app_strings); $this->smarty->assign('mod_strings', $email_mod_strings); $ie1 = new InboundEmail(); //Signatures $defsigID = $current_user->getPreference('signature_default'); $defaultSignature = $current_user->getDefaultSignature(); $sigJson = !empty($defaultSignature) ? json_encode(array($defaultSignature['id'] => from_html($defaultSignature['signature_html']))) : "new Object()"; $this->smarty->assign('defaultSignature', $sigJson); $this->smarty->assign('signatureDefaultId', (isset($defaultSignature['id'])) ? $defaultSignature['id'] : ""); //User Preferences $this->smarty->assign('userPrefs', json_encode($this->getUserPrefsJS())); //Get the users default outbound id $defaultOutID = $ie1->getUsersDefaultOutboundServerId($current_user); $this->smarty->assign('defaultOutID', $defaultOutID); //Character Set $charsets = json_encode($locale->getCharsetSelect()); $this->smarty->assign('emailCharsets', $charsets); //Relateable List of People for address book search //#20776 jchi $peopleTables = array("users", "contacts", "leads", "prospects", "accounts"); $filterPeopleTables = array(); global $app_list_strings, $app_strings; $filterPeopleTables['LBL_DROPDOWN_LIST_ALL'] = $app_strings['LBL_DROPDOWN_LIST_ALL']; foreach($peopleTables as $table) { $module = ucfirst($table); $class = substr($module, 0, strlen($module) - 1); require_once("modules/{$module}/{$class}.php"); $person = new $class(); if (!$person->ACLAccess('list')) continue; $filterPeopleTables[$person->table_name] = $app_list_strings['moduleList'][$person->module_dir]; } $this->smarty->assign('listOfPersons' , get_select_options_with_id($filterPeopleTables,'')); } //// END CORE /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// //// ADDRESS BOOK /** * Retrieves all relationship metadata for a user's address book * @return array */ function getContacts() { global $current_user; $q = "SELECT * FROM address_book WHERE assigned_user_id = '{$current_user->id}' ORDER BY bean DESC"; $r = $this->db->query($q); $ret = array(); while($a = $this->db->fetchByAssoc($r)) { $ret[$a['bean_id']] = array( 'id' => $a['bean_id'], 'module' => $a['bean'], ); } return $ret; } /** * Saves changes to a user's address book * @param array contacts */ function setContacts($contacts) { global $current_user; $oldContacts = $this->getContacts(); foreach($contacts as $cid => $contact) { if(!in_array($contact['id'], $oldContacts)) { $q = "INSERT INTO address_book (assigned_user_id, bean, bean_id) VALUES ('{$current_user->id}', '{$contact['module']}', '{$contact['id']}')"; $r = $this->db->query($q, true); } } } /** * Removes contacts from the user's address book * @param array ids */ function removeContacts($ids) { global $current_user; $concat = ""; foreach($ids as $id) { if(!empty($concat)) $concat .= ", "; $concat .= "'{$id}'"; } $q = "DELETE FROM address_book WHERE assigned_user_id = '{$current_user->id}' AND bean_id IN ({$concat})"; $r = $this->db->query($q); } /** * saves editted Contact info * @param string $str JSON serialized object */ function saveContactEdit($str) { $json = getJSONobj(); $str = from_html($str); $obj = $json->decode($str); $contact = new Contact(); $contact->retrieve($obj['contact_id']); $contact->first_name = $obj['contact_first_name']; $contact->last_name = $obj['contact_last_name']; $contact->save(); // handle email address changes $addresses = array(); foreach($obj as $k => $req) { if(strpos($k, 'emailAddress') !== false) { $addresses[$k] = $req; } } // prefill some REQUEST vars for emailAddress save $_REQUEST['emailAddressOptOutFlag'] = $obj['optOut']; $_REQUEST['emailAddressInvalidFlag'] = $obj['invalid']; $contact->emailAddress->save($obj['contact_id'], 'Contacts', $addresses, $obj['primary'], ''); } /** * Prepares the Edit Contact mini-form via template assignment * @param string id ID of contact in question * @param string module Module in focus * @return array */ function getEditContact($id, $module) { global $app_strings; if(!class_exists("Contact")) { } $contact = new Contact(); $contact->retrieve($_REQUEST['id']); $ret = array(); if($contact->ACLAccess('edit')) { $contactMeta = array(); $contactMeta['id'] = $contact->id; $contactMeta['module'] = $contact->module_dir; $contactMeta['first_name'] = $contact->first_name; $contactMeta['last_name'] = $contact->last_name; $this->smarty->assign("app_strings", $app_strings); $this->smarty->assign("contact_strings", return_module_language($_SESSION['authenticated_user_language'], 'Contacts')); $this->smarty->assign("contact", $contactMeta); $ea = new SugarEmailAddress(); $newEmail = $ea->getEmailAddressWidgetEditView($id, $module, true); $this->smarty->assign("emailWidget", $newEmail['html']); $ret['form'] = $this->smarty->fetch("modules/Emails/templates/editContact.tpl"); $ret['prefillData'] = $newEmail['prefillData']; } else { $id = ""; $ret['form'] = $app_strings['LBL_EMAIL_ERROR_NO_ACCESS']; $ret['prefillData'] = '{}'; } $ret['id'] = $id; $ret['contactName'] = $contact->full_name; return $ret; } /** * Retrieves a concatenated list of contacts, those with assigned_user_id = user's id and those in the address_book * table * @param array $contacts Array of contact types -> IDs * @param object $user User in focus * @return array */ function getUserContacts($contacts, $user=null) { global $current_user; global $locale; if(empty($user)) { $user = $current_user; } $emailAddress = new SugarEmailAddress(); $ret = array(); $union = ''; $modules = array(); foreach($contacts as $contact) { if(!isset($modules[$contact['module']])) { $modules[$contact['module']] = array(); } $modules[$contact['module']][] = $contact; } foreach($modules as $module => $contacts) { if(!empty($union)) { $union .= " UNION ALL "; } $table = strtolower($module); $idsSerial = ''; foreach($contacts as $contact) { if(!empty($idsSerial)) { $idsSerial .= ","; } $idsSerial .= "'{$contact['id']}'"; } $union .= "(SELECT id, first_name, last_name, title, '{$module}' module FROM {$table} WHERE id IN({$idsSerial}) AND deleted = 0 )"; } if(!empty($union)) { $union .= " ORDER BY last_name"; } $r = $user->db->query($union); //_pp($union); while($a = $user->db->fetchByAssoc($r)) { $c = array(); $c['name'] = $locale->getLocaleFormattedName($a['first_name'], "{$a['last_name']}", '', $a['title'], '', $user); $c['id'] = $a['id']; $c['module'] = $a['module']; $c['email'] = $emailAddress->getAddressesByGUID($a['id'], $a['module']); $ret[$a['id']] = $c; } return $ret; } //// END ADDRESS BOOK /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// //// EMAIL 2.0 Preferences function getUserPrefsJS() { global $current_user; global $locale; // sort order per mailbox view $sortSerial = $current_user->getPreference('folderSortOrder', 'Emails'); $sortArray = array(); if(!empty($sortSerial)) { $sortArray = unserialize($sortSerial); } // treeview collapsed/open states $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); $folderStates = array(); if(!empty($folderStateSerial)) { $folderStates = unserialize($folderStateSerial); } // subscribed accounts $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); // general settings $emailSettings = $current_user->getPreference('emailSettings', 'Emails'); if(empty($emailSettings)) { $emailSettings = array(); $emailSettings['emailCheckInterval'] = -1; $emailSettings['autoImport'] = ''; $emailSettings['alwaysSaveOutbound'] = '1'; $emailSettings['sendPlainText'] = ''; $emailSettings['defaultOutboundCharset'] = $GLOBALS['sugar_config']['default_email_charset']; $emailSettings['showNumInList'] = 20; } // focus folder $focusFolder = $current_user->getPreference('focusFolder', 'Emails'); $focusFolder = !empty($focusFolder) ? unserialize($focusFolder) : array(); // unread only flag $showUnreadOnly = $current_user->getPreference('showUnreadOnly', 'Emails'); $listViewSort = array( "sortBy" => 'date', "sortDirection" => 'DESC', ); // signature prefs $signaturePrepend = $current_user->getPreference('signature_prepend') ? 'true' : 'false'; $signatureDefault = $current_user->getPreference('signature_default'); $signatures = array( 'signature_prepend' => $signaturePrepend, 'signature_default' => $signatureDefault ); // current_user $user = array( 'emailAddresses' => $current_user->emailAddress->getAddressesByGUID($current_user->id, 'Users'), 'full_name' => from_html($current_user->full_name), ); $userPreferences = array(); $userPreferences['sort'] = $sortArray; $userPreferences['folderStates'] = $folderStates; $userPreferences['showFolders'] = $showFolders; $userPreferences['emailSettings'] = $emailSettings; $userPreferences['focusFolder'] = $focusFolder; $userPreferences['showUnreadOnly'] = $showUnreadOnly; $userPreferences['listViewSort'] = $listViewSort; $userPreferences['signatures'] = $signatures; $userPreferences['current_user'] = $user; return $userPreferences; } /////////////////////////////////////////////////////////////////////////// //// FOLDER FUNCTIONS /** * Creates a new Sugar folder * @param string $nodeLabel New sugar folder name * @param string $parentLabel Parent folder name */ function saveNewFolder($nodeLabel, $parentId, $isGroup=0) { global $current_user; $this->folder->name = $nodeLabel; $this->folder->is_group = $isGroup; $this->folder->parent_folder = ($parentId == 'Home') ? "" : $parentId; $this->folder->has_child = 0; $this->folder->created_by = $current_user->id; $this->folder->modified_by = $current_user->id; $this->folder->date_modified = $this->folder->date_created = TimeDate::getInstance()->nowDb(); $this->folder->save(); return array( 'action' => 'newFolderSave', 'id' => $this->folder->id, 'name' => $this->folder->name, 'is_group' => $this->folder->is_group, 'is_dynamic' => $this->folder->is_dynamic ); } /** * Saves user sort prefernces */ function saveListViewSortOrder($ieId, $focusFolder, $sortBy, $sortDir) { global $current_user; $sortArray = array(); $sortSerial = $current_user->getPreference('folderSortOrder', 'Emails'); if(!empty($sortSerial)) { $sortArray = unserialize($sortSerial); } $sortArray[$ieId][$focusFolder]['current']['sort'] = $sortBy; $sortArray[$ieId][$focusFolder]['current']['direction'] = $sortDir; $sortSerial = serialize($sortArray); $current_user->setPreference('folderSortOrder', $sortSerial, '', 'Emails'); } /** * Stickies folder collapse/open state */ function saveFolderOpenState($focusFolder, $focusFolderOpen) { global $current_user; $folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); $folderStates = array(); if(!empty($folderStateSerial)) { $folderStates = unserialize($folderStateSerial); } $folderStates[$focusFolder] = $focusFolderOpen; $newFolderStateSerial = serialize($folderStates); $current_user->setPreference('folderOpenState', $newFolderStateSerial, '', 'Emails'); } /** * saves a folder's view state */ function saveListView($ieId, $folder) { global $current_user; $saveState = array(); $saveState['ieId'] = $ieId; $saveState['folder'] = $folder; $saveStateSerial = serialize($saveState); $current_user->setPreference('focusFolder', $saveStateSerial, '', 'Emails'); } /** * Generates cache folder structure */ function preflightEmailCache($cacheRoot) { // base if(!file_exists($cacheRoot)) mkdir_recursive(clean_path($cacheRoot)); // folders if(!file_exists($cacheRoot."/folders")) mkdir_recursive(clean_path("{$cacheRoot}/folders")); // messages if(!file_exists($cacheRoot."/messages")) mkdir_recursive(clean_path("{$cacheRoot}/messages")); // attachments if(!file_exists($cacheRoot."/attachments")) mkdir_recursive(clean_path("{$cacheRoot}/attachments")); } function deleteEmailCacheForFolders($cacheRoot) { $filePath = $cacheRoot."/folders/folders.php"; if (file_exists($filePath)) { unlink($filePath); } } /////////////////////////////////////////////////////////////////////////// //// IMAP FUNCTIONS /** * Identifies subscribed mailboxes and empties the trash * @param object $ie InboundEmail */ function emptyTrash(&$ie) { global $current_user; $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); if(is_array($showFolders)) { foreach($showFolders as $ieId) { if(!empty($ieId)) { $ie->retrieve($ieId); $ie->emptyTrash(); } } } } /** * returns an array of nodes that correspond to IMAP mailboxes. * @param bool $forceRefresh * @return object TreeView object */ function getMailboxNodes() { global $sugar_config; global $current_user; global $app_strings; $tree = new Tree("frameFolders"); $tree->tree_style= 'include/ytree/TreeView/css/check/tree.css'; $nodes = array(); $ie = new InboundEmail(); $refreshOffset = $this->cacheTimeouts['folders']; // 5 mins. this will be set via user prefs $rootNode = new ExtNode($app_strings['LBL_EMAIL_HOME_FOLDER'], $app_strings['LBL_EMAIL_HOME_FOLDER']); $rootNode->dynamicloadfunction = ''; $rootNode->expanded = true; $rootNode->dynamic_load = true; $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); if(empty($showFolders)) { $showFolders = array(); } // INBOX NODES if($current_user->hasPersonalEmail()) { $personals = $ie->retrieveByGroupId($current_user->id); foreach($personals as $k => $personalAccount) { if(in_array($personalAccount->id, $showFolders)) { // check for cache value $cacheRoot = sugar_cached("modules/Emails/{$personalAccount->id}"); $this->preflightEmailCache($cacheRoot); if($this->validCacheFileExists($personalAccount->id, 'folders', "folders.php")) { $mailboxes = $this->getMailBoxesFromCacheValue($personalAccount); } else { $mailboxes = $personalAccount->getMailboxes(); } $acctNode = new ExtNode('Home::' . $personalAccount->name, $personalAccount->name); $acctNode->dynamicloadfunction = ''; $acctNode->expanded = false; $acctNode->set_property('cls', 'ieFolder'); $acctNode->set_property('ieId', $personalAccount->id); $acctNode->set_property('protocol', $personalAccount->protocol); if(array_key_exists('Home::'.$personalAccount->name, $this->folderStates)) { if($this->folderStates['Home::'.$personalAccount->name] == 'open') { $acctNode->expanded = true; } } $acctNode->dynamic_load = true; $nodePath = $acctNode->_properties['id']; foreach($mailboxes as $k => $mbox) { $acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $personalAccount->id, $nodePath, false, $personalAccount)); } $rootNode->add_node($acctNode); } } } // GROUP INBOX NODES $beans = $ie->retrieveAllByGroupId($current_user->id, false); foreach($beans as $k => $groupAccount) { if(in_array($groupAccount->id, $showFolders)) { // check for cache value $cacheRoot = sugar_cached("modules/Emails/{$groupAccount->id}"); $this->preflightEmailCache($cacheRoot); //$groupAccount->connectMailserver(); if($this->validCacheFileExists($groupAccount->id, 'folders', "folders.php")) { $mailboxes = $this->getMailBoxesFromCacheValue($groupAccount); } else { $mailboxes = $groupAccount->getMailBoxesForGroupAccount(); } $acctNode = new ExtNode($groupAccount->name, "group.{$groupAccount->name}"); $acctNode->dynamicloadfunction = ''; $acctNode->expanded = false; $acctNode->set_property('isGroup', 'true'); $acctNode->set_property('ieId', $groupAccount->id); $acctNode->set_property('protocol', $groupAccount->protocol); if(array_key_exists('Home::'.$groupAccount->name, $this->folderStates)) { if($this->folderStates['Home::'.$groupAccount->name] == 'open') { $acctNode->expanded = true; } } $acctNode->dynamic_load = true; $nodePath = $rootNode->_properties['id']."::".$acctNode->_properties['id']; foreach($mailboxes as $k => $mbox) { $acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $groupAccount->id, $nodePath, true, $groupAccount)); } $rootNode->add_node($acctNode); } } // SugarFolder nodes /* SugarFolders are built at onload when the UI renders */ $tree->add_node($rootNode); return $tree; } function getMailBoxesFromCacheValue($mailAccount) { $foldersCache = $this->getCacheValue($mailAccount->id, 'folders', "folders.php", 'foldersCache'); $mailboxes = $foldersCache['mailboxes']; $mailboxesArray = $mailAccount->generateFlatArrayFromMultiDimArray($mailboxes, $mailAccount->retrieveDelimiter()); $mailAccount->saveMailBoxFolders($mailboxesArray); $this->deleteEmailCacheForFolders($cacheRoot); return $mailboxes; } // fn /** * Builds up a TreeView Node object * @param mixed * @param mixed * @param string * @param string ID of InboundEmail instance * @param string nodePath Serialized path from root node to current node * @param bool isGroup * @param bool forceRefresh * @return mixed */ function buildTreeNode($key, $label, $mbox, $ieId, $nodePath, $isGroup, $ie) { global $sugar_config; // get unread counts $exMbox = explode("::", $nodePath); $unseen = 0; $GLOBALS['log']->debug("$key --- $nodePath::$label"); if(count($exMbox) >= 2) { $mailbox = ""; for($i=2; $igetUnreadCount($ie, $mailbox); if($unseen > 0) { //$label = " {$label} ({$unseen})"; } } $nodePath = $nodePath."::".$label; $node = new ExtNode($nodePath, $label); $node->dynamicloadfunction = ''; $node->expanded = false; $node->set_property('labelStyle', "remoteFolder"); if(array_key_exists($nodePath, $this->folderStates)) { if($this->folderStates[$nodePath] == 'open') { $node->expanded = true; } } $group = ($isGroup) ? 'true' : 'false'; $node->dynamic_load = true; //$node->set_property('href', " SUGAR.email2.listView.populateListFrame(YAHOO.namespace('frameFolders').selectednode, '{$ieId}', 'false');"); $node->set_property('isGroup', $group); $node->set_property('isDynamic', 'false'); $node->set_property('ieId', $ieId); $node->set_property('mbox', $key); $node->set_property('unseen', $unseen); $node->set_property('cls', 'ieFolder'); if(is_array($mbox)) { foreach($mbox as $k => $v) { $node->add_node($this->buildTreeNode("$key.$k", $k, $v, $ieId, $nodePath, $isGroup, $ie)); } } return $node; } /** * Totals the unread emails */ function getUnreadCount(&$ie, $mailbox) { global $sugar_config; $unseen = 0; // use cache return $ie->getCacheUnreadCount($mailbox); } /////////////////////////////////////////////////////////////////////////// //// DISPLAY CODE /** * Used exclusively by draft code. Returns Notes and Documents as attachments. * @param array $ret * @return array */ function getDraftAttachments($ret) { global $db; // $ret['uid'] is the draft Email object's GUID $ret['attachments'] = array(); $q = "SELECT id, filename FROM notes WHERE parent_id = '{$ret['uid']}' AND deleted = 0"; $r = $db->query($q); while($a = $db->fetchByAssoc($r)) { $ret['attachments'][$a['id']] = array( 'id' => $a['id'], 'filename' => $a['filename'], ); } return $ret; } function createCopyOfInboundAttachment($ie, $ret, $uid) { global $sugar_config; if ($ie->isPop3Protocol()) { // get the UIDL from database; $cachedUIDL = md5($uid); $cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$cachedUIDL}.php"); } else { $cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$uid}.php"); } if(file_exists($cache)) { include($cache); // profides $cacheFile $metaOut = unserialize($cacheFile['out']); $meta = $metaOut['meta']['email']; if (isset($meta['attachments'])) { $attachmentHtmlData = $meta['attachments']; $actualAttachmentInfo = array(); $this->parseAttachmentInfo($actualAttachmentInfo, $attachmentHtmlData); if (sizeof($actualAttachmentInfo) > 0) { foreach($actualAttachmentInfo as $key => $value) { $info_vars = array(); parse_str($value, $info_vars); $fileName = $info_vars['tempName']; $attachmentid = $info_vars['id']; $guid = create_guid(); $destination = clean_path("{$this->userCacheDir}/{$guid}"); $attachmentFilePath = sugar_cached("modules/Emails/{$ie->id}/attachments/{$attachmentid}"); copy($attachmentFilePath, $destination); $ret['attachments'][$guid] = array(); $ret['attachments'][$guid]['id'] = $guid . $fileName; $ret['attachments'][$guid]['filename'] = $fileName; } // for } // if } // if } // if return $ret; } // fn function parseAttachmentInfo(&$actualAttachmentInfo, $attachmentHtmlData) { $downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&"); while ($downLoadPHP) { $attachmentHtmlData = substr($attachmentHtmlData, $downLoadPHP+30); $final = strpos($attachmentHtmlData, "\">"); $actualAttachmentInfo[] = substr($attachmentHtmlData, 0, $final); $attachmentHtmlData = substr($attachmentHtmlData, $final); $downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&"); } // while } /** * Renders the QuickCreate form from Smarty and returns HTML * @param array $vars request variable global * @param object $email Fetched email object * @param bool $addToAddressBook * @return array */ function getQuickCreateForm($vars, $email, $addToAddressBookButton=false) { require_once("include/EditView/EditView2.php"); global $app_strings; global $mod_strings; global $current_user; global $beanList; global $beanFiles; global $current_language; //Setup the current module languge $mod_strings = return_module_language($current_language, $_REQUEST['qc_module']); $bean = $beanList[$_REQUEST['qc_module']]; $class = $beanFiles[$bean]; require_once($class); $focus = new $bean(); $people = array( 'Contact' ,'Lead' ); $emailAddress = array(); // people if(in_array($bean, $people)) { // lead specific $focus->lead_source = 'Email'; $focus->lead_source_description = trim($email->name); $from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr; if(isset($_REQUEST['sugarEmail']) && !empty($_REQUEST['sugarEmail'])) $from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr_name; $name = explode(" ", trim($from)); $address = trim(array_pop($name)); $address = str_replace(array("<",">","<",">"), "", $address); $emailAddress[] = array( 'email_address' => $address, 'primary_address' => 1, 'invalid_email' => 0, 'opt_out' => 0, 'reply_to_address' => 1 ); $focus->email1 = $address; if(!empty($name)) { $focus->last_name = trim(array_pop($name)); foreach($name as $first) { if(!empty($focus->first_name)) { $focus->first_name .= " "; } $focus->first_name .= trim($first); } } } else { // bugs, cases, tasks $focus->name = trim($email->name); } $focus->description = trim(strip_tags($email->description)); $focus->assigned_user_id = $current_user->id; $EditView = new EditView(); $EditView->ss = new Sugar_Smarty(); //MFH BUG#20283 - checks for custom quickcreate fields $EditView->setup($_REQUEST['qc_module'], $focus, 'custom/modules/'.$focus->module_dir.'/metadata/editviewdefs.php', 'include/EditView/EditView.tpl'); $EditView->process(); $EditView->render(); $EditView->defs['templateMeta']['form']['buttons'] = array( 'email2save' => array( 'id' => 'e2AjaxSave', 'customCode' => '' ), 'email2saveandreply' => array( 'id' => 'e2SaveAndReply', 'customCode' => '' ), 'email2cancel' => array( 'id' => 'e2cancel', 'customCode' => '' ) ); if($addToAddressBookButton) { $EditView->defs['templateMeta']['form']['buttons']['email2saveAddToAddressBook'] = array( 'id' => 'e2addToAddressBook', 'customCode' => '' ); } //Get the module language for javascript if(!is_file(sugar_cached('jsLanguage/') . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js')) { require_once('include/language/jsLanguage.php'); jsLanguage::createModuleStringsCache($_REQUEST['qc_module'], $GLOBALS['current_language']); } $jsLanguage = getVersionedScript("cache/jsLanguage/{$_REQUEST['qc_module']}/{$GLOBALS['current_language']}.js", $GLOBALS['sugar_config']['js_lang_version']); $EditView->view = 'EmailQCView'; $EditView->defs['templateMeta']['form']['headerTpl'] = 'include/EditView/header.tpl'; $EditView->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl'; $meta = array(); $meta['html'] = $jsLanguage . $EditView->display(false, true); $meta['html'] = str_replace("src='".getVersionedPath('include/SugarEmailAddress/SugarEmailAddress.js')."'", '', $meta['html']); $meta['emailAddress'] = $emailAddress; $mod_strings = return_module_language($current_language, 'Emails'); return $meta; } /** * Renders the Import form from Smarty and returns HTML * @param array $vars request variable global * @param object $email Fetched email object * @param bool $addToAddressBook * @return array */ function getImportForm($vars, $email, $formName = 'ImportEditView') { require_once("include/EditView/EditView2.php"); require_once("include/TemplateHandler/TemplateHandler.php"); require_once('include/QuickSearchDefaults.php'); $qsd = new QuickSearchDefaults(); $qsd->setFormName($formName); global $app_strings; global $current_user; global $app_list_strings; $sqs_objects = array( "{$formName}_parent_name" => $qsd->getQSParent(), ); $smarty = new Sugar_Smarty(); $smarty->assign("APP",$app_strings); $smarty->assign('formName',$formName); $showAssignTo = false; if (!isset($vars['showAssignTo']) || $vars['showAssignTo'] == true) { $showAssignTo = true; } // if if ($showAssignTo) { if(empty($email->assigned_user_id) && empty($email->id)) $email->assigned_user_id = $current_user->id; if(empty($email->assigned_name) && empty($email->id)) $email->assigned_user_name = $current_user->user_name; $sqs_objects["{$formName}_assigned_user_name"] = $qsd->getQSUser(); } $smarty->assign("showAssignedTo",$showAssignTo); $showDelete = false; if (!isset($vars['showDelete']) || $vars['showDelete'] == true) { $showDelete = true; } $smarty->assign("showDelete",$showDelete); $smarty->assign("userId",$email->assigned_user_id); $smarty->assign("userName",$email->assigned_user_name); $parent_types = $app_list_strings['record_type_display']; $smarty->assign('parentOptions', get_select_options_with_id($parent_types, $email->parent_type)); $quicksearch_js = ''; $smarty->assign('SQS', $quicksearch_js); $meta = array(); $meta['html'] = $smarty->fetch("modules/Emails/templates/importRelate.tpl"); return $meta; } /** * This function returns the detail view for email in new 2.0 interface * */ function getDetailViewForEmail2($emailId) { require_once('include/DetailView/DetailView.php'); global $app_strings, $app_list_strings; global $mod_strings; $smarty = new Sugar_Smarty(); // SETTING DEFAULTS $focus = new Email(); $focus->retrieve($emailId); $detailView->ss = new Sugar_Smarty(); $detailView = new DetailView(); $title = ""; $offset = 0; if($focus->type == 'out') { $title = getClassicModuleTitle('Emails', array($mod_strings['LBL_SENT_MODULE_NAME'],$focus->name), true); } elseif ($focus->type == 'draft') { $title = getClassicModuleTitle('Emails', array($mod_strings['LBL_LIST_FORM_DRAFTS_TITLE'],$focus->name), true); } elseif($focus->type == 'inbound') { $title = getClassicModuleTitle('Emails', array($mod_strings['LBL_INBOUND_TITLE'],$focus->name), true); } $smarty->assign("emailTitle", $title); // DEFAULT TO TEXT IF NO HTML CONTENT: $html = trim(from_html($focus->description_html)); if(empty($html)) { $smarty->assign('SHOW_PLAINTEXT', 'true'); } else { $smarty->assign('SHOW_PLAINTEXT', 'false'); } //if not empty or set to test (from test campaigns) if (!empty($focus->parent_type) && $focus->parent_type !='test') { $smarty->assign('PARENT_MODULE', $focus->parent_type); $smarty->assign('PARENT_TYPE', $app_list_strings['record_type_display'][$focus->parent_type] . ":"); } global $gridline; $smarty->assign('MOD', $mod_strings); $smarty->assign('APP', $app_strings); $smarty->assign('GRIDLINE', $gridline); $smarty->assign('PRINT_URL', 'index.php?'.$GLOBALS['request_string']); $smarty->assign('ID', $focus->id); $smarty->assign('TYPE', $focus->type); $smarty->assign('PARENT_NAME', $focus->parent_name); $smarty->assign('PARENT_ID', $focus->parent_id); $smarty->assign('NAME', $focus->name); $smarty->assign('ASSIGNED_TO', $focus->assigned_user_name); $smarty->assign('DATE_MODIFIED', $focus->date_modified); $smarty->assign('DATE_ENTERED', $focus->date_entered); $smarty->assign('DATE_START', $focus->date_start); $smarty->assign('TIME_START', $focus->time_start); $smarty->assign('FROM', $focus->from_addr); $smarty->assign('TO', nl2br($focus->to_addrs)); $smarty->assign('CC', nl2br($focus->cc_addrs)); $smarty->assign('BCC', nl2br($focus->bcc_addrs)); $smarty->assign('CREATED_BY', $focus->created_by_name); $smarty->assign('MODIFIED_BY', $focus->modified_by_name); $smarty->assign('DATE_SENT', $focus->date_entered); $smarty->assign('EMAIL_NAME', 'RE: '.$focus->name); $smarty->assign("TAG", $focus->listviewACLHelper()); $smarty->assign("SUGAR_VERSION", $GLOBALS['sugar_version']); $smarty->assign("JS_CUSTOM_VERSION", $GLOBALS['sugar_config']['js_custom_version']); if(!empty($focus->reply_to_email)) { $replyTo = " ".$mod_strings['LBL_REPLY_TO_NAME']." ".$focus->reply_to_addr." "; $smarty->assign("REPLY_TO", $replyTo); } /////////////////////////////////////////////////////////////////////////////// //// JAVASCRIPT VARS $jsVars = ''; $jsVars .= "var showRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL']}';"; $jsVars .= "var hideRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL_HIDE']}';"; $smarty->assign("JS_VARS", $jsVars); /////////////////////////////////////////////////////////////////////////////// //// NOTES (attachements, etc.) /////////////////////////////////////////////////////////////////////////////// $note = new Note(); $where = "notes.parent_id='{$focus->id}'"; //take in account if this is from campaign and the template id is stored in the macros. if(isset($macro_values) && isset($macro_values['email_template_id'])){ $where = "notes.parent_id='{$macro_values['email_template_id']}'"; } $notes_list = $note->get_full_list("notes.name", $where, true); if(! isset($notes_list)) { $notes_list = array(); } $attachments = ''; for($i=0; $iid}&type=Notes\">".$the_note->name."
"; $focus->cid2Link($the_note->id, $the_note->file_mime_type); } $smarty->assign('DESCRIPTION', nl2br($focus->description)); $smarty->assign('DESCRIPTION_HTML', from_html($focus->description_html)); $smarty->assign("ATTACHMENTS", $attachments); /////////////////////////////////////////////////////////////////////////////// //// SUBPANELS /////////////////////////////////////////////////////////////////////////////// $show_subpanels = true; if ($show_subpanels) { require_once('include/SubPanel/SubPanelTiles.php'); $subpanel = new SubPanelTiles($focus, 'Emails'); $smarty->assign("SUBPANEL", $subpanel->display()); } $meta['html'] = $smarty->fetch("modules/Emails/templates/emailDetailView.tpl"); return $meta; } // fn /** * Sets the "read" flag in the overview cache */ function setReadFlag($ieId, $mbox, $uid) { $this->markEmails('read', $ieId, $mbox, $uid); } /** * Marks emails with the passed flag type. This will be applied to local * cache files as well as remote emails. * @param string $type Flag type * @param string $ieId * @param string $folder IMAP folder structure or SugarFolder GUID * @param string $uids Comma sep list of UIDs or GUIDs */ function markEmails($type, $ieId, $folder, $uids) { global $app_strings; $uids = $this->_cleanUIDList($uids); $exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); if(strpos($folder, 'sugar::') !== false) { // dealing with a sugar email object, uids are GUIDs foreach($exUids as $id) { $email = new Email(); $email->retrieve($id); switch($type) { case "unread": $email->status = 'unread'; $email->save(); break; case "read": $email->status = 'read'; $email->save(); break; case "deleted": $email->delete(); break; case "flagged": $email->flagged = 1; $email->save(); break; case "unflagged": $email->flagged = 0; $email->save(); break; } } } else { /* dealing with IMAP email, uids are IMAP uids */ global $ie; // provided by EmailUIAjax.php if(empty($ie)) { $ie = new InboundEmail(); } $ie->retrieve($ieId); $ie->mailbox = $folder; $ie->connectMailserver(); // mark cache files if($type == 'deleted') { $ie->deleteMessageOnMailServer($uids); $ie->deleteMessageFromCache($uids); } else { $overviews = $ie->getCacheValueForUIDs($ie->mailbox, $exUids); $manipulated = array(); foreach($overviews['retArr'] as $k => $overview) { if(in_array($overview->uid, $exUids)) { switch($type) { case "unread": $overview->seen = 0; break; case "read": $overview->seen = 1; break; case "flagged": $overview->flagged = 1; break; case "unflagged": $overview->flagged = 0; break; } $manipulated[] = $overview; } } if(!empty($manipulated)) { $ie->setCacheValue($ie->mailbox, array(), $manipulated); /* now mark emails on email server */ $ie->markEmails(implode(",", explode($app_strings['LBL_EMAIL_DELIMITER'], $uids)), $type); } } // end not type == deleted } } function doAssignment($distributeMethod, $ieid, $folder, $uids, $users) { global $app_strings; $users = explode(",", $users); $emailIds = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); $out = ""; if($folder != 'sugar::Emails') { $emailIds = array(); $uids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); $ie = new InboundEmail(); $ie->retrieve($ieid); $messageIndex = 1; // dealing with an inbound email data so we need to import an email and then foreach($uids as $uid) { $ie->mailbox = $folder; $ie->connectMailserver(); $msgNo = $uid; if (!$ie->isPop3Protocol()) { $msgNo = imap_msgno($ie->conn, $uid); } else { $msgNo = $ie->getCorrectMessageNoForPop3($uid); } if(!empty($msgNo)) { if ($ie->importOneEmail($msgNo, $uid)) { $emailIds[] = $ie->email->id; $ie->deleteMessageOnMailServer($uid); //$ie->retrieve($ieid); //$ie->connectMailserver(); $ie->mailbox = $folder; $ie->deleteMessageFromCache(($uids[] = $uid)); } else { $out = $out . "Message No : " . $messageIndex . " failed. Reason : Message already imported \r\n"; } } $messageIndex++; } // for } // if if (count($emailIds) > 0) { $this->doDistributionWithMethod($users, $emailIds, $distributeMethod); } // if return $out; } // fn /** * get team id and team set id from request * @return array */ function getTeams() { } function doDistributionWithMethod($users, $emailIds, $distributionMethod) { // we have users and the items to distribute if($distributionMethod == 'roundRobin') { $this->distRoundRobin($users, $emailIds); } elseif($distributionMethod == 'leastBusy') { $this->distLeastBusy($users, $emailIds); } elseif($distributionMethod == 'direct') { if(count($users) > 1) { // only 1 user allowed in direct assignment $error = 1; } else { $user = $users[0]; $this->distDirect($user, $emailIds); } // else } // elseif } // fn /** * distributes emails to users on Round Robin basis * @param $userIds array of users to dist to * @param $mailIds array of email ids to push on those users * @return boolean true on success */ function distRoundRobin($userIds, $mailIds) { // check if we have a 'lastRobin' $lastRobin = $userIds[0]; foreach($mailIds as $k => $mailId) { $userIdsKeys = array_flip($userIds); // now keys are values $thisRobinKey = $userIdsKeys[$lastRobin] + 1; if(!empty($userIds[$thisRobinKey])) { $thisRobin = $userIds[$thisRobinKey]; $lastRobin = $userIds[$thisRobinKey]; } else { $thisRobin = $userIds[0]; $lastRobin = $userIds[0]; } $email = new Email(); $email->retrieve($mailId); $email->assigned_user_id = $thisRobin; $email->status = 'unread'; $email->save(); } return true; } /** * distributes emails to users on Least Busy basis * @param $userIds array of users to dist to * @param $mailIds array of email ids to push on those users * @return boolean true on success */ function distLeastBusy($userIds, $mailIds) { foreach($mailIds as $k => $mailId) { $email = new Email(); $email->retrieve($mailId); foreach($userIds as $k => $id) { $r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '.$id.' AND status = 'unread'"); $a = $this->db->fetchByAssoc($r); $counts[$id] = $a['c']; } asort($counts); // lowest to highest $countsKeys = array_flip($counts); // keys now the 'count of items' $leastBusy = array_shift($countsKeys); // user id of lowest item count $email->assigned_user_id = $leastBusy; $email->status = 'unread'; $email->save(); } return true; } /** * distributes emails to 1 user * @param $user users to dist to * @param $mailIds array of email ids to push * @return boolean true on success */ function distDirect($user, $mailIds) { foreach($mailIds as $k => $mailId) { $email = new Email(); $email->retrieve($mailId); $email->assigned_user_id = $user; $email->status = 'unread'; $email->save(); } return true; } function getAssignedEmailsCountForUsers($userIds) { $counts = array(); foreach($userIds as $id) { $r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '$id' AND status = 'unread'"); $a = $this->db->fetchByAssoc($r); $counts[$id] = $a['c']; } // foreach return $counts; } // fn function getLastRobin($ie) { $lastRobin = ""; if($this->validCacheFileExists($ie->id, 'folders', "robin.cache.php")) { $lastRobin = $this->getCacheValue($ie->id, 'folders', "robin.cache.php", 'robin'); } // if return $lastRobin; } // fn function setLastRobin($ie, $lastRobin) { global $sugar_config; $cacheFolderPath = sugar_cached("modules/Emails/{$ie->id}/folders"); if (!file_exists($cacheFolderPath)) { mkdir_recursive($cacheFolderPath); } $this->writeCacheFile('robin', $lastRobin, $ie->id, 'folders', "robin.cache.php"); } // fn /** * returns the metadata defining a single email message for display. Uses cache file if it exists * @return array */ function getSingleMessage($ie) { global $timedate; global $app_strings,$mod_strings; $ie->retrieve($_REQUEST['ieId']); $noCache = true; $ie->mailbox = $_REQUEST['mbox']; $filename = $_REQUEST['mbox'].$_REQUEST['uid'].".php"; $md5uidl = ""; if ($ie->isPop3Protocol()) { $md5uidl = md5($_REQUEST['uid']); $filename = $_REQUEST['mbox'].$md5uidl.".php"; } // if if($this->validCacheFileExists($_REQUEST['ieId'], 'messages', $filename)) { $out = $this->getCacheValue($_REQUEST['ieId'], 'messages', $filename, 'out'); $noCache = false; // something fubar'd the cache? if(empty($out['meta']['email']['name']) && empty($out['meta']['email']['description'])) { $noCache = true; } else { // When sending data from cache, convert date into users preffered format $dateTimeInGMTFormat = $out['meta']['email']['date_start']; $out['meta']['email']['date_start'] = $timedate->to_display_date_time($dateTimeInGMTFormat); } // else } if($noCache) { $writeToCacheFile = true; if ($ie->isPop3Protocol()) { $status = $ie->setEmailForDisplay($_REQUEST['uid'], true, true, true); } else { $status = $ie->setEmailForDisplay($_REQUEST['uid'], false, true, true); } $out = $ie->displayOneEmail($_REQUEST['uid'], $_REQUEST['mbox']); // modify the out object to store date in GMT format on the local cache file $dateTimeInUserFormat = $out['meta']['email']['date_start']; $out['meta']['email']['date_start'] = $timedate->to_db($dateTimeInUserFormat); if ($status == 'error') { $writeToCacheFile = false; } if ($writeToCacheFile) { if ($ie->isPop3Protocol()) { $this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$md5uidl}.php"); } else { $this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$_REQUEST['uid']}.php"); } // else // restore date in the users preferred format to be send on to UI for diaply $out['meta']['email']['date_start'] = $dateTimeInUserFormat; } // if } $out['meta']['email']['toaddrs'] = $this->generateExpandableAddrs($out['meta']['email']['toaddrs']); if(!empty($out['meta']['email']['cc_addrs'])) { $ccs = $this->generateExpandableAddrs($out['meta']['email']['cc_addrs']); $out['meta']['cc'] = << {$app_strings['LBL_EMAIL_CC']}: {$ccs} eoq; } if(empty($out['meta']['email']['description'])) $out['meta']['email']['description'] = $mod_strings['LBL_EMPTY_EMAIL_BODY']; if($noCache) { $GLOBALS['log']->debug("EMAILUI: getSingleMessage() NOT using cache file"); } else { $GLOBALS['log']->debug("EMAILUI: getSingleMessage() using cache file [ ".$_REQUEST['mbox'].$_REQUEST['uid'].".php ]"); } $this->setReadFlag($_REQUEST['ieId'], $_REQUEST['mbox'], $_REQUEST['uid']); return $out; } /** * Returns the HTML for a list of emails in a given folder * @param GUID $ieId GUID to InboundEmail instance * @param string $mbox Mailbox path name in dot notation * @param int $folderListCacheOffset Seconds for valid cache file * @return string HTML render of list. */ function getListEmails($ieId, $mbox, $folderListCacheOffset, $forceRefresh='false') { global $sugar_config; $ie = new InboundEmail(); $ie->retrieve($ieId); $list = $ie->displayFolderContents($mbox, $forceRefresh); return $list; } /** * Returns the templatized compose screen. Used by reply, forwards and draft status messages. * @param object email Email bean in focus */ function displayComposeEmail($email) { global $locale; global $current_user; $ea = new SugarEmailAddress(); if(!empty($email)) { $email->cids2Links(); $description = (empty($email->description_html)) ? $email->description : $email->description_html; } //Get the most complete address list availible for this email $addresses = array('toAddresses' => 'to', 'ccAddresses' => 'cc', 'bccAddresses' => 'bcc'); foreach($addresses as $var => $type) { $$var = ""; foreach (array("{$type}_addrs_names", "{$type}addrs", "{$type}_addrs") as $emailVar) { if (!empty($email->$emailVar)) { $$var = $email->$emailVar; break; } } } $ret = array(); $ret['type'] = $email->type; $ret['name'] = $email->name; $ret['description'] = $description; $ret['from'] = (isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'forward') ? "" : $email->from_addr; $ret['to'] = from_html($toAddresses); $ret['uid'] = $email->id; $ret['parent_name'] = $email->parent_name; $ret['parent_type'] = $email->parent_type; $ret['parent_id'] = $email->parent_id; // reply all if(isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'replyAll') { $ret['cc'] = from_html($ccAddresses); $ret['bcc'] = $bccAddresses; $userEmails = array(); $userEmailsMeta = $ea->getAddressesByGUID($current_user->id, 'Users'); foreach($userEmailsMeta as $emailMeta) { $userEmails[] = from_html(strtolower(trim($emailMeta['email_address']))); } $userEmails[] = from_html(strtolower(trim($email->from_addr))); $ret['cc'] = from_html($email->cc_addrs); $toAddresses = from_html($toAddresses); $to = str_replace($this->addressSeparators, "::", $toAddresses); $exTo = explode("::", $to); if(is_array($exTo)) { foreach($exTo as $addr) { $addr = strtolower(trim($addr)); if(!in_array($addr, $userEmails)) { if(!empty($ret['cc'])) { $ret['cc'] = $ret['cc'].", "; } $ret['cc'] = $ret['cc'].trim($addr); } } } elseif(!empty($exTo)) { $exTo = trim($exTo); if(!in_array($exTo, $userEmails)) { $ret['cc'] = $ret['cc'].", ".$exTo; } } } return $ret; } /** * Formats email body on reply/forward * @param object email Email object in focus * @param string type * @return object email */ function handleReplyType($email, $type) { global $mod_strings; $GLOBALS['log']->debug("****At Handle Reply Type: $type"); switch($type) { case "reply": case "replyAll": $header = $email->getReplyHeader(); if(!preg_match('/^(re:)+/i', $email->name)) { $email->name = "{$mod_strings['LBL_RE']} {$email->name}"; } if ($type == "reply") { $email->cc_addrs = ""; if (!empty($email->reply_to_addr)) { $email->from_addr = $email->reply_to_addr; } // if } else { if (!empty($email->reply_to_addr)) { $email->to_addrs = $email->to_addrs . "," . $email->reply_to_addr; } // if } // else break; case "forward": $header = $email->getForwardHeader(); if(!preg_match('/^(fw:)+/i', $email->name)) { $email->name = "{$mod_strings['LBL_FW']} {$email->name}"; } $email->cc_addrs = ""; break; case "replyCase": $GLOBALS['log']->debug("EMAILUI: At reply case"); $header = $email->getReplyHeader(); $myCase = new aCase(); $myCase->retrieve($email->parent_id); $myCaseMacro = $myCase->getEmailSubjectMacro(); $email->parent_name = $myCase->name; $GLOBALS['log']->debug("****Case # : {$myCase->case_number} macro: $myCaseMacro"); if(!strpos($email->name, str_replace('%1',$myCase->case_number,$myCaseMacro))) { $GLOBALS['log']->debug("Replacing"); $email->name = str_replace('%1',$myCase->case_number,$myCaseMacro) . ' '. $email->name; } $email->name = "{$mod_strings['LBL_RE']} {$email->name}"; break; } $html = trim($email->description_html); $plain = trim($email->description); $desc = (!empty($html)) ? $html : $plain; $email->description = $header.$email->quoteHtmlEmailForNewEmailUI($desc); return $email; } /////////////////////////////////////////////////////////////////////////// //// PRIVATE HELPERS /** * Generates a UNION query to get one list of users, contacts, leads, and * prospects; used specifically for the addressBook */ function _getPeopleUnionQuery($whereArr , $person) { global $current_user , $app_strings; global $db; if(!isset($person) || $person === 'LBL_DROPDOWN_LIST_ALL'){ $peopleTables = array("users", "contacts", "leads", "prospects", "accounts" ); }else{ $peopleTables = array($person); } $q = ''; $whereAdd = ""; foreach($whereArr as $column => $clause) { if(!empty($whereAdd)) { $whereAdd .= " AND "; } $clause = $current_user->db->quote($clause); $whereAdd .= "{$column} LIKE '{$clause}%'"; } foreach($peopleTables as $table) { $module = ucfirst($table); $class = substr($module, 0, strlen($module) - 1); require_once("modules/{$module}/{$class}.php"); $person = new $class(); if (!$person->ACLAccess('list')) { continue; } // if $where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id <> '{$current_user->id}')"; if (ACLController::requireOwner($module, 'list')) { $where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')"; } // if if(!empty($whereAdd)) { $where .= " AND ({$whereAdd})"; } if ($person === 'accounts') { $t = "SELECT {$table}.id, '' first_name, {$table}.name, eabr.primary_address, ea.email_address, '{$module}' module "; } else { $t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module "; } $t .= "FROM {$table} "; $t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) "; $t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) "; $t .= " WHERE {$where}"; if(!empty($q)) { $q .= "\n UNION ALL \n"; } $q .= "({$t})"; } $countq = "SELECT count(people.id) c from ($q) people"; $q .= "ORDER BY last_name"; return array('query' => $q, 'countQuery' => $countq); } /** * get emails of related bean for a given bean id * @param $beanType * @param $condition array of conditions inclued bean id * @return array('query' => $q, 'countQuery' => $countq); */ function getRelatedEmail($beanType, $whereArr, $relatedBeanInfoArr = ''){ global $beanList, $current_user, $app_strings, $db; $finalQuery = ''; $searchBeans = null; if($beanType === 'LBL_DROPDOWN_LIST_ALL') $searchBeans = array("users", "contacts", "leads", "prospects", "accounts" ); if ($relatedBeanInfoArr == '' || empty($relatedBeanInfoArr['related_bean_type']) ) { if ($searchBeans != null) { $q = array(); foreach ($searchBeans as $searchBean) { $searchq = $this->findEmailFromBeanIds('', $searchBean, $whereArr); if(!empty($searchq)) { $q[] = "($searchq)"; } } if (!empty($q)) $finalQuery .= implode("\n UNION ALL \n", $q); } else $finalQuery = $this->findEmailFromBeanIds('', $beanType, $whereArr); } else { $class = $beanList[$relatedBeanInfoArr['related_bean_type']]; $focus = new $class(); $focus->retrieve($relatedBeanInfoArr['related_bean_id']); if ($searchBeans != null) { $q = array(); foreach ($searchBeans as $searchBean) { if ($focus->load_relationship($searchBean)) { $data = $focus->$searchBean->get(); if (count($data) != 0) $q[] = '('.$this->findEmailFromBeanIds($data, $searchBean, $whereArr).')'; } } if (!empty($q)) $finalQuery .= implode("\n UNION ALL \n", $q); } else { if ($focus->load_relationship($beanType)) { $data = $focus->$beanType->get(); if (count($data) != 0) $finalQuery = $this->findEmailFromBeanIds($data, $beanType, $whereArr); } } } $countq = "SELECT count(people.id) c from ($finalQuery) people"; return array('query' => $finalQuery, 'countQuery' => $countq); } function findEmailFromBeanIds($beanIds, $beanType, $whereArr) { global $current_user; $q = ''; $whereAdd = ""; $relatedIDs = ''; if ($beanIds != '') { foreach ($beanIds as $key => $value) { $beanIds[$key] = '\''.$value.'\''; } $relatedIDs = implode(',', $beanIds); } if ($beanType == 'accounts') { if (isset($whereArr['first_name'])) { $whereArr['name'] = $whereArr['first_name']; } unset($whereArr['last_name']); unset($whereArr['first_name']); } foreach($whereArr as $column => $clause) { if(!empty($whereAdd)) { $whereAdd .= " OR "; } $clause = $current_user->db->quote($clause); $whereAdd .= "{$column} LIKE '{$clause}%'"; } $table = $beanType; $module = ucfirst($table); $class = substr($module, 0, strlen($module) - 1); require_once("modules/{$module}/{$class}.php"); $person = new $class(); if ($person->ACLAccess('list')) { if ($relatedIDs != '') { $where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id in ($relatedIDs))"; } else { $where = "({$table}.deleted = 0 AND eabr.primary_address = 1)"; } if (ACLController::requireOwner($module, 'list')) { $where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')"; } // if if(!empty($whereAdd)) { $where .= " AND ({$whereAdd})"; } if ($beanType === 'accounts') { $t = "SELECT {$table}.id, '' first_name, {$table}.name last_name, eabr.primary_address, ea.email_address, '{$module}' module "; } else { $t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module "; } $t .= "FROM {$table} "; $t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) "; $t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) "; $t .= " WHERE {$where}"; } // if return $t; } /** * Cleans UID lists * @param mixed $uids * @param bool $returnString False will return an array * @return mixed */ function _cleanUIDList($uids, $returnString=false) { global $app_strings; $GLOBALS['log']->debug("_cleanUIDList: before - [ {$uids} ]"); if(!is_array($uids)) { $returnString = true; $exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); $uids = $exUids; } $cleanUids = array(); foreach($uids as $uid) { $cleanUids[$uid] = $uid; } sort($cleanUids); if($returnString) { $cleanImplode = implode($app_strings['LBL_EMAIL_DELIMITER'], $cleanUids); $GLOBALS['log']->debug("_cleanUIDList: after - [ {$cleanImplode} ]"); return $cleanImplode; } return $cleanUids; } /** * Creates defaults for the User * @param object $user User in focus */ function preflightUser(&$user) { global $mod_strings; $goodToGo = $user->getPreference("email2Preflight", "Emails"); $q = "SELECT count(*) count FROM folders f where f.created_by = '{$user->id}' AND f.folder_type = 'inbound' AND f.deleted = 0"; $r = $user->db->query($q); $a = $user->db->fetchByAssoc($r); if($a['count'] < 1) { require_once("include/SugarFolders/SugarFolders.php"); // My Emails $folder = new SugarFolder(); $folder->new_with_id = true; $folder->id = create_guid(); $folder->name = $mod_strings['LNK_MY_INBOX']; $folder->has_child = 1; $folder->created_by = $user->id; $folder->modified_by = $user->id; $folder->is_dynamic = 1; $folder->folder_type = "inbound"; $folder->dynamic_query = $this->generateDynamicFolderQuery('inbound', $user->id); $folder->save(); // My Drafts $drafts = new SugarFolder(); $drafts->name = $mod_strings['LNK_MY_DRAFTS']; $drafts->has_child = 0; $drafts->parent_folder = $folder->id; $drafts->created_by = $user->id; $drafts->modified_by = $user->id; $drafts->is_dynamic = 1; $drafts->folder_type = "draft"; $drafts->dynamic_query = $this->generateDynamicFolderQuery('draft', $user->id); $drafts->save(); // Sent Emails $archived = new SugarFolder(); $archived->name = $mod_strings['LNK_SENT_EMAIL_LIST']; $archived->has_child = 0; $archived->parent_folder = $folder->id; $archived->created_by = $user->id; $archived->modified_by = $user->id; $archived->is_dynamic = 1; $archived->folder_type = "sent"; $archived->dynamic_query = $this->generateDynamicFolderQuery('sent', $user->id); $archived->save(); // set flag to show that this was run $user->setPreference("email2Preflight", true, 1, "Emails"); } } /** * Parses the core dynamic folder query * @param string $type 'inbound', 'draft', etc. * @param string $userId * @return string */ function generateDynamicFolderQuery($type, $userId) { $q = $this->coreDynamicFolderQuery; $status = $type; if($type == "sent") { $type = "out"; } $replacee = array("::TYPE::", "::STATUS::", "::USER_ID::"); $replacer = array($type, $status, $userId); $ret = str_replace($replacee, $replacer, $q); if($type == 'inbound') { $ret .= " AND status NOT IN ('sent', 'archived', 'draft') AND type NOT IN ('out', 'archived', 'draft')"; } else { $ret .= " AND status NOT IN ('archived') AND type NOT IN ('archived')"; } return $ret; } /** * Preps the User's cache dir */ function preflightUserCache() { $path = clean_path($this->userCacheDir); if(!file_exists($this->userCacheDir)) mkdir_recursive($path); $files = findAllFiles($path, array()); foreach($files as $file) { unlink($file); } } function clearInboundAccountCache($ieId) { global $sugar_config; $cacheRoot = sugar_cached("modules/Emails/{$ieId}"); $files = findAllFiles($cacheRoot."/messages/", array()); foreach($files as $file) { unlink($file); } // fn $files = findAllFiles($cacheRoot."/attachments/", array()); foreach($files as $file) { unlink($file); } // for } // fn /** * returns an array of EmailTemplates that the user has access to for the compose email screen * @return array */ function getEmailTemplatesArray() { global $app_strings; if(ACLController::checkAccess('EmailTemplates', 'list', true) && ACLController::checkAccess('EmailTemplates', 'view', true)) { $et = new EmailTemplate(); $etResult = $et->db->query($et->create_new_list_query('','',array(),array(),'')); $email_templates_arr = array('' => $app_strings['LBL_NONE']); while($etA = $et->db->fetchByAssoc($etResult)) { $email_templates_arr[$etA['id']] = $etA['name']; } } else { $email_templates_arr = array('' => $app_strings['LBL_NONE']); } return $email_templates_arr; } function getFromAccountsArray($ie) { global $current_user; global $app_strings; $ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id); $ieAccountsFrom= array(); $oe = new OutboundEmail(); $system = $oe->getSystemMailerSettings(); $ret = $current_user->getUsersNameAndEmail(); $ret['name'] = from_html($ret['name']); $useMyAccountString = true; if(empty($ret['email'])) { $systemReturn = $current_user->getSystemDefaultNameAndEmail(); $ret['email'] = $systemReturn['email']; $ret['name'] = from_html($systemReturn['name']); $useMyAccountString = false; } // if $myAccountString = ''; if ($useMyAccountString) { $myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}"; } // if //Check to make sure that the user has set the associated inbound email acount -> outbound acount is active. $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); $sf = new SugarFolder(); $groupSubs = $sf->getSubscriptions($current_user); foreach($ieAccountsFull as $k => $v) { $personalSelected = (!empty($showFolders) && in_array($v->id, $showFolders)); $allowOutboundGroupUsage = $v->get_stored_options('allow_outbound_group_usage',FALSE); $groupSelected = ( in_array($v->groupfolder_id, $groupSubs) && $allowOutboundGroupUsage); $selected = ( $personalSelected || $groupSelected ); if(!$selected) { $GLOBALS['log']->debug("Inbound Email {$v->name}, not selected and will not be available for selection within compose UI."); continue; } $name = $v->get_stored_options('from_name'); $addr = $v->get_stored_options('from_addr'); if ($name != null && $addr != null) { $name = from_html($name); if (!$v->is_personal) { $ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}"); } else { $ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr})"); } // else } // if } // foreach $userSystemOverride = $oe->getUsersMailerForSystemOverride($current_user->id); //Substitute in the users system override if its available. if($userSystemOverride != null) $system = $userSystemOverride; if( !empty($system->mail_smtpserver) ) { $admin = new Administration(); $admin->retrieveSettings(); //retrieve all admin settings. $ieAccountsFrom[] = array("value" => $system->id, "text" => "{$ret['name']} ({$ret['email']}){$myAccountString}"); } return $ieAccountsFrom; } // fn /** * This function will return all the accounts this user has access to based on the * match of the emailId passed in as a parameter * * @param unknown_type $ie * @return unknown */ function getFromAllAccountsArray($ie, $ret) { global $current_user; global $app_strings; $ret['fromAccounts'] = array(); if (!isset($ret['to']) && !empty($ret['from'])) { $ret['fromAccounts']['status'] = false; return $ret; } $ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id); $foundInPersonalAccounts = false; $foundInGroupAccounts = false; $foundInSystemAccounts = false; //$toArray = array(); if ($ret['type'] == "draft") { $toArray = explode(",", $ret['from']); } else { $toArray = $ie->email->email2ParseAddressesForAddressesOnly($ret['to']); } // else foreach($ieAccountsFull as $k => $v) { $storedOptions = unserialize(base64_decode($v->stored_options)); if ( array_search_insensitive($storedOptions['from_addr'], $toArray)) { if ($v->is_personal) { $foundInPersonalAccounts = true; break; } else { $foundInGroupAccounts = true; } // else } // if } // foreach $oe = new OutboundEmail(); $system = $oe->getSystemMailerSettings(); $return = $current_user->getUsersNameAndEmail(); $return['name'] = from_html($return['name']); $useMyAccountString = true; if(empty($return['email'])) { $systemReturn = $current_user->getSystemDefaultNameAndEmail(); $return['email'] = $systemReturn['email']; $return['name'] = from_html($systemReturn['name']); $useMyAccountString = false; } // if $myAccountString = ''; if ($useMyAccountString) { $myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}"; } // if if(!empty($system->id)) { $admin = new Administration(); $admin->retrieveSettings(); //retrieve all admin settings. if (in_array(trim($return['email']), $toArray)) { $foundInSystemAccounts = true; } // if } // if if (!$foundInPersonalAccounts && !$foundInGroupAccounts && !$foundInSystemAccounts) { $ret['fromAccounts']['status'] = false; return $ret; } // if $ieAccountsFrom= array(); foreach($ieAccountsFull as $k => $v) { $storedOptions = unserialize(base64_decode($v->stored_options)); $storedOptionsName = from_html($storedOptions['from_name']); $selected = false; if (array_search_insensitive($storedOptions['from_addr'], $toArray)) { //if ($ret['to'] == $storedOptions['from_addr']) { $selected = true; } // if if ($foundInPersonalAccounts) { if ($v->is_personal) { $ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']})"); } // if } else { $ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}"); } // else } // foreach if(!empty($system->id)) { if (!$foundInPersonalAccounts && !$foundInGroupAccounts && $foundInSystemAccounts) { $ieAccountsFrom[] = array("value" => $system->id, "selected" => true, "text" => "{$return['name']} ({$return['email']}){$myAccountString}"); } else { $ieAccountsFrom[] = array("value" => $system->id, "text" => "{$return['name']} ({$return['email']}){$myAccountString}"); } // else } // if $ret['fromAccounts']['status'] = ($foundInPersonalAccounts || $foundInGroupAccounts || $foundInSystemAccounts) ? true : false; $ret['fromAccounts']['data'] = $ieAccountsFrom; return $ret; } // fn /** * takes an array and creates XML * @param array Array to convert * @param string Name to wrap highest level items in array * @return string XML */ function arrayToXML($a, $paramName) { if(!is_array($a)) return ''; $bad = array("<",">","'",'"',"&"); $good = array("<", ">", "'", ""","&"); $ret = ""; for($i=0; $i $v) { $ret .= "\n\t<{$k}>".str_replace($bad, $good, $v).""; } $ret .= "\n"; } return $ret; } /** * Re-used option getter for Show Accounts multiselect pane */ function getShowAccountsOptions(&$ie) { global $current_user; global $app_strings; global $mod_strings; $ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id); $ieAccountsShowOptionsMeta = array(); $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); $defaultIEAccount = $ie->getUsersDefaultOutboundServerId($current_user); foreach($ieAccountsFull as $k => $v) { $selected = (!empty($showFolders) && in_array($v->id, $showFolders)) ? true : false; $default = ($defaultIEAccount == $v->id) ? TRUE : FALSE; $has_groupfolder = !empty($v->groupfolder_id) ? TRUE : FALSE; $type = ($v->is_personal) ? $mod_strings['LBL_MAILBOX_TYPE_PERSONAL'] : $mod_strings['LBL_MAILBOX_TYPE_GROUP']; $ieAccountsShowOptionsMeta[] = array("id" => $v->id, "name" => $v->name, 'is_active' => $selected, 'server_url' => $v->server_url, 'is_group' => !$v->is_personal,'group_id' => $v->group_id, 'is_default' => $default, 'has_groupfolder' => $has_groupfolder,'type' => $type ); } //Retrieve the grou folders $f = new SugarFolder(); $groupFolders = $f->getGroupFoldersForSettings($current_user); foreach ($groupFolders as $singleGroup) { //Retrieve the related IE accounts. $relatedIEAccounts = $ie->retrieveByGroupFolderId($singleGroup['id']); if(count($relatedIEAccounts) == 0) $server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS_EMPTY']; else if(count($relatedIEAccounts) == 1) { if($relatedIEAccounts[0]->status != 'Active' || $relatedIEAccounts[0]->mailbox_type == 'bounce') continue; $server_url = $relatedIEAccounts[0]->server_url; } else $server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS']; $type = $mod_strings['LBL_MAILBOX_TYPE_GROUP_FOLDER']; $ieAccountsShowOptionsMeta[] = array("id" => $singleGroup['id'], "name" => $singleGroup['origName'], 'is_active' => $singleGroup['selected'], 'server_url' => $server_url, 'is_group' => true,'group_id' => $singleGroup['id'], 'is_default' => FALSE, 'has_groupfolder' => true,'type' => $type); } return $ieAccountsShowOptionsMeta; } function getShowAccountsOptionsForSearch(&$ie) { global $current_user; global $app_strings; $ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id); //$ieAccountsShowOptions = "\n"; $ieAccountsShowOptionsMeta = array(); $ieAccountsShowOptionsMeta[] = array("value" => "", "text" => $app_strings['LBL_NONE'], 'selected' => ''); $showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); foreach($ieAccountsFull as $k => $v) { if(!in_array($v->id, $showFolders)) { continue; } $group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : ""; $ieAccountsShowOptionsMeta[] = array("value" => $v->id, "text" => $group.$v->name, 'protocol' => $v->protocol); } return $ieAccountsShowOptionsMeta; } /** * Formats a display message on successful async call * @param string $type Type of message to display */ function displaySuccessMessage($type) { global $app_strings; switch($type) { case "delete": $message = $app_strings['LBL_EMAIL_DELETE_SUCCESS']; break; default: $message = "NOOP: invalid type"; break; } $this->smarty->assign('app_strings', $app_strings); $this->smarty->assign('message', $message); echo $this->smarty->fetch("modules/Emails/templates/successMessage.tpl"); } /** * Validates existence and expiration of a cache file * @param string $ieId * @param string $type Type of cache file: folders, messages, etc. * @param string $file The cachefile name * @param int refreshOffset Refresh time in secs. * @return mixed. */ function validCacheFileExists($ieId, $type, $file, $refreshOffset=-1) { global $sugar_config; if($refreshOffset == -1) { $refreshOffset = $this->cacheTimeouts[$type]; // use defaults } $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); if(file_exists($cacheFilePath)) { return true; } return false; } /** * retrieves the cached value * @param string $ieId * @param string $type Type of cache file: folders, messages, etc. * @param string $file The cachefile name * @param string $key name of cache value * @return mixed */ function getCacheValue($ieId, $type, $file, $key) { global $sugar_config; $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { include($cacheFilePath); // provides $cacheFile if(isset($cacheFile[$key])) { $ret = unserialize($cacheFile[$key]); return $ret; } } else { $GLOBALS['log']->debug("EMAILUI: cache file not found [ {$cacheFilePath} ] - creating blank cache file"); $this->writeCacheFile('retArr', array(), $ieId, $type, $file); } return null; } /** * retrieves the cache file last touched time * @param string $ieId * @param string $type Type of cache file: folders, messages, etc. * @param string $file The cachefile name * @return string */ function getCacheTimestamp($ieId, $type, $file) { global $sugar_config; $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { include($cacheFilePath); // provides $cacheFile['timestamp'] if(isset($cacheFile['timestamp'])) { $GLOBALS['log']->debug("EMAILUI: found timestamp [ {$cacheFile['timestamp']} ]"); return $cacheFile['timestamp']; } } return ''; } /** * Updates the timestamp for a cache file - usually to mark a "check email" * process * @param string $ieId * @param string $type Type of cache file: folders, messages, etc. * @param string $file The cachefile name */ function setCacheTimestamp($ieId, $type, $file) { global $sugar_config; $cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); $cacheFile = array(); if(file_exists($cacheFilePath)) { include($cacheFilePath); // provides $cacheFile['timestamp'] if(isset($cacheFile['timestamp'])) { $cacheFile['timestamp'] = strtotime('now'); $GLOBALS['log']->debug("EMAILUI: setting updated timestamp [ {$cacheFile['timestamp']} ]"); return $this->_writeCacheFile($cacheFile, $cacheFilePath); } } } /** * Writes caches to flat file in cache dir. * @param string $key Key to the main cache entry (not timestamp) * @param mixed $var Variable to be cached * @param string $ieId I-E focus ID * @param string $type Folder in cache * @param string $file Cache file name */ function writeCacheFile($key, $var, $ieId, $type, $file) { global $sugar_config; $the_file = sugar_cached("/modules/Emails/{$ieId}/{$type}/{$file}"); $timestamp = strtotime('now'); $array = array(); $array['timestamp'] = $timestamp; $array[$key] = serialize($var); // serialized since varexport_helper() can't handle PHP objects return $this->_writeCacheFile($array, $the_file); } /** * Performs the actual file write. Abstracted from writeCacheFile() for * flexibility * @param array $array The array to write to the cache * @param string $file Full path (relative) with cache file name * @return bool */ function _writeCacheFile($array, $file) { global $sugar_config; $arrayString = var_export_helper($array); $date = date("r"); $the_string =<< eoq; if($fh = @sugar_fopen($file, "w")) { fputs($fh, $the_string); fclose($fh); return true; } else { $GLOBALS['log']->debug("EMAILUI: Could not write cache file [ {$file} ]"); return false; } } /** * Generate JSON encoded data to be consumed by yui datatable. * * @param array $data * @param string $resultsParam The resultsList name * @return string */ function jsonOuput($data, $resultsParam, $count=0, $fromCache=true, $unread=-1) { global $app_strings; $count = ($count > 0) ? $count : 0; if(isset($a['fromCache'])) $cached = ($a['fromCache'] == 1) ? 1 : 0; else $cached = ($fromCache) ? 1 : 0; if($data['mbox'] == 'undefined' || empty($data['mbox'])) $data['mbox'] = $app_strings['LBL_NONE']; $jsonOut = array('TotalCount' => $count, 'FromCache' => $cached, 'UnreadCount' => $unread, $resultsParam => $data['out']); return json_encode($jsonOut); } /** * generates XML output from an array * @param array * @param string master list Item * @return string */ function xmlOutput($a, $paramName, $count=0, $fromCache=true, $unread=-1) { global $app_strings; $count = ($count > 0) ? $count : 0; if(isset($a['fromCache'])) { $cached = ($a['fromCache'] == 1) ? 1 : 0; } else { $cached = ($fromCache) ? 1 : 0; } if($a['mbox'] == 'undefined' || empty($a['mbox'])) { $a['mbox'] = $app_strings['LBL_NONE']; } $xml = $this->arrayToXML($a['out'], $paramName); $ret =<< {$count} {$unread} {$cached} <{$paramName}s> {$xml} eoq; return $ret; } /** * Generate to/cc addresses string in email detailview. * * @param string $str * @param string $target values: to, cc * @param int $defaultNum * @return string $str */ function generateExpandableAddrs($str) { global $mod_strings; $tempStr = $str.','; $tempStr = html_entity_decode($tempStr); $tempStr = $this->unifyEmailString($tempStr); $defaultNum = 2; $pattern = '/@.*,/U'; preg_match_all($pattern, $tempStr, $matchs); $totalCount = count($matchs[0]); if(!empty($matchs[0]) && $totalCount > $defaultNum) { $position = strpos($tempStr, $matchs[0][$defaultNum]); $hiddenCount = $totalCount - $defaultNum; $frontStr = substr($tempStr, 0, $position); $backStr = substr($tempStr, $position, -1); $str = htmlentities($frontStr) . '...['.$mod_strings['LBL_EMAIL_DETAIL_VIEW_SHOW'].$hiddenCount.$mod_strings['LBL_EMAIL_DETAIL_VIEW_MORE'].']' .htmlentities($backStr).''; } return $str; } /** * Unify the seperator as , * * @param String $str email address string * @return String converted string */ function unifyEmailString($str) { preg_match_all('/@.*;/U', $str, $matches); if(!empty($matches[0])) { foreach($matches[0] as $key => $value) { $new[] = str_replace(";",",",$value); } return str_replace($matches[0], $new, $str); } return $str; } } // end class def