2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
40 * Set up an array of Jobs with the appropriate metadata
41 * 'jobName' => array (
44 * 'X' should be an increment of 1
45 * 'name' should be the EXACT name of your function
47 * Your function should not be passed any parameters
48 * Always return a Boolean. If it does not the Job will not terminate itself
49 * after completion, and the webserver will be forced to time-out that Job instance.
50 * DO NOT USE sugar_cleanup(); in your function flow or includes. this will
51 * break Schedulers. That function is called at the foot of cron.php
55 * This array provides the Schedulers admin interface with values for its "Job"
58 $job_strings = array (
60 1 => 'pollMonitoredInboxes',
61 2 => 'runMassEmailCampaign',
62 5 => 'pollMonitoredInboxesForBouncedCampaignEmails',
65 /*4 => 'securityAudit()',*/
70 * Job 0 refreshes all job schedulers at midnight
73 function refreshJobs() {
81 function pollMonitoredInboxes() {
83 $GLOBALS['log']->info('----->Scheduler fired job of type pollMonitoredInboxes()');
88 require_once('modules/Emails/EmailUI.php');
90 $ie = new InboundEmail();
91 $emailUI = new EmailUI();
92 $r = $ie->db->query('SELECT id, name FROM inbound_email WHERE is_personal = 0 AND deleted=0 AND status=\'Active\' AND mailbox_type != \'bounce\'');
93 $GLOBALS['log']->debug('Just got Result from get all Inbounds of Inbound Emails');
95 while($a = $ie->db->fetchByAssoc($r)) {
96 $GLOBALS['log']->debug('In while loop of Inbound Emails');
97 $ieX = new InboundEmail();
98 $ieX->retrieve($a['id']);
99 $mailboxes = $ieX->mailboxarray;
100 foreach($mailboxes as $mbox) {
101 $ieX->mailbox = $mbox;
103 $msgNoToUIDL = array();
104 $connectToMailServer = false;
105 if ($ieX->isPop3Protocol()) {
106 $msgNoToUIDL = $ieX->getPop3NewMessagesToDownloadForCron();
107 // get all the keys which are msgnos;
108 $newMsgs = array_keys($msgNoToUIDL);
110 if($ieX->connectMailserver() == 'true') {
111 $connectToMailServer = true;
114 $GLOBALS['log']->debug('Trying to connect to mailserver for [ '.$a['name'].' ]');
115 if($connectToMailServer) {
116 $GLOBALS['log']->debug('Connected to mailserver');
117 if (!$ieX->isPop3Protocol()) {
118 $newMsgs = $ieX->getNewMessageIds();
120 if(is_array($newMsgs)) {
122 $total = count($newMsgs);
123 require_once("include/SugarFolders/SugarFolders.php");
124 $sugarFolder = new SugarFolder();
125 $groupFolderId = $ieX->groupfolder_id;
126 $isGroupFolderExists = false;
128 if ($groupFolderId != null && $groupFolderId != "") {
129 $sugarFolder->retrieve($groupFolderId);
130 $isGroupFolderExists = true;
132 $messagesToDelete = array();
133 if ($ieX->isMailBoxTypeCreateCase()) {
134 $users[] = $sugarFolder->assign_to_id;
135 $distributionMethod = $ieX->get_stored_options("distrib_method", "");
136 if ($distributionMethod != 'roundRobin') {
137 $counts = $emailUI->getAssignedEmailsCountForUsers($users);
139 $lastRobin = $emailUI->getLastRobin($ieX);
141 $GLOBALS['log']->debug('distribution method id [ '.$distributionMethod.' ]');
143 foreach($newMsgs as $k => $msgNo) {
145 if ($ieX->isPop3Protocol()) {
146 $uid = $msgNoToUIDL[$msgNo];
148 $uid = imap_uid($ieX->conn, $msgNo);
150 if ($isGroupFolderExists) {
151 if ($ieX->importOneEmail($msgNo, $uid)) {
153 $sugarFolder->addBean($ieX->email);
154 if ($ieX->isPop3Protocol()) {
155 $messagesToDelete[] = $msgNo;
157 $messagesToDelete[] = $uid;
159 if ($ieX->isMailBoxTypeCreateCase()) {
161 if ($distributionMethod == 'roundRobin') {
162 if (sizeof($users) == 1) {
164 $lastRobin = $users[0];
166 $userIdsKeys = array_flip($users); // now keys are values
167 $thisRobinKey = $userIdsKeys[$lastRobin] + 1;
168 if(!empty($users[$thisRobinKey])) {
169 $userId = $users[$thisRobinKey];
170 $lastRobin = $users[$thisRobinKey];
173 $lastRobin = $users[0];
177 if (sizeof($users) == 1) {
178 foreach($users as $k => $value) {
182 asort($counts); // lowest to highest
183 $countsKeys = array_flip($counts); // keys now the 'count of items'
184 $leastBusy = array_shift($countsKeys); // user id of lowest item count
185 $userId = $leastBusy;
186 $counts[$leastBusy] = $counts[$leastBusy] + 1;
189 $GLOBALS['log']->debug('userId [ '.$userId.' ]');
190 $ieX->handleCreateCase($ieX->email, $userId);
194 if($ieX->isAutoImport()) {
195 $ieX->importOneEmail($msgNo, $uid);
197 /*If the group folder doesn't exist then download only those messages
198 which has caseid in message*/
199 $ieX->getMessagesInEmailCache($msgNo, $uid);
200 $email = new Email();
201 $header = imap_headerinfo($ieX->conn, $msgNo);
202 $email->name = $ieX->handleMimeHeaderDecode($header->subject);
203 $email->from_addr = $ieX->convertImapToSugarEmailAddress($header->from);
204 $email->reply_to_email = $ieX->convertImapToSugarEmailAddress($header->reply_to);
205 if(!empty($email->reply_to_email)) {
206 $contactAddr = $email->reply_to_email;
208 $contactAddr = $email->from_addr;
210 $mailBoxType = $ieX->mailbox_type;
211 $ieX->handleAutoresponse($email, $contactAddr);
214 $GLOBALS['log']->debug('***** On message [ '.$current.' of '.$total.' ] *****');
217 // update Inbound Account with last robin
218 if ($ieX->isMailBoxTypeCreateCase() && $distributionMethod == 'roundRobin') {
219 $emailUI->setLastRobin($ieX, $lastRobin);
223 if ($isGroupFolderExists) {
224 $leaveMessagesOnMailServer = $ieX->get_stored_options("leaveMessagesOnMailServer", 0);
225 if (!$leaveMessagesOnMailServer) {
226 if ($ieX->isPop3Protocol()) {
227 $ieX->deleteMessageOnMailServerForPop3(implode(",", $messagesToDelete));
229 $ieX->deleteMessageOnMailServer(implode($app_strings['LBL_EMAIL_DELIMITER'], $messagesToDelete));
234 $GLOBALS['log']->fatal("SCHEDULERS: could not get an IMAP connection resource for ID [ {$a['id']} ]. Skipping mailbox [ {$a['name']} ].");
235 // cn: bug 9171 - continue while
238 imap_expunge($ieX->conn);
239 imap_close($ieX->conn, CL_EXPUNGE);
248 function runMassEmailCampaign() {
249 if (!class_exists('LoggerManager')){
252 $GLOBALS['log'] = LoggerManager::getLogger('emailmandelivery');
253 $GLOBALS['log']->debug('Called:runMassEmailCampaign');
255 if (!class_exists('DBManagerFactory')){
256 require('include/database/DBManagerFactory.php');
261 require("config.php");
262 require('include/modules.php');
263 if(!class_exists('AclController')) {
264 require('modules/ACL/ACLController.php');
267 require('modules/EmailMan/EmailManDelivery.php');
274 function pruneDatabase() {
275 $GLOBALS['log']->info('----->Scheduler fired job of type pruneDatabase()');
276 $backupDir = $GLOBALS['sugar_config']['cache_dir'].'backups';
277 $backupFile = 'backup-pruneDatabase-GMT0_'.gmdate('Y_m_d-H_i_s', strtotime('now')).'.php';
279 $db = DBManagerFactory::getInstance();
280 $tables = $db->getTablesArray();
283 if(!empty($tables)) {
284 foreach($tables as $kTable => $table) {
285 // find tables with deleted=1
286 $qDel = 'SELECT * FROM '.$table.' WHERE deleted = 1';
287 $rDel = $db->query($qDel);// OR continue; // continue if no 'deleted' column
289 // make a backup INSERT query if we are deleting.
290 while($aDel = $db->fetchByAssoc($rDel)) {
291 // build column names
292 $rCols = $db->query('SHOW COLUMNS FROM '.$table);
295 while($aCols = $db->fetchByAssoc($rCols)) {
296 $colName[] = $aCols['Field'];
299 $query = 'INSERT INTO '.$table.' (';
301 foreach($colName as $kC => $column) {
302 $query .= $column.', ';
303 $values .= '"'.$aDel[$column].'", ';
306 $query = substr($query, 0, (strlen($query) - 2));
307 $values = substr($values, 0, (strlen($values) - 2));
308 $query .= ') VALUES ('.str_replace("'", "'", $values).');';
310 $queryString[] = $query;
312 if(empty($colName)) {
313 $GLOBALS['log']->fatal('pruneDatabase() could not get the columns for table ('.$table.')');
315 } // end aDel while()
316 // now do the actual delete
317 $db->query('DELETE FROM '.$table.' WHERE deleted = 1');
318 } // foreach() tables
320 // now output file with SQL
321 if(!function_exists('mkdir_recursive')) {
324 if(!function_exists('write_array_to_file')) {
327 if(!file_exists($backupDir) || !file_exists($backupDir.'/'.$backupFile)) {
328 // create directory if not existent
329 mkdir_recursive($backupDir, false);
333 write_array_to_file('pruneDatabase', $queryString, $backupDir.'/'.$backupFile);
344 //function securityAudit() {
349 function trimTracker()
351 global $sugar_config, $timedate;
352 $GLOBALS['log']->info('----->Scheduler fired job of type trimTracker()');
353 $db = DBManagerFactory::getInstance();
355 $admin = new Administration();
356 $admin->retrieveSettings('tracker');
357 require('modules/Trackers/config.php');
358 $trackerConfig = $tracker_config;
360 require_once('include/utils/db_utils.php');
361 $prune_interval = !empty($admin->settings['tracker_prune_interval']) ? $admin->settings['tracker_prune_interval'] : 30;
362 foreach($trackerConfig as $tableName=>$tableConfig) {
364 //Skip if table does not exist
365 if(!$db->tableExists($tableName)) {
369 $timeStamp = db_convert("'". $timedate->asDb($timedate->getNow()->get("+"+$prune_interval+" days")) ."'" ,"datetime");
370 if($tableName == 'tracker_sessions') {
371 $query = "DELETE FROM $tableName WHERE date_end < $timeStamp";
373 $query = "DELETE FROM $tableName WHERE date_modified < $timeStamp";
376 $GLOBALS['log']->info("----->Scheduler is about to trim the $tableName table by running the query $query");
385 function pollMonitoredInboxesForBouncedCampaignEmails() {
386 $GLOBALS['log']->info('----->Scheduler job of type pollMonitoredInboxesForBouncedCampaignEmails()');
390 $ie = new InboundEmail();
391 $r = $ie->db->query('SELECT id FROM inbound_email WHERE deleted=0 AND status=\'Active\' AND mailbox_type=\'bounce\'');
393 while($a = $ie->db->fetchByAssoc($r)) {
394 $ieX = new InboundEmail();
395 $ieX->retrieve($a['id']);
396 $ieX->connectMailserver();
397 $GLOBALS['log']->info("Bounced campaign scheduler connected to mail server id: {$a['id']} ");
399 if ($ieX->isPop3Protocol()) {
400 $newMsgs = $ieX->getPop3NewMessagesToDownload();
402 $newMsgs = $ieX->getNewMessageIds();
405 //$newMsgs = $ieX->getNewMessageIds();
406 if(is_array($newMsgs)) {
407 foreach($newMsgs as $k => $msgNo) {
409 if ($ieX->isPop3Protocol()) {
410 $uid = $ieX->getUIDLForMessage($msgNo);
412 $uid = imap_uid($ieX->conn, $msgNo);
414 $GLOBALS['log']->info("Bounced campaign scheduler will import message no: $msgNo");
415 $ieX->importOneEmail($msgNo, $uid, false,false);
418 imap_expunge($ieX->conn);
419 imap_close($ieX->conn);
429 if (file_exists('custom/modules/Schedulers/_AddJobsHere.php')) {
430 require('custom/modules/Schedulers/_AddJobsHere.php');