/modules/InboundEmail/InboundEmail.php
PHP | 6480 lines | 4383 code | 783 blank | 1314 comment | 812 complexity | 4ed6b6cb6b0602abf3a6f2907774d78b MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- <?php
- if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
- /*********************************************************************************
- * SugarCRM Community Edition is a customer relationship management program developed by
- * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Affero General Public License version 3 as published by the
- * Free Software Foundation with the addition of the following permission added
- * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
- * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
- * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Affero General Public License along with
- * this program; if not, see http://www.gnu.org/licenses or write to the Free
- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- *
- * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
- * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
- *
- * The interactive user interfaces in modified source and object code versions
- * of this program must display Appropriate Legal Notices, as required under
- * Section 5 of the GNU Affero General Public License version 3.
- *
- * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
- * these Appropriate Legal Notices must retain the display of the "Powered by
- * SugarCRM" logo. If the display of the logo is not reasonably feasible for
- * technical reasons, the Appropriate Legal Notices must display the words
- * "Powered by SugarCRM".
- ********************************************************************************/
- require_once('include/OutboundEmail/OutboundEmail.php');
- function this_callback($str) {
- foreach($str as $match) {
- $ret .= chr(hexdec(str_replace("%","",$match)));
- }
- return $ret;
- }
- /**
- * Stub for certain interactions;
- */
- class temp {
- var $name;
- }
- class InboundEmail extends SugarBean {
- // module specific
- var $conn;
- var $purifier; // HTMLPurifier object placeholder
- var $email;
- // fields
- var $id;
- var $deleted;
- var $date_entered;
- var $date_modified;
- var $modified_user_id;
- var $created_by;
- var $created_by_name;
- var $modified_by_name;
- var $name;
- var $status;
- var $server_url;
- var $email_user;
- var $email_password;
- var $port;
- var $service;
- var $mailbox;
- var $mailboxarray;
- var $delete_seen;
- var $mailbox_type;
- var $template_id;
- var $stored_options;
- var $group_id;
- var $is_personal;
- var $groupfolder_id;
- // email 2.0
- var $pop3socket;
- var $outboundInstance; // id to outbound_email instance
- var $autoImport;
- var $iconFlagged = "F";
- var $iconDraft = "D";
- var $iconAnswered = "A";
- var $iconDeleted = "del";
- var $isAutoImport = false;
- var $smarty;
- var $attachmentCount = 0;
- var $tempAttachment = array();
- var $unsafeChars = array("&", "!", "'", '"', '\\', '/', '<', '>', '|', '$',);
- var $currentCache;
- var $defaultSort = 'date';
- var $defaultDirection = "DESC";
- var $hrSort = array(
- 0 => 'flagged',
- 1 => 'status',
- 2 => 'from',
- 3 => 'subj',
- 4 => 'date',
- );
- var $hrSortLocal = array(
- 'flagged' => 'flagged',
- 'status' => 'answered',
- 'from' => 'fromaddr',
- 'subject' => 'subject',
- 'date' => 'senddate',
- );
- // default attributes
- var $transferEncoding = array(0 => '7BIT',
- 1 => '8BIT',
- 2 => 'BINARY',
- 3 => 'BASE64',
- 4 => 'QUOTED-PRINTABLE',
- 5 => 'OTHER'
- );
- // object attributes
- var $compoundMessageId; // concatenation of messageID and deliveredToEmail
- var $serverConnectString;
- var $disable_row_level_security = true;
- var $InboundEmailCachePath;
- var $InboundEmailCacheFile = 'InboundEmail.cache.php';
- var $object_name = 'InboundEmail';
- var $module_dir = 'InboundEmail';
- var $table_name = 'inbound_email';
- var $new_schema = true;
- var $process_save_dates = true;
- var $order_by;
- var $db;
- var $dbManager;
- var $field_defs;
- var $column_fields;
- var $required_fields = array('name' => 'name',
- 'server_url' => 'server_url',
- 'mailbox' => 'mailbox',
- 'user' => 'user',
- 'port' => 'port',
- );
- var $imageTypes = array("JPG", "JPEG", "GIF", "PNG");
- var $inlineImages = array(); // temporary space to store ID of inlined images
- var $defaultEmailNumAutoreplies24Hours = 10;
- var $maxEmailNumAutoreplies24Hours = 10;
- // custom ListView attributes
- var $mailbox_type_name;
- var $global_personal_string;
- // service attributes
- var $tls;
- var $ca;
- var $ssl;
- var $protocol;
- var $keyForUsersDefaultIEAccount = 'defaultIEAccount';
- // prefix to use when importing inlinge images in emails
- public $imagePrefix;
- /**
- * Sole constructor
- */
- function InboundEmail() {
- $this->InboundEmailCachePath = sugar_cached('modules/InboundEmail');
- $this->EmailCachePath = sugar_cached('modules/Emails');
- parent::SugarBean();
- if(function_exists("imap_timeout")) {
- /*
- * 1: Open
- * 2: Read
- * 3: Write
- * 4: Close
- */
- imap_timeout(1, 60);
- imap_timeout(2, 60);
- imap_timeout(3, 60);
- }
- $this->smarty = new Sugar_Smarty();
- $this->overview = new Overview();
- $this->imagePrefix = "{$GLOBALS['sugar_config']['site_url']}/cache/images/";
- }
- /**
- * retrieves I-E bean
- * @param string id
- * @return object Bean
- */
- function retrieve($id, $encode=true, $deleted=true) {
- $ret = parent::retrieve($id,$encode,$deleted);
- // if I-E bean exist
- if (!is_null($ret)) {
- $this->email_password = blowfishDecode(blowfishGetKey('InboundEmail'), $this->email_password);
- $this->retrieveMailBoxFolders();
- }
- return $ret;
- }
- /**
- * wraps SugarBean->save()
- * @param string ID of saved bean
- */
- function save($check_notify=false) {
- // generate cache table for email 2.0
- $multiDImArray = $this->generateMultiDimArrayFromFlatArray(explode(",", $this->mailbox), $this->retrieveDelimiter());
- $raw = $this->generateFlatArrayFromMultiDimArray($multiDImArray, $this->retrieveDelimiter());
- sort($raw);
- //_pp(explode(",", $this->mailbox));
- //_ppd($raw);
- $raw = $this->filterMailBoxFromRaw(explode(",", $this->mailbox), $raw);
- $this->mailbox = implode(",", $raw);
- if(!empty($this->email_password)) {
- $this->email_password = blowfishEncode(blowfishGetKey('InboundEmail'), $this->email_password);
- }
- $ret = parent::save($check_notify);
- return $ret;
- }
- function filterMailBoxFromRaw($mailboxArray, $rawArray) {
- $newArray = array_intersect($mailboxArray, $rawArray);
- sort($newArray);
- return $newArray;
- } // fn
- /**
- * Overrides SugarBean's mark_deleted() to drop the related cache table
- * @param string $id GUID of I-E instance
- */
- function mark_deleted($id) {
- parent::mark_deleted($id);
- $q = "update inbound_email set groupfolder_id = null WHERE id = '{$id}'";
- $r = $this->db->query($q);
- $this->deleteCache();
- }
- /**
- * Mark cached email answered (replied)
- * @param string $mailid (uid for imap, message_id for pop3)
- */
- function mark_answered($mailid, $type = 'smtp') {
- switch ($type) {
- case 'smtp' :
- $q = "update email_cache set answered = 1 WHERE imap_uid = $mailid and ie_id = '{$this->id}'";
- $this->db->query($q);
- break;
- case 'pop3' :
- $q = "update email_cache set answered = 1 WHERE message_id = '$mailid' and ie_id = '{$this->id}'";
- $this->db->query($q);
- break;
- }
- }
- /**
- * Renames an IMAP mailbox
- * @param string $newName
- */
- function renameFolder($oldName, $newName) {
- //$this->mailbox = "INBOX"
- $this->connectMailserver();
- $oldConnect = $this->getConnectString('', $oldName);
- $newConnect = $this->getConnectString('', $newName);
- if(!imap_renamemailbox($this->conn, $oldConnect , $newConnect)) {
- $GLOBALS['log']->debug("***INBOUNDEMAIL: failed to rename mailbox [ {$oldConnect} ] to [ {$newConnect} ]");
- } else {
- $this->mailbox = str_replace($oldName, $newName, $this->mailbox);
- $this->save();
- $sessionFoldersString = $this->getSessionInboundFoldersString($this->server_url, $this->email_user, $this->port, $this->protocol);
- $sessionFoldersString = str_replace($oldName, $newName, $sessionFoldersString);
- $this->setSessionInboundFoldersString($this->server_url, $this->email_user, $this->port, $this->protocol, $sessionFoldersString);
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- //// CUSTOM LOGIC HOOKS
- /**
- * Called from $this->getMessageText()
- * Allows upgrade-safe custom processing of message text.
- *
- * To use:
- * 1. Create a directory path: ./custom/modules/InboundEmail if it does not exist
- * 2. Create a file in the ./custom/InboundEmail/ folder called "getMessageText.php"
- * 3. Define a function named "custom_getMessageText()" that takes a string as an argument and returns a string
- *
- * @param string $msgPart
- * @return string
- */
- function customGetMessageText($msgPart) {
- $custom = "custom/modules/InboundEmail/getMessageText.php";
- if(file_exists($custom)) {
- include_once($custom);
- if(function_exists("custom_getMessageText")) {
- $GLOBALS['log']->debug("*** INBOUND EMAIL-CUSTOM_LOGIC: calling custom_getMessageText()");
- $msgPart = custom_getMessageText($msgPart);
- }
- }
- return $msgPart;
- }
- //// END CUSTOM LOGIC HOOKS
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
- //// EMAIL 2.0 SPECIFIC
- /**
- * constructs a nicely formatted version of raw source
- * @param int $uid UID of email
- * @return string
- */
- function getFormattedRawSource($uid) {
- global $app_strings;
- //if($this->protocol == 'pop3') {
- //$raw = $app_strings['LBL_EMAIL_VIEW_UNSUPPORTED'];
- //} else {
- if (empty($this->id)) {
- $q = "SELECT raw_source FROM emails_text WHERE email_id = '{$uid}'";
- $r = $this->db->query($q);
- $a = $this->db->fetchByAssoc($r);
- $ret = array();
- $raw = $this->convertToUtf8($a['raw_source']);
- if (empty($raw)) {
- $raw = $app_strings['LBL_EMAIL_ERROR_VIEW_RAW_SOURCE'];
- }
- } else {
- if ($this->isPop3Protocol()) {
- $uid = $this->getCorrectMessageNoForPop3($uid);
- }
- $raw = imap_fetchheader($this->conn, $uid, FT_UID+FT_PREFETCHTEXT);
- $raw .= $this->convertToUtf8(imap_body($this->conn, $uid, FT_UID));
- } // else
- $raw = to_html($raw);
- $raw = nl2br($raw);
- //}
- return $raw;
- }
- /**
- * helper method to convert text to utf-8 if necessary
- *
- * @param string $input text
- * @return string output text
- */
- function convertToUtf8($input)
- {
- $charset = $GLOBALS['locale']->detectCharset($input, true);
- // we haven't a clue due to missing package?, just return as itself
- if ($charset === FALSE) {
- return $input;
- }
- // convert if we can or must
- return $this->handleCharsetTranslation($input, $charset);
- }
- /**
- * constructs a nicely formatted version of email headers.
- * @param int $uid
- * @return string
- */
- function getFormattedHeaders($uid) {
- global $app_strings;
- //if($this->protocol == 'pop3') {
- // $header = $app_strings['LBL_EMAIL_VIEW_UNSUPPORTED'];
- //} else {
- if ($this->isPop3Protocol()) {
- $uid = $this->getCorrectMessageNoForPop3($uid);
- }
- $headers = imap_fetchheader($this->conn, $uid, FT_UID);
- $lines = explode("\n", $headers);
- $header = "<table cellspacing='0' cellpadding='2' border='0' width='100%'>";
- foreach($lines as $line) {
- $line = trim($line);
- if(!empty($line)) {
- $key = trim(substr($line, 0, strpos($line, ":")));
- $key = strip_tags($key);
- $value = trim(substr($line, strpos($line, ":") + 1));
- $value = to_html($value);
- $header .= "<tr>";
- $header .= "<td class='displayEmailLabel' NOWRAP><b>{$key}</b> </td>";
- $header .= "<td class='displayEmailValueWhite'>{$value} </td>";
- $header .= "</tr>";
- }
- }
- $header .= "</table>";
- //}
- return $header;
- }
- /**
- * Empties Trash folders
- */
- function emptyTrash() {
- global $sugar_config;
- $this->mailbox = $this->get_stored_options("trashFolder");
- if (empty($this->mailbox)) {
- $this->mailbox = 'INBOX.Trash';
- }
- $this->connectMailserver();
- $uids = imap_search($this->conn, "ALL", SE_UID);
- foreach($uids as $uid) {
- if(!imap_delete($this->conn, $uid, FT_UID)) {
- $lastError = imap_last_error();
- $GLOBALS['log']->warn("INBOUNDEMAIL: emptyTrash() Could not delete message [ {$uid} ] from [ {$this->mailbox} ]. IMAP_ERROR [ {$lastError} ]");
- }
- }
- // remove local cache file
- $q = "DELETE FROM email_cache WHERE mbox = '{$this->mailbox}' AND ie_id = '{$this->id}'";
- $r = $this->db->query($q);
- }
- /**
- * Fetches a timestamp
- */
- function getCacheTimestamp($mbox) {
- $key = $this->db->quote("{$this->id}_{$mbox}");
- $q = "SELECT ie_timestamp FROM inbound_email_cache_ts WHERE id = '{$key}'";
- $r = $this->db->query($q);
- $a = $this->db->fetchByAssoc($r);
- if(empty($a)) {
- return -1;
- }
- return $a['ie_timestamp'];
- }
- /**
- * sets the cache timestamp
- * @param string mbox
- */
- function setCacheTimestamp($mbox) {
- $key = $this->db->quote("{$this->id}_{$mbox}");
- $ts = mktime();
- $tsOld = $this->getCacheTimestamp($mbox);
- if($tsOld < 0) {
- $q = "INSERT INTO inbound_email_cache_ts (id, ie_timestamp) VALUES ('{$key}', {$ts})";
- } else {
- $q = "UPDATE inbound_email_cache_ts SET ie_timestamp = {$ts} WHERE id = '{$key}'";
- }
- $r = $this->db->query($q, true);
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: setting timestamp query [ {$q} ]");
- }
- /**
- * Gets a count of all rows that are flagged seen = 0
- * @param string $mbox
- * @return int
- */
- function getCacheUnreadCount($mbox) {
- $q = "SELECT count(*) c FROM email_cache WHERE mbox = '{$mbox}' AND seen = 0 AND ie_id = '{$this->id}'";
- $r = $this->db->query($q);
- $a = $this->db->fetchByAssoc($r);
- return $a['c'];
- }
- /**
- * Returns total number of emails for a mailbox
- * @param string mbox
- * @return int
- */
- function getCacheCount($mbox) {
- $q = "SELECT count(*) c FROM email_cache WHERE mbox = '{$mbox}' AND ie_id = '{$this->id}'";
- $r = $this->db->query($q);
- $a = $this->db->fetchByAssoc($r);
- return $a['c'];
- }
- function getCacheUnread($mbox) {
- $q = "SELECT count(*) c FROM email_cache WHERE mbox = '{$mbox}' AND ie_id = '{$this->id}' AND seen = '0'";
- $r = $this->db->query($q);
- $a = $this->db->fetchByAssoc($r);
- return $a['c'];
- }
- /**
- * Deletes all rows for a given instance
- */
- function deleteCache() {
- $q = "DELETE FROM email_cache WHERE ie_id = '{$this->id}'";
- $GLOBALS['log']->info("INBOUNDEMAIL: deleting cache using query [ {$q} ]");
- $r = $this->db->query($q);
- }
- /**
- * Deletes all the pop3 data which has been deleted from server
- */
- function deletePop3Cache() {
- global $sugar_config;
- $UIDLs = $this->pop3_getUIDL();
- $cacheUIDLs = $this->pop3_getCacheUidls();
- foreach($cacheUIDLs as $msgNo => $msgId) {
- if (!in_array($msgId, $UIDLs)) {
- $md5msgIds = md5($msgId);
- $file = "{$this->EmailCachePath}/{$this->id}/messages/INBOX{$md5msgIds}.PHP";
- $GLOBALS['log']->debug("INBOUNDEMAIL: deleting file [ {$file} ] ");
- if(file_exists($file)) {
- if(!unlink($file)) {
- $GLOBALS['log']->debug("INBOUNDEMAIL: Could not delete [ {$file} ] ");
- } // if
- } // if
- $q = "DELETE from email_cache where imap_uid = {$msgNo} AND msgno = {$msgNo} AND ie_id = '{$this->id}' AND message_id = '{$msgId}'";
- $r = $this->db->query($q);
- } // if
- } // for
- } // fn
- /**
- * Retrieves cached headers
- * @return array
- */
- function getCacheValueForUIDs($mbox, $UIDs) {
- if (!is_array($UIDs) || empty($UIDs)) {
- return array();
- }
- $q = "SELECT * FROM email_cache WHERE ie_id = '{$this->id}' AND mbox = '{$mbox}' AND ";
- $startIndex = 0;
- $endIndex = 5;
- $slicedArray = array_slice($UIDs, $startIndex ,$endIndex);
- $columnName = ($this->isPop3Protocol() ? "message_id" : "imap_uid");
- $ret = array(
- 'timestamp' => $this->getCacheTimestamp($mbox),
- 'uids' => array(),
- 'retArr' => array(),
- );
- while (!empty($slicedArray)) {
- $messageIdString = implode(',', $slicedArray);
- $GLOBALS['log']->debug("sliced array = {$messageIdString}");
- $extraWhere = "{$columnName} IN (";
- $i = 0;
- foreach($slicedArray as $UID) {
- if($i != 0) {
- $extraWhere = $extraWhere . ",";
- } // if
- $i++;
- $extraWhere = "{$extraWhere} '{$UID}'";
- } // foreach
- $newQuery = $q . $extraWhere . ")";
- $r = $this->db->query($newQuery);
- while($a = $this->db->fetchByAssoc($r)) {
- if (isset($a['uid'])) {
- if ($this->isPop3Protocol()) {
- $ret['uids'][] = $a['message_id'];
- } else {
- $ret['uids'][] = $a['uid'];
- }
- }
- $overview = new Overview();
- foreach($a as $k => $v) {
- $k=strtolower($k);
- switch($k) {
- case "imap_uid":
- $overview->imap_uid = $v;
- if ($this->isPop3Protocol()) {
- $overview->uid = $a['message_id'];
- } else {
- $overview->uid = $v;
- }
- break;
- case "toaddr":
- $overview->to = from_html($v);
- break;
- case "fromaddr":
- $overview->from = from_html($v);
- break;
- case "mailsize":
- $overview->size = $v;
- break;
- case "senddate":
- $overview->date = $v;
- break;
- default:
- $overview->$k = from_html($v);
- break;
- } // switch
- } // foreach
- $ret['retArr'][] = $overview;
- } // while
- $startIndex = $startIndex + $endIndex;
- $slicedArray = array_slice($UIDs, $startIndex ,$endIndex);
- $messageIdString = implode(',', $slicedArray);
- $GLOBALS['log']->debug("sliced array = {$messageIdString}");
- } // while
- return $ret;
- }
- /**
- * Retrieves cached headers
- * @return array
- */
- function getCacheValue($mbox, $limit = 20, $page = 1, $sort='', $direction='') {
- // try optimizing this call as we don't want repeat queries
- if(!empty($this->currentCache)) {
- return $this->currentCache;
- }
- $sort = (empty($sort)) ? $this->defaultSort : $sort;
- $direction = (empty($direction)) ? $this->defaultDirection : $direction;
- $order = " ORDER BY {$this->hrSortLocal[$sort]} {$direction}";
- $q = "SELECT * FROM email_cache WHERE ie_id = '{$this->id}' AND mbox = '{$mbox}' {$order}";
- if(!empty($limit)) {
- $start = ( $page - 1 ) * $limit;
- $r = $this->db->limitQuery($q, $start, $limit);
- } else {
- $r = $this->db->query($q);
- }
- $ret = array(
- 'timestamp' => $this->getCacheTimestamp($mbox),
- 'uids' => array(),
- 'retArr' => array(),
- );
- while($a = $this->db->fetchByAssoc($r)) {
- if (isset($a['uid'])) {
- if ($this->isPop3Protocol()) {
- $ret['uids'][] = $a['message_id'];
- } else {
- $ret['uids'][] = $a['uid'];
- }
- }
- $overview = new Overview();
- foreach($a as $k => $v) {
- $k=strtolower($k);
- switch($k) {
- case "imap_uid":
- $overview->imap_uid = $v;
- if ($this->isPop3Protocol()) {
- $overview->uid = $a['message_id'];
- } else {
- $overview->uid = $v;
- }
- break;
- case "toaddr":
- $overview->to = from_html($v);
- break;
- case "fromaddr":
- $overview->from = from_html($v);
- break;
- case "mailsize":
- $overview->size = $v;
- break;
- case "senddate":
- $overview->date = $v;
- break;
- default:
- $overview->$k = from_html($v);
- break;
- }
- }
- $ret['retArr'][] = $overview;
- }
- $this->currentCache = $ret;
- return $ret;
- }
- /**
- * Sets cache values
- */
- function setCacheValue($mbox, $insert, $update=array(), $remove=array()) {
- if(empty($mbox)) {
- return;
- }
- global $timedate;
- // reset in-memory cache
- $this->currentCache = null;
- $table = 'email_cache';
- $where = "WHERE ie_id = '{$this->id}' AND mbox = '{$mbox}'";
- // handle removed rows
- if(!empty($remove)) {
- $removeIds = '';
- foreach($remove as $overview) {
- if(!empty($removeIds)) {
- $removeIds .= ",";
- }
- $removeIds .= "'{$overview->imap_uid}'";
- }
- $q = "DELETE FROM {$table} {$where} AND imap_uid IN ({$removeIds})";
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: delete query [ {$q} ]");
- $r = $this->db->query($q, true, $q);
- }
- // handle insert rows
- if(!empty($insert)) {
- $q = "SELECT imap_uid FROM {$table} {$where}";
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: filter UIDs query [ {$q} ]");
- $r = $this->db->query($q);
- $uids = array();
- while($a = $this->db->fetchByAssoc($r)) {
- $uids[] = $a['imap_uid'];
- }
- $count = count($uids);
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: found [ {$count} ] UIDs to filter against");
- $tmp = '';
- foreach($uids as $uid) {
- if(!empty($tmp))
- $tmp .= ", ";
- $tmp .= "{$uid}";
- }
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: filter UIDs: [ {$tmp} ]");
- $cols = "";
- foreach($this->overview->fieldDefs as $colDef) {
- if(!empty($cols))
- $cols .= ",";
- $cols .= "{$colDef['name']}";
- }
- foreach($insert as $overview) {
- if(in_array($overview->imap_uid, $uids))
- {
- // fixing bug #49543: setting 'mbox' property for the following updating of other items in this box
- if (!isset($overview->mbox))
- {
- $overview->mbox = $mbox;
- }
- $update[] = $overview;
- continue;
- }
- $values = '';
- foreach($this->overview->fieldDefs as $colDef) {
- if(!empty($values)) {
- $values .= ", ";
- }
- // trim values for Oracle/MSSql
- if( isset($colDef['len']) && !empty($colDef['len']) &&
- isset($colDef['type']) && !empty($colDef['type']) &&
- $colDef['type'] == 'varchar'
- )
- {
- if (isset($overview->$colDef['name']))
- {
- $overview->$colDef['name'] = substr($overview->$colDef['name'], 0, $colDef['len']);
- }
- }
- switch($colDef['name']) {
- case "imap_uid":
- if(isset($overview->uid) && !empty($overview->uid)) {
- $this->imap_uid = $overview->uid;
- }
- $values .= "'{$this->imap_uid}'";
- break;
- case "ie_id":
- $values .= "'{$this->id}'";
- break;
- case "toaddr":
- $values .= $this->db->quoted($overview->to);
- break;
- case "fromaddr":
- $values .= $this->db->quoted($overview->from);
- break;
- case "message_id" :
- $values .= $this->db->quoted($overview->message_id);
- break;
- case "mailsize":
- $values .= $overview->size;
- break;
- case "senddate":
- $conv=$timedate->fromString($overview->date);
- if (!empty($conv)) {
- $values .= $this->db->quoted($conv->asDb());
- } else {
- $values .= "NULL";
- }
- break;
- case "mbox":
- $values .= "'{$mbox}'";
- break;
- default:
- $overview->$colDef['name'] = SugarCleaner::cleanHtml(from_html($overview->$colDef['name']));
- $values .= $this->db->quoted($overview->$colDef['name']);
- break;
- }
- }
- $q = "INSERT INTO {$table} ({$cols}) VALUES ({$values})";
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: insert query [ {$q} ]");
- $r = $this->db->query($q, true, $q);
- }
- }
- // handle update rows
- if(!empty($update)) {
- $cols = "";
- foreach($this->overview->fieldDefs as $colDef) {
- if(!empty($cols))
- $cols .= ",";
- $cols .= "{$colDef['name']}";
- }
- foreach($update as $overview) {
- $q = "UPDATE {$table} SET ";
- $set = '';
- foreach($this->overview->fieldDefs as $colDef) {
- switch($colDef['name']) {
- case "toaddr":
- case "fromaddr":
- case "mailsize":
- case "senddate":
- case "mbox":
- case "ie_id":
- break;
- default:
- if(!empty($set))
- {
- $set .= ",";
- }
- $value = '';
- if (isset($overview->$colDef['name']))
- {
- $value = $this->db->quoted($overview->$colDef['name']);
- }
- else
- {
- $value = $this->db->quoted($value);
- }
- $set .= "{$colDef['name']} = " . $value;
- break;
- }
- }
- $q .= $set . " WHERE ie_id = '{$this->id}' AND mbox = '{$overview->mbox}' AND imap_uid = '{$overview->imap_uid}'";
- $GLOBALS['log']->info("INBOUNDEMAIL-CACHE: update query [ {$q} ]");
- $r = $this->db->query($q, true, $q);
- }
- }
- }
- /**
- * Opens a socket connection to the pop3 server
- * @return bool
- */
- function pop3_open() {
- if(!is_resource($this->pop3socket)) {
- $GLOBALS['log']->info("*** INBOUNDEMAIL: opening socket connection");
- $exServ = explode('::', $this->service);
- $socket = ($exServ[2] == 'ssl') ? "ssl://" : "tcp://";
- $socket .= $this->server_url;
- $this->pop3socket = fsockopen($socket, $this->port);
- } else {
- $GLOBALS['log']->info("*** INBOUNDEMAIL: REUSING socket connection");
- return true;
- }
- if(!is_resource($this->pop3socket)) {
- $GLOBALS['log']->debug("*** INBOUNDEMAIL: unable to open socket connection");
- return false;
- }
- // clear buffer
- $ret = trim(fgets($this->pop3socket, 1024));
- $GLOBALS['log']->info("*** INBOUNDEMAIL: got socket connection [ {$ret} ]");
- return true;
- }
- /**
- * Closes connections and runs clean-up routines
- */
- function pop3_cleanUp() {
- $GLOBALS['log']->info("*** INBOUNDEMAIL: cleaning up socket connection");
- fputs($this->pop3socket, "QUIT\r\n");
- $buf = fgets($this->pop3socket, 1024);
- fclose($this->pop3socket);
- }
- /**
- * sends a command down to the POP3 server
- * @param string command
- * @param string args
- * @param bool return
- * @return string
- */
- function pop3_sendCommand($command, $args='', $return=true) {
- $command .= " {$args}";
- $command = trim($command);
- $GLOBALS['log']->info("*** INBOUNDEMAIL: pop3_sendCommand() SEND [ {$command} ]");
- $command .= "\r\n";
- fputs($this->pop3socket, $command);
- if($return) {
- $ret = trim(fgets($this->pop3socket, 1024));
- $GLOBALS['log']->info("*** INBOUNDEMAIL: pop3_sendCommand() RECEIVE [ {$ret} ]");
- return $ret;
- }
- }
- function getPop3NewMessagesToDownload() {
- $pop3UIDL = $this->pop3_getUIDL();
- $cacheUIDLs = $this->pop3_getCacheUidls();
- // new email cache values we should deal with
- $diff = array_diff_assoc($pop3UIDL, $cacheUIDLs);
- // this is msgNo to UIDL array
- $diff = $this->pop3_shiftCache($diff, $cacheUIDLs);
- // get all the keys which are msgnos;
- return array_keys($diff);
- }
- function getPop3NewMessagesToDownloadForCron() {
- $pop3UIDL = $this->pop3_getUIDL();
- $cacheUIDLs = $this->pop3_getCacheUidls();
- // new email cache values we should deal with
- $diff = array_diff_assoc($pop3UIDL, $cacheUIDLs);
- // this is msgNo to UIDL array
- $diff = $this->pop3_shiftCache($diff, $cacheUIDLs);
- // insert data into email_cache
- if ($this->groupfolder_id != null && $this->groupfolder_id != "" && $this->isPop3Protocol()) {
- $searchResults = array_keys($diff);
- $concatResults = implode(",", $searchResults);
- if ($this->connectMailserver() == 'true') {
- $fetchedOverviews = imap_fetch_overview($this->conn, $concatResults);
- // clean up cache entry
- foreach($fetchedOverviews as $k => $overview) {
- $overview->message_id = trim($diff[$overview->msgno]);
- $fetchedOverviews[$k] = $overview;
- }
- $this->updateOverviewCacheFile($fetchedOverviews);
- }
- } // if
- return $diff;
- }
- /**
- * This method returns all the UIDL for this account. This should be called if the protocol is pop3
- * @return array od messageno to UIDL array
- */
- function pop3_getUIDL() {
- $UIDLs = array();
- if($this->pop3_open()) {
- // authenticate
- $this->pop3_sendCommand("USER", $this->email_user);
- $this->pop3_sendCommand("PASS", $this->email_password);
- // get UIDLs
- $this->pop3_sendCommand("UIDL", '', false); // leave socket buffer alone until the while()
- fgets($this->pop3socket, 1024); // handle "OK+";
- $UIDLs = array();
- $buf = '!';
- if(is_resource($this->pop3socket)) {
- while(!feof($this->pop3socket)) {
- $buf = fgets($this->pop3socket, 1024); // 8kb max buffer - shouldn't be more than 80 chars via pop3...
- //_pp(trim($buf));
- if(trim($buf) == '.') {
- $GLOBALS['log']->debug("*** GOT '.'");
- break;
- }
- // format is [msgNo] [UIDL]
- $exUidl = explode(" ", $buf);
- $UIDLs[$exUidl[0]] = trim($exUidl[1]);
- } // while
- } // if
- $this->pop3_cleanUp();
- } // if
- return $UIDLs;
- } // fn
- /**
- * Special handler for POP3 boxes. Standard IMAP commands are useless.
- * This will fetch only partial emails for POP3 and hence needs to be call again and again based on status it returns
- */
- function pop3_checkPartialEmail($synch = false) {
- require_once('include/utils/array_utils.php');
- global $current_user;
- global $sugar_config;
- $cacheDataExists = false;
- $diff = array();
- $results = array();
- $cacheFilePath = clean_path("{$this->EmailCachePath}/{$this->id}/folders/MsgNOToUIDLData.php");
- if(file_exists($cacheFilePath)) {
- $cacheDataExists = true;
- if($fh = @fopen($cacheFilePath, "rb")) {
- $data = "";
- $chunksize = 1*(1024*1024); // how many bytes per chunk
- while(!feof($fh)) {
- $buf = fgets($fh, $chunksize); // 8kb max buffer - shouldn't be more than 80 chars via pop3...
- $data = $data . $buf;
- flush();
- } // while
- fclose($fh);
- $diff = unserialize($data);
- if (!empty($diff)) {
- if (count($diff)> 50) {
- $newDiff = array_slice($diff, 50, count($diff), true);
- } else {
- $newDiff=array();
- }
- $results = array_slice(array_keys($diff), 0 ,50);
- $data = serialize($newDiff);
- if($fh = @fopen($cacheFilePath, "w")) {
- fputs($fh, $data);
- fclose($fh);
- } // if
- }
- } // if
- } // if
- if (!$cacheDataExists) {
- if ($synch) {
- $this->deletePop3Cache();
- }
- $UIDLs = $this->pop3_getUIDL();
- if(count($UIDLs) > 0) {
- // get cached UIDLs
- $cacheUIDLs = $this->pop3_getCacheUidls();
- // new email cache values we should deal with
- $diff = array_diff_assoc($UIDLs, $cacheUIDLs);
- $diff = $this->pop3_shiftCache($diff, $cacheUIDLs);
- require_once('modules/Emails/EmailUI.php');
- EmailUI::preflightEmailCache("{$this->EmailCachePath}/{$this->id}");
- if (count($diff)> 50) {
- $newDiff = array_slice($diff, 50, count($diff), true);
- } else {
- $newDiff=array();
- }
- $results = array_slice(array_keys($diff), 0 ,50);
- $data = serialize($newDiff);
- if($fh = @fopen($cacheFilePath, "w")) {
- fputs($fh, $data);
- fclose($fh);
- } // if
- } else {
- $GLOBALS['log']->debug("*** INBOUNDEMAIL: could not open socket connection to POP3 server");
- return "could not open socket connection to POP3 server";
- } // else
- } // if
- // build up msgNo request
- if(count($diff) > 0) {
- // remove dirty cache entries
- $startingNo = 0;
- if (isset($_REQUEST['currentCount']) && $_REQUEST['currentCount'] > -1) {
- $startingNo = $_REQUEST['currentCount'];
- }
- $this->mailbox = 'INBOX';
- $this->connectMailserver();
- //$searchResults = array_keys($diff);
- //$fetchedOverviews = array();
- //$chunkArraySerachResults = array_chunk($searchResults, 50);
- $concatResults = implode(",", $results);
- $GLOBALS['log']->info('$$$$ '.$concatResults);
- $GLOBALS['log']->info("[EMAIL] Start POP3 fetch overview on mailbox [{$this->mailbox}] for user [{$current_user->user_name}] on 50 data");
- $fetchedOverviews = imap_fetch_overview($this->conn, $concatResults);
- $GLOBALS['log']->info("[EMAIL] End POP3 fetch overview on mailbox [{$this->mailbox}] for user [{$current_user->user_name}] on "
- . sizeof($fetchedOverviews) . " data");
- // clean up cache entry
- foreach($fetchedOverviews as $k => $overview) {
- $overview->message_id = trim($diff[$overview->msgno]);
- $fetchedOverviews[$k] = $overview;
- }
- $GLOBALS['log']->info("[EMAIL] Start updating overview cache for pop3 mailbox [{$this->mailbox}] for user [{$current_user->user_name}]");
- $this->updateOverviewCacheFile($fetchedOverviews);
- $GLOBALS['log']->info("[EMAIL] Start updating overview cache for pop3 mailbox [{$this->mailbox}] for user [{$current_user->user_name}]");
- return array('status' => "In Progress", 'mbox' => $this->mailbox, 'count'=> (count($results) + $startingNo), 'totalcount' => count($diff), 'ieid' => $this->id);
- } // if
- unlink($cacheFilePath);
- return array('status' => "done");
- }
- /**
- * Special handler for POP3 boxes. Standard IMAP commands are useless.
- */
- function pop3_checkEmail() {
- if($this->pop3_open()) {
- // authenticate
- $this->pop3_sendCommand("USER", $this->email_user);
- $this->pop3_sendCommand("PASS", $this->email_password);
- // get UIDLs
- $this->pop3_sendCommand("UIDL", '', false); // leave socket buffer alone until the while()
- fgets($this->pop3socket, 1024); // handle "OK+";
- $UIDLs = array();
- $buf = '!';
- if(is_resource($this->pop3socket)) {
- while(!feof($this->pop3socket)) {
- $buf = fgets($this->pop3socket, 1024); // 8kb max buffer - shouldn't be more than 80 chars via pop3...
- //_pp(trim($buf));
- if(trim($buf) == '.') {
- $GLOBALS['log']->debug("*** GOT '.'");
- break;
- }
- // format is [msgNo] [UIDL]
- $exUidl = explode(" ", $buf);
- $UIDLs[$exUidl[0]] = trim($exUidl[1]);
- }
- }
- $this->pop3_cleanUp();
- // get cached UIDLs
- $cacheUIDLs = $this->pop3_getCacheUidls();
- // _pp($UIDLs);_pp($cacheUIDLs);
- // new email cache values we should deal with
- $diff = array_diff_assoc($UIDLs, $cacheUIDLs);
- // remove dirty cache entries
- $diff = $this->pop3_shiftCache($diff, $cacheUIDLs);
- // build up msgNo request
- if(!empty($diff)) {
- $this->mailbox = 'INBOX';
- $this->connectMailserver();
- $searchResults = array_keys($diff);
- $concatResults = implode(",", $searchResults);
- $fetchedOverviews = imap_fetch_overview($this->conn, $concatResults);
- // clean up cache entry
- foreach($fetchedOverviews as $k => $overview) {
- $overview->message_id = trim($diff[$overview->msgno]);
- $fetchedOverviews[$k] = $overview;
- }
- $this->updateOverviewCacheFile($fetchedOverviews);
- }
- } else {
- $GLOBALS['log']->debug("*** INBOUNDEMAIL: could not open socket connection to POP3 server");
- return false;
- }
- }
- /**
- * Iterates through msgno and message_id to remove dirty cache entries
- * @param array diff
- */
- function pop3_shiftCache($diff, $cacheUIDLs) {
- $msgNos = "";
- $msgIds = "";
- $newArray = array();
- foreach($diff as $msgNo => $msgId) {
- if (in_array($msgId, $cacheUIDLs)) {
- $q1 = "UPDATE email_cache SET imap_uid = {$msgNo}, msgno = {$msgNo} WHERE ie_id = '{$this->id}' AND message_id = '{$msgId}'";
- $this->db->query($q1);
- } else {
- $newArray[$msgNo] = $msgId;
- }
- }
- return $newArray;
- /*
- foreach($diff as $msgNo => $msgId) {
- if(!empty($msgNos)) {
- $msgNos .= ", ";
- }
- if(!empty($msgIds)) {
- $msgIds .= ", ";
- }
- $msgNos .= $msgNo;
- $msgIds .= "'{$msgId}'";
- }
- if(!empty($msgNos)) {
- $q1 = "DELETE FROM email_cache WHERE ie_id = '{$this->id}' AND msgno IN ({$msgNos})";
- $this->db->query($q1);
- }
- if(!empty($msgIds)) {
- $q2 = "DELETE FROM email_cache WHERE ie_id = '{$this->id}' AND message_id IN ({$msgIds})";
- $this->db->query($q2);
- }
- */
- }
- /**
- * retrieves cached uidl values.
- * When dealing with POP3 accounts, the message_id column in email_cache will contain the UIDL.
- * @return array
- */
- function pop3_getCacheUidls() {
- $q = "SELECT msgno, message_id FROM email_cache WHERE ie_id = '{$this->id}'";
- $r = $this->db->query($q);
- $ret = array();
- while($a = $this->db->fetchByAssoc($r)) {
- $ret[$a['msgno']] = $a['message_id'];
- }
- return $ret;
- }
- /**
- * This function is used by cron job for group mailbox without group folder
- * @param string $msgno for pop
- * @param string $uid for imap
- */
- function getMessagesInEmailCache($msgno, $uid) {
- $fetchedOverviews = array();
- if ($this->isPop3Protocol()) {
- $fetchedOverviews = imap_fetch_overview($this->conn, $msgno);
- foreach($fetchedOverviews as $k => $overview) {
- $overview->message_id = $uid;
- $fetchedOverviews[$k] = $overview;
- }
- } else {
- $fetchedOverviews = imap_fetch_overview($this->conn, $uid, FT_UID);
- } // else
- $this->updateOverviewCacheFile($fetchedOverviews);
- } // fn
- /**
- * Checks email (local caching too) for one mailbox
- * @param string $mailbox IMAP Mailbox path
- * @param bool $prefetch Flag to prefetch email body on check
- */
- function checkEmailOneMailbox($mailbox, $prefetch=true, $synchronize=false) {
- global $sugar_config;
- global $current_user;
- global $app_strings;
- $result = 1;
- $GLOBALS['log']->info("INBOUNDEMAIL: checking mailbox [ {$mailbox} ]");
- $this->mailbox = $mailbox;
- $this->connectMailserver();
- $checkTime = '';
- $shouldProcessRules = true;
- $timestamp = $this->getCacheTimestamp($mailbox);
- if($timestamp > 0) {
- $checkTime = date('r', $timestamp);
- }
- /* first time through, process ALL emails */
- if(empty($checkTime) || $synchronize) {
- // do not process rules for the first time or sunchronize
- $shouldProcessRules = false;
- $criteria = "ALL UNDELETED";
- $prefetch = false; // do NOT prefetch emails on a brand new account - timeouts happen.
- $GLOBALS['log']->info("INBOUNDEMAIL: new account detected - not prefetching email bodies.");
- } else {
- $criteria = "SINCE \"{$checkTime}\" UNDELETED"; // not using UNSEEN
- }
- $this->setCacheTimestamp($mailbox);
- $GLOBALS['log']->info("[EMAIL] Performing IMAP search using criteria [{$criteria}] on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $searchResults = imap_search($this->conn, $criteria, SE_UID);
- $GLOBALS['log']->info("[EMAIL] Done IMAP search on mailbox [{$mailbox}] for user [{$current_user->user_name}]. Result count = ".count($searchResults));
- if(!empty($searchResults)) {
- $concatResults = implode(",", $searchResults);
- $GLOBALS['log']->info("[EMAIL] Start IMAP fetch overview on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $fetchedOverview = imap_fetch_overview($this->conn, $concatResults, FT_UID);
- $GLOBALS['log']->info("[EMAIL] Done IMAP fetch overview on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $GLOBALS['log']->info("[EMAIL] Start updating overview cache for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $this->updateOverviewCacheFile($fetchedOverview);
- $GLOBALS['log']->info("[EMAIL] Done updating overview cache for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- // prefetch emails
- if($prefetch == true) {
- $GLOBALS['log']->info("[EMAIL] Start fetching emails for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- if(!$this->fetchCheckedEmails($fetchedOverview))
- {
- $result = 0;
- }
- $GLOBALS['log']->info("[EMAIL] Done fetching emails for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- }
- } else {
- $GLOBALS['log']->info("INBOUNDEMAIL: no results for mailbox [ {$mailbox} ]");
- $result = 1;
- }
- /**
- * To handle the use case where an external client is also connected, deleting emails, we need to clear our
- * local cache of all emails with the "DELETED" flag
- */
- $criteria = 'DELETED';
- $criteria .= (!empty($checkTime)) ? " SINCE \"{$checkTime}\"" : "";
- $GLOBALS['log']->info("INBOUNDEMAIL: checking for deleted emails using [ {$criteria} ]");
- $trashFolder = $this->get_stored_options("trashFolder");
- if (empty($trashFolder)) {
- $trashFolder = "INBOX.Trash";
- }
- if($this->mailbox != $trashFolder) {
- $searchResults = imap_search($this->conn, $criteria, SE_UID);
- if(!empty($searchResults)) {
- $uids = implode($app_strings['LBL_EMAIL_DELIMITER'], $searchResults);
- $GLOBALS['log']->info("INBOUNDEMAIL: removing UIDs found deleted [ {$uids} ]");
- $this->getOverviewsFromCacheFile($uids, $mailbox, true);
- }
- }
- return $result;
- }
- /**
- * Checks email (local caching too) for one mailbox
- * @param string $mailbox IMAP Mailbox path
- * @param bool $prefetch Flag to prefetch email body on check
- */
- function checkEmailOneMailboxPartial($mailbox, $prefetch=true, $synchronize=false, $start = 0, $max = -1) {
- global $sugar_config;
- global $current_user;
- global $app_strings;
- $GLOBALS['log']->info("INBOUNDEMAIL: checking mailbox [ {$mailbox} ]");
- $this->mailbox = $mailbox;
- $this->connectMailserver();
- $checkTime = '';
- $shouldProcessRules = true;
- $timestamp = $this->getCacheTimestamp($mailbox);
- if($timestamp > 0) {
- $checkTime = date('r', $timestamp);
- }
- /* first time through, process ALL emails */
- if(empty($checkTime) || $synchronize) {
- // do not process rules for the first time or sunchronize
- $shouldProcessRules = false;
- $criteria = "ALL UNDELETED";
- $prefetch = false; // do NOT prefetch emails on a brand new account - timeouts happen.
- $GLOBALS['log']->info("INBOUNDEMAIL: new account detected - not prefetching email bodies.");
- } else {
- $criteria = "SINCE \"{$checkTime}\" UNDELETED"; // not using UNSEEN
- }
- $this->setCacheTimestamp($mailbox);
- $GLOBALS['log']->info("[EMAIL] Performing IMAP search using criteria [{$criteria}] on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $searchResults = $this->getCachedIMAPSearch($criteria);
- if(!empty($searchResults)) {
- $total = sizeof($searchResults);
- $searchResults = array_slice($searchResults, $start, $max);
- $GLOBALS['log']->info("INBOUNDEMAIL: there are $total messages in [{$mailbox}], we are on $start");
- $GLOBALS['log']->info("INBOUNDEMAIL: getting the next " . sizeof($searchResults) . " messages");
- $concatResults = implode(",", $searchResults);
- $GLOBALS['log']->info("INBOUNDEMAIL: Start IMAP fetch overview on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $fetchedOverview = imap_fetch_overview($this->conn, $concatResults, FT_UID);
- $GLOBALS['log']->info("INBOUNDEMAIL: Done IMAP fetch overview on mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $GLOBALS['log']->info("INBOUNDEMAIL: Start updating overview cache for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $this->updateOverviewCacheFile($fetchedOverview);
- $GLOBALS['log']->info("INBOUNDEMAIL: Done updating overview cache for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- // prefetch emails
- if($prefetch == true) {
- $GLOBALS['log']->info("INBOUNDEMAIL: Start fetching emails for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- $this->fetchCheckedEmails($fetchedOverview);
- $GLOBALS['log']->info("INBOUNDEMAIL: Done fetching emails for mailbox [{$mailbox}] for user [{$current_user->user_name}]");
- }
- $status = ($total > $start + sizeof($searchResults)) ? 'continue' : 'done';
- $ret = array('status' => $status, 'count' => $start + sizeof($searchResults), 'mbox' => $mailbox, 'totalcount' => $total);
- $GLOBALS['log']->info("INBOUNDEMAIL: $status : Downloaded " . $start + sizeof($searchResults) . "messages of $total");
- } else {
- $GLOBALS['log']->info("INBOUNDEMAIL: no results for mailbox [ {$mailbox} ]");
- $ret = array('status' =>'done');
- }
- if ($ret['status'] == 'done') {
- //Remove the cached search if we are done with this mailbox
- $cacheFilePath = clean_path("{$this->EmailCachePath}/{$this->id}/folders/SearchData.php");
- unlink($cacheFilePath);
- /**
- * To handle the use case where an external client is also connected, deleting emails, we need to clear our
- * local cache of all emails with the "DELETED" flag
- */
- $criteria = 'DELETED';
- $criteria .= (!empty($checkTime)) ? " SINCE \"{$checkTime}\"" : "";
- $GLOBALS['log']->info("INBOUNDEMAIL: checking for deleted emails using [ {$criteria} ]");
- $trashFolder = $this->get_stored_options("trashFolder");
- if (empty($trashFolder)) {
- $trashFolder = "INBOX.Trash";
- }
- if($this->mailbox != $trashFolder) {
- $searchResults = imap_search($this->conn, $criteria, SE_UID);
- if(!empty($searchResults)) {
- $uids = implode($app_strings['LBL_EMAIL_DELIMITER'], $searchResults);
- $GLOBALS['log']->info("INBOUNDEMAIL: removing UIDs found deleted [ {$uids} ]");
- $this->getOverviewsFromCacheFile($uids, $mailbox, true);
- }
- }
- }
- return $ret;
- }
- function getCachedIMAPSearch($criteria) {
- global $current_user;
- global $sugar_config;
- $cacheDataExists = false;
- $diff = array();
- $results = array();
- $cacheFolderPath = clean_path("{$this->EmailCachePath}/{$this->id}/folders");
- if (!file_exists($cacheFolderPath)) {
- mkdir_recursive($cacheFolderPath);
- }
- $cacheFilePath = $cacheFolderPath . '/SearchData.php';
- $GLOBALS['log']->info("INBOUNDEMAIL: Cache path is $cacheFilePath");
- if(file_exists($cacheFilePath)) {
- $cacheDataExists = true;
- if($fh = @fopen($cacheFilePath, "rb")) {
- $data = "";
- $chunksize = 1*(1024*1024); // how many bytes per chunk
- while(!feof($fh)) {
- $buf = fgets($fh, $chunksize); // 8kb max buffer - shouldn't be more than 80 chars via pop3...
- $data = $data . $buf;
- flush();
- } // while
- fclose($fh);
- $results = unserialize($data);
- } // if
- } // if
- if (!$cacheDataExists) {
- $searchResults = imap_search($this->conn, $criteria, SE_UID);
- if(count($searchResults) > 0) {
- $results = $searchResults;
- $data = serialize($searchResults);
- if($fh = @fopen($cacheFilePath, "w")) {
- fputs($fh, $data);
- fclose($fh);
- } // if
- }
- } // if
- return $results;
- }
- function checkEmailIMAPPartial($prefetch=true, $synch = false) {
- $GLOBALS['log']->info("*****************INBOUNDEMAIL: at IMAP check partial");
- global $sugar_config;
- $result = $this->connectMailserver();
- if ($result == 'false')
- {
- return array(
- 'status' => 'error',
- 'message' => 'Email server is down'
- );
- }
- $mailboxes = $this->getMailboxes(true);
- if (!in_array('INBOX', $mailboxes)) {
- $mailboxes[] = 'INBOX';
- }
- sort($mailboxes);
- if (isset($_REQUEST['mbox']) && !empty($_REQUEST['mbox']) && isset($_REQUEST['currentCount'])) {
- $GLOBALS['log']->info("INBOUNDEMAIL: Picking up from where we left off");
- $mbox = $_REQUEST['mbox'];
- $count = $_REQUEST['currentCount'];
- } else {
- if ($synch) {
- $GLOBALS['log']->info("INBOUNDEMAIL: Cleaning out the cache");
- $this->cleanOutCache();
- }
- $mbox = $mailboxes[0];
- $count = 0;
- }
- $GLOBALS['log']->info("INBOUNDEMAIL:found " . sizeof($mailboxes) . " Mailboxes");
- $index = array_search($mbox, $mailboxes) + 1;
- $ret = $this->checkEmailOneMailboxPartial($mbox, $prefetch, $synch, $count, 100);
- while($ret['status'] == 'done' && $index < sizeof($mailboxes)) {
- if ($ret['count'] > 100) {
- $ret['mbox'] = $mailboxes[$index];
- $ret['status'] = 'continue';
- return $ret;
- }
- $GLOBALS['log']->info("INBOUNDEMAIL: checking account [ $index => $mbox : $count]");
- $mbox = $mailboxes[$index];
- $ret = $this->checkEmailOneMailboxPartial($mbox, $prefetch, $synch, 0, 100);
- $index++;
- }
- return $ret;
- }
- function checkEmail2_meta() {
- global $sugar_config;
- $this->connectMailserver();
- $mailboxes = $this->getMailboxes(true);
- $mailboxes[] = 'INBOX';
- sort($mailboxes);
- $GLOBALS['log']->info("INBOUNDEMAIL: checking account [ {$this->name} ]");
- $mailboxes_meta = array();
- foreach($mailboxes as $mailbox) {
- $mailboxes_meta[$mailbox] = $this->getMailboxProcessCount($mailbox);
- }
- $ret = array();
- $ret['mailboxes'] = $mailboxes_meta;
- foreach($mailboxes_…
Large files files are truncated, but you can click here to view the full file