[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /********************************************************************************* 3 ** The contents of this file are subject to the vtiger CRM Public License Version 1.0 4 * ("License"); You may not use this file except in compliance with the License 5 * The Original Code is: vtiger CRM Open Source 6 * The Initial Developer of the Original Code is vtiger. 7 * Portions created by vtiger are Copyright (C) vtiger. 8 * All Rights Reserved. 9 * 10 ********************************************************************************/ 11 12 require_once ('modules/Settings/MailConverter/handlers/MailBox.php'); 13 require_once ('modules/Settings/MailConverter/handlers/MailAttachmentMIME.php'); 14 15 /** 16 * Mail Scanner provides the ability to scan through the given mailbox 17 * applying the rules configured. 18 */ 19 class Vtiger_MailScanner { 20 // MailScanner information instance 21 var $_scannerinfo = false; 22 // Reference mailbox to use 23 var $_mailbox = false; 24 25 // Ignore scanning the folders always 26 var $_generalIgnoreFolders = Array( "INBOX.Trash", "INBOX.Drafts", "[Gmail]/Spam", "[Gmail]/Trash", "[Gmail]/Drafts", "[Gmail]/Important", "[Gmail]/Starred", "[Gmail]/Sent Mail", "[Gmail]/All Mail"); 27 28 /** DEBUG functionality. */ 29 var $debug = false; 30 function log($message) { 31 global $log; 32 if($log && $this->debug) { $log->debug($message); } 33 else if($this->debug) echo "$message\n"; 34 } 35 36 /** 37 * Constructor. 38 */ 39 function __construct($scannerinfo) { 40 $this->_scannerinfo = $scannerinfo; 41 } 42 43 /** 44 * Get mailbox instance configured for the scan 45 */ 46 function getMailBox() { 47 if(!$this->_mailbox) { 48 $this->_mailbox = new Vtiger_MailBox($this->_scannerinfo); 49 $this->_mailbox->debug = $this->debug; 50 } 51 return $this->_mailbox; 52 } 53 54 /** 55 * Start Scanning. 56 */ 57 function performScanNow() { 58 // Check if rules exists to proceed 59 $rules = $this->_scannerinfo->rules; 60 61 if(empty($rules)) { 62 $this->log("No rules setup for scanner [". $this->_scannerinfo->scannername . "] SKIPING\n"); 63 return; 64 } 65 66 // Get mailbox instance to work with 67 $mailbox = $this->getMailBox(); 68 $mailbox->connect(); 69 70 /** Loop through all the folders. */ 71 $folders = $mailbox->getFolders(); 72 if(!is_array($folders)) { 73 return $folders; 74 } 75 76 // Build ignore folder list 77 $ignoreFolders = Array(); 78 $folderinfoList = $this->_scannerinfo->getFolderInfo(); 79 $allFolders = array_keys($folderinfoList); 80 foreach ($folders as $folder) { 81 if (!in_array($folder, $allFolders)) 82 $ignoreFolders[] = $folder; 83 } 84 85 if ($folders) 86 $this->log("Folders found: " . implode(',', $folders) . "\n"); 87 88 foreach($folders as $lookAtFolder) { 89 // Skip folder scanning? 90 if(in_array($lookAtFolder, $ignoreFolders)) { 91 $this->log("\nIgnoring Folder: $lookAtFolder\n"); 92 continue; 93 } 94 // If a new folder has been added we should avoid scanning it 95 if(!isset($folderinfoList[$lookAtFolder])) { 96 $this->log("\nSkipping New Folder: $lookAtFolder\n"); 97 continue; 98 } 99 100 // Search for mail in the folder 101 $mailsearch = $mailbox->search($lookAtFolder); 102 $this->log($mailsearch? "Total Mails Found in [$lookAtFolder]: " . count($mailsearch) : "No Mails Found in [$lookAtFolder]"); 103 104 // No emails? Continue with next folder 105 if(empty($mailsearch)) continue; 106 107 // Loop through each of the email searched 108 foreach($mailsearch as $messageid) { 109 // Fetch only header part first, based on account lookup fetch the body. 110 $mailrecord = $mailbox->getMessage($messageid, false); 111 $mailrecord->debug = $mailbox->debug; 112 $mailrecord->log(); 113 114 // If the email is already scanned & rescanning is not set, skip it 115 if($this->isMessageScanned($mailrecord, $lookAtFolder)) { 116 $this->log("\nMessage already scanned [$mailrecord->_subject], IGNORING...\n"); 117 unset($mailrecord); 118 continue; 119 } 120 121 // Apply rules configured for the mailbox 122 $crmid = false; 123 foreach($rules as $mailscannerrule) { 124 $crmid = $this->applyRule($mailscannerrule, $mailrecord, $mailbox, $messageid); 125 if($crmid) { 126 break; // Rule was successfully applied and action taken 127 } 128 } 129 // Mark the email message as scanned 130 $this->markMessageScanned($mailrecord, $crmid); 131 $mailbox->markMessage($messageid); 132 133 /** Free the resources consumed. */ 134 unset($mailrecord); 135 } 136 /* Update lastscan for this folder and reset rescan flag */ 137 // TODO: Update lastscan only if all the mail searched was parsed successfully? 138 $rescanFolderFlag = false; 139 $this->updateLastScan($lookAtFolder, $rescanFolderFlag); 140 } 141 // Close the mailbox at end 142 $mailbox->close(); 143 return true; 144 } 145 146 /** 147 * Apply all the rules configured for a mailbox on the mailrecord. 148 */ 149 function applyRule($mailscannerrule, $mailrecord, $mailbox, $messageid) { 150 // If no actions are set, don't proceed 151 if(empty($mailscannerrule->actions)) return false; 152 153 // Check if rule is defined for the body 154 $bodyrule = $mailscannerrule->hasBodyRule(); 155 156 if($bodyrule) { 157 // We need the body part for rule evaluation 158 $mailrecord->fetchBody($mailbox->_imap, $messageid); 159 } 160 161 // Apply rule to check if record matches the criteria 162 $matchresult = $mailscannerrule->applyAll($mailrecord, $bodyrule); 163 164 // If record matches the conditions fetch body to take action. 165 $crmid = false; 166 if($matchresult) { 167 $mailrecord->fetchBody($mailbox->_imap, $messageid); 168 $crmid = $mailscannerrule->takeAction($this, $mailrecord, $matchresult); 169 } 170 // Return the CRMID 171 return $crmid; 172 } 173 174 /** 175 * Mark the email as scanned. 176 */ 177 function markMessageScanned($mailrecord, $crmid=false) { 178 global $adb; 179 if($crmid === false) $crmid = null; 180 // TODO Make sure we have unique entry 181 $adb->pquery("INSERT INTO vtiger_mailscanner_ids(scannerid, messageid, crmid) VALUES(?,?,?)", 182 Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid, $crmid)); 183 } 184 185 /** 186 * Check if email was scanned. 187 */ 188 function isMessageScanned($mailrecord, $lookAtFolder) { 189 global $adb; 190 $messages = $adb->pquery("SELECT 1 FROM vtiger_mailscanner_ids WHERE scannerid=? AND messageid=?", 191 Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid)); 192 193 $folderRescan = $this->_scannerinfo->needRescan($lookAtFolder); 194 $isScanned = false; 195 196 if($adb->num_rows($messages)) { 197 $isScanned = true; 198 199 // If folder is scheduled for rescan and earlier message was not acted upon? 200 $relatedCRMId = $adb->query_result($messages, 0, 'crmid'); 201 202 if($folderRescan && empty($relatedCRMId)) { 203 $adb->pquery("DELETE FROM vtiger_mailscanner_ids WHERE scannerid=? AND messageid=?", 204 Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid)); 205 $isScanned = false; 206 } 207 } 208 return $isScanned; 209 } 210 211 /** 212 * Update last scan on the folder. 213 */ 214 function updateLastscan($folder) { 215 $this->_scannerinfo->updateLastscan($folder); 216 } 217 218 /** 219 * Convert string to integer value. 220 * @param $strvalue 221 * @returns false if given contain non-digits, else integer value 222 */ 223 function __toInteger($strvalue) { 224 $ival = intval($strvalue); 225 $intvalstr = "$ival"; 226 if(strlen($strvalue) == strlen($intvalstr)) { 227 return $ival; 228 } 229 return false; 230 } 231 232 /** Lookup functionality. */ 233 var $_cachedContactIds = Array(); 234 var $_cachedLeadIds = Array(); 235 var $_cachedAccountIds = Array(); 236 var $_cachedTicketIds = Array(); 237 var $_cachedAccounts = Array(); 238 var $_cachedContacts = Array(); 239 var $_cachedLeads = Array(); 240 var $_cachedTickets = Array(); 241 242 /** 243 * Lookup Contact record based on the email given. 244 */ 245 function LookupContact($email) { 246 global $adb; 247 if($this->_cachedContactIds[$email]) { 248 $this->log("Reusing Cached Contact Id for email: $email"); 249 return $this->_cachedContactIds[$email]; 250 } 251 $contactid = false; 252 $contactres = $adb->pquery("SELECT contactid FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON crmid = contactid WHERE setype = ? AND email = ? AND deleted = ?", array('Contacts', $email, 0)); 253 if($adb->num_rows($contactres)) { 254 $deleted = $adb->query_result($contactres, 0, 'deleted'); 255 if ($deleted != 1) { 256 $contactid = $adb->query_result($contactres, 0, 'contactid'); 257 } 258 } 259 if($contactid) { 260 $this->log("Caching Contact Id found for email: $email"); 261 $this->_cachedContactIds[$email] = $contactid; 262 } else { 263 $this->log("No matching Contact found for email: $email"); 264 } 265 return $contactid; 266 } 267 268 /** 269 * Lookup Lead record based on the email given. 270 */ 271 function LookupLead($email) { 272 global $adb; 273 if ($this->_cachedLeadIds[$email]) { 274 $this->log("Reusing Cached Lead Id for email: $email"); 275 return $this->_cachedLeadIds[$email]; 276 } 277 $leadid = false; 278 $leadres = $adb->pquery("SELECT leadid FROM vtiger_leaddetails INNER JOIN vtiger_crmentity ON crmid = leadid WHERE setype=? AND email = ? AND converted = ? AND deleted = ?", array('Leads', $email, 0, 0)); 279 if ($adb->num_rows($leadres)) { 280 $deleted = $adb->query_result($leadres, 0, 'deleted'); 281 if ($deleted != 1) { 282 $leadid = $adb->query_result($leadres, 0, 'leadid'); 283 } 284 } 285 if ($leadid) { 286 $this->log("Caching Lead Id found for email: $email"); 287 $this->_cachedLeadIds[$email] = $leadid; 288 } else { 289 $this->log("No matching Lead found for email: $email"); 290 } 291 return $leadid; 292 } 293 294 /** 295 * Lookup Account record based on the email given. 296 */ 297 function LookupAccount($email) { 298 global $adb; 299 if($this->_cachedAccountIds[$email]) { 300 $this->log("Reusing Cached Account Id for email: $email"); 301 return $this->_cachedAccountIds[$email]; 302 } 303 304 $accountid = false; 305 $accountres = $adb->pquery("SELECT accountid FROM vtiger_account INNER JOIN vtiger_crmentity ON crmid = accountid WHERE setype=? AND (email1 = ? OR email2 = ?) AND deleted = ?", Array('Accounts', $email, $email, 0)); 306 if($adb->num_rows($accountres)) { 307 $deleted = $adb->query_result($accountres, 0, 'deleted'); 308 if ($deleted != 1) { 309 $accountid = $adb->query_result($accountres, 0, 'accountid'); 310 } 311 } 312 if($accountid) { 313 $this->log("Caching Account Id found for email: $email"); 314 $this->_cachedAccountIds[$email] = $accountid; 315 } else { 316 $this->log("No matching Account found for email: $email"); 317 } 318 return $accountid; 319 } 320 321 /** 322 * Lookup Ticket record based on the subject or id given. 323 */ 324 function LookupTicket($subjectOrId) { 325 global $adb; 326 327 $checkTicketId = $this->__toInteger($subjectOrId); 328 if(!$checkTicketId) { 329 $ticketres = $adb->pquery("SELECT ticketid FROM vtiger_troubletickets WHERE title = ? OR ticket_no = ?", Array($subjectOrId, $subjectOrId)); 330 if($adb->num_rows($ticketres)) $checkTicketId = $adb->query_result($ticketres, 0, 'ticketid'); 331 } 332 // Try with ticket_no before CRMID (case where ticket_no is also just number) 333 if(!$checkTicketId) { 334 $ticketres = $adb->pquery("SELECT ticketid FROM vtiger_troubletickets WHERE ticket_no = ?", Array($subjectOrId)); 335 if($adb->num_rows($ticketres)) $checkTicketId = $adb->query_result($ticketres, 0, 'ticketid'); 336 } 337 // Nothing found? 338 if(!$checkTicketId) return false; 339 340 if($this->_cachedTicketIds[$checkTicketId]) { 341 $this->log("Reusing Cached Ticket Id for: $subjectOrId"); 342 return $this->_cachedTicketIds[$checkTicketId]; 343 } 344 345 // Verify ticket is not deleted 346 $ticketid = false; 347 if($checkTicketId) { 348 $crmres = $adb->pquery("SELECT setype, deleted FROM vtiger_crmentity WHERE crmid=?", Array($checkTicketId)); 349 if($adb->num_rows($crmres)) { 350 if($adb->query_result($crmres, 0, 'setype') == 'HelpDesk' && 351 $adb->query_result($crmres, 0, 'deleted') == '0') $ticketid = $checkTicketId; 352 } 353 } 354 if($ticketid) { 355 $this->log("Caching Ticket Id found for: $subjectOrId"); 356 $this->_cachedTicketIds[$checkTicketId] = $ticketid; 357 } else { 358 $this->log("No matching Ticket found for: $subjectOrId"); 359 } 360 return $ticketid; 361 } 362 363 /** 364 * Get Account record information based on email. 365 */ 366 function GetAccountRecord($email, $accountid = false) { 367 require_once ('modules/Accounts/Accounts.php'); 368 if(!$accountid) 369 $accountid = $this->LookupAccount($email); 370 $account_focus = false; 371 if($accountid) { 372 if($this->_cachedAccounts[$accountid]) { 373 $account_focus = $this->_cachedAccounts[$accountid]; 374 $this->log("Reusing Cached Account [" . $account_focus->column_fields[accountname] . "]"); 375 } else { 376 $account_focus = new Accounts(); 377 $account_focus->retrieve_entity_info($accountid, 'Accounts'); 378 $account_focus->id = $accountid; 379 380 $this->log("Caching Account [" . $account_focus->column_fields[accountname] . "]"); 381 $this->_cachedAccounts[$accountid] = $account_focus; 382 } 383 } 384 return $account_focus; 385 } 386 387 /** 388 * Get Contact record information based on email. 389 */ 390 function GetContactRecord($email, $contactid = false) { 391 require_once ('modules/Contacts/Contacts.php'); 392 if(!$contactid) 393 $contactid = $this->LookupContact($email); 394 $contact_focus = false; 395 if($contactid) { 396 if($this->_cachedContacts[$contactid]) { 397 $contact_focus = $this->_cachedContacts[$contactid]; 398 $this->log("Reusing Cached Contact [" . $contact_focus->column_fields[lastname] . 399 '-' . $contact_focus->column_fields[firstname] . "]"); 400 } else { 401 $contact_focus = new Contacts(); 402 $contact_focus->retrieve_entity_info($contactid, 'Contacts'); 403 $contact_focus->id = $contactid; 404 405 $this->log("Caching Contact [" . $contact_focus->column_fields[lastname] . 406 '-' . $contact_focus->column_fields[firstname] . "]"); 407 $this->_cachedContacts[$contactid] = $contact_focus; 408 } 409 } 410 return $contact_focus; 411 } 412 413 /** 414 * Get Lead record information based on email. 415 */ 416 function GetLeadRecord($email) { 417 require_once ('modules/Leads/Leads.php'); 418 $leadid = $this->LookupLead($email); 419 $lead_focus = false; 420 if ($leadid) { 421 if ($this->_cachedLeads[$leadid]) { 422 $lead_focus = $this->_cachedLeads[$leadid]; 423 $this->log("Reusing Cached Lead [" . $lead_focus->column_fields[lastname] . 424 '-' . $lead_focus->column_fields[firstname] . "]"); 425 } else { 426 $lead_focus = new Leads(); 427 $lead_focus->retrieve_entity_info($leadid, 'Leads'); 428 $lead_focus->id = $leadid; 429 430 $this->log("Caching Lead [" . $lead_focus->column_fields[lastname] . 431 '-' . $lead_focus->column_fields[firstname] . "]"); 432 $this->_cachedLeads[$leadid] = $lead_focus; 433 } 434 } 435 return $lead_focus; 436 } 437 438 /** 439 * Lookup Contact or Account based on from email and with respect to given CRMID 440 */ 441 function LookupContactOrAccount($fromemail, $checkWith) { 442 $recordid = $this->LookupContact($fromemail); 443 if ($checkWith['contact_id'] && $recordid != $checkWith['contact_id']) { 444 $recordid = $this->LookupAccount($fromemail); 445 if (($checkWith['parent_id'] && $recordid != $checkWith['parent_id'])) 446 $recordid = false; 447 } 448 return $recordid; 449 } 450 451 /** 452 * Get Ticket record information based on subject or id. 453 */ 454 function GetTicketRecord($subjectOrId, $fromemail=false) { 455 require_once ('modules/HelpDesk/HelpDesk.php'); 456 $ticketid = $this->LookupTicket($subjectOrId); 457 $ticket_focus = false; 458 if($ticketid) { 459 if($this->_cachedTickets[$ticketid]) { 460 $ticket_focus = $this->_cachedTickets[$ticketid]; 461 // Check the parentid association if specified. 462 if ($fromemail && !$this->LookupContactOrAccount($fromemail, $ticket_focus->column_fields)) { 463 $ticket_focus = false; 464 } 465 if($ticket_focus) { 466 $this->log("Reusing Cached Ticket [" . $ticket_focus->column_fields[ticket_title] ."]"); 467 } 468 } else { 469 $ticket_focus = new HelpDesk(); 470 $ticket_focus->retrieve_entity_info($ticketid, 'HelpDesk'); 471 $ticket_focus->id = $ticketid; 472 // Check the parentid association if specified. 473 if ($fromemail && !$this->LookupContactOrAccount($fromemail, $ticket_focus->column_fields)) { 474 $ticket_focus = false; 475 } 476 if($ticket_focus) { 477 $this->log("Caching Ticket [" . $ticket_focus->column_fields[ticket_title] . "]"); 478 $this->_cachedTickets[$ticketid] = $ticket_focus; 479 } 480 } 481 } 482 return $ticket_focus; 483 } 484 485 function getAccountId($contactId) { 486 global $adb; 487 $result = $adb->pquery("SELECT accountid FROM vtiger_contactdetails WHERE contactid=?", array($contactId)); 488 $accountId = $adb->query_result($result, 0, 'accountid'); 489 return $accountId; 490 } 491 492 function disableMailScanner(){ 493 global $adb; 494 $scannerId = $this->_scannerinfo->scannerid; 495 $adb->pquery("UPDATE vtiger_mailscanner SET isvalid=? WHERE scannerid=?", array(0,$scannerId)); 496 } 497 498 } 499 500 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |