[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/modules/Settings/MailConverter/handlers/ -> MailScanner.php (source)

   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  ?>


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1