晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
|
Server : Apache System : Linux srv.rainic.com 4.18.0-553.47.1.el8_10.x86_64 #1 SMP Wed Apr 2 05:45:37 EDT 2025 x86_64 User : rainic ( 1014) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/akaindir/www/crm/modules/Settings/MailConverter/handlers/ |
Upload File : |
<?php
/*********************************************************************************
** The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
*
********************************************************************************/
require_once('modules/Settings/MailConverter/handlers/MailBox.php');
require_once('modules/Settings/MailConverter/handlers/MailAttachmentMIME.php');
/**
* Mail Scanner provides the ability to scan through the given mailbox
* applying the rules configured.
*/
class Vtiger_MailScanner {
// MailScanner information instance
var $_scannerinfo = false;
// Reference mailbox to use
var $_mailbox = false;
// Ignore scanning the folders always
var $_generalIgnoreFolders = Array( "INBOX.Trash", "INBOX.Drafts", "[Gmail]/Spam", "[Gmail]/Trash", "[Gmail]/Drafts", "[Gmail]/Important", "[Gmail]/Starred", "[Gmail]/Sent Mail", "[Gmail]/All Mail");
/** DEBUG functionality. */
var $debug = false;
function log($message) {
global $log;
if($log && $this->debug) { $log->debug($message); }
else if($this->debug) echo "$message\n";
}
/**
* Constructor.
*/
function __construct($scannerinfo) {
$this->_scannerinfo = $scannerinfo;
}
/**
* Get mailbox instance configured for the scan
*/
function getMailBox() {
if(!$this->_mailbox) {
$this->_mailbox = new Vtiger_MailBox($this->_scannerinfo);
$this->_mailbox->debug = $this->debug;
}
return $this->_mailbox;
}
/**
* Start Scanning.
*/
function performScanNow() {
// Check if rules exists to proceed
$rules = $this->_scannerinfo->rules;
if(empty($rules)) {
$this->log("No rules setup for scanner [". $this->_scannerinfo->scannername . "] SKIPING\n");
return;
}
// Get mailbox instance to work with
$mailbox = $this->getMailBox();
$mailbox->connect();
/** Loop through all the folders. */
$folders = $mailbox->getFolders();
if(!is_array($folders)) {
return $folders;
}
// Build ignore folder list
$ignoreFolders = Array();
$folderinfoList = $this->_scannerinfo->getFolderInfo();
$allFolders = array_keys($folderinfoList);
foreach ($folders as $folder) {
if (!in_array($folder, $allFolders))
$ignoreFolders[] = $folder;
}
if ($folders)
$this->log("Folders found: " . implode(',', $folders) . "\n");
foreach($folders as $lookAtFolder) {
// Skip folder scanning?
if(in_array($lookAtFolder, $ignoreFolders)) {
$this->log("\nIgnoring Folder: $lookAtFolder\n");
continue;
}
// If a new folder has been added we should avoid scanning it
if(!isset($folderinfoList[$lookAtFolder])) {
$this->log("\nSkipping New Folder: $lookAtFolder\n");
continue;
}
// Search for mail in the folder
$mailsearch = $mailbox->search($lookAtFolder);
$this->log($mailsearch? "Total Mails Found in [$lookAtFolder]: " . count($mailsearch) : "No Mails Found in [$lookAtFolder]");
// No emails? Continue with next folder
if(empty($mailsearch)) continue;
// Loop through each of the email searched
foreach($mailsearch as $messageid) {
// Fetch only header part first, based on account lookup fetch the body.
$mailrecord = $mailbox->getMessage($messageid, false);
$mailrecord->debug = $mailbox->debug;
$mailrecord->log();
// If the email is already scanned & rescanning is not set, skip it
if($this->isMessageScanned($mailrecord, $lookAtFolder)) {
$this->log("\nMessage already scanned [$mailrecord->_subject], IGNORING...\n");
unset($mailrecord);
continue;
}
// Apply rules configured for the mailbox
$crmid = false;
foreach($rules as $mailscannerrule) {
$crmid = $this->applyRule($mailscannerrule, $mailrecord, $mailbox, $messageid);
if($crmid) {
break; // Rule was successfully applied and action taken
}
}
// Mark the email message as scanned
$this->markMessageScanned($mailrecord, $crmid);
$mailbox->markMessage($messageid);
/** Free the resources consumed. */
unset($mailrecord);
}
/* Update lastscan for this folder and reset rescan flag */
// TODO: Update lastscan only if all the mail searched was parsed successfully?
$rescanFolderFlag = false;
$this->updateLastScan($lookAtFolder, $rescanFolderFlag);
}
// Close the mailbox at end
$mailbox->close();
return true;
}
/**
* Apply all the rules configured for a mailbox on the mailrecord.
*/
function applyRule($mailscannerrule, $mailrecord, $mailbox, $messageid) {
// If no actions are set, don't proceed
if(empty($mailscannerrule->actions)) return false;
// Check if rule is defined for the body
$bodyrule = $mailscannerrule->hasBodyRule();
if($bodyrule) {
// We need the body part for rule evaluation
$mailrecord->fetchBody($mailbox->_imap, $messageid);
}
// Apply rule to check if record matches the criteria
$matchresult = $mailscannerrule->applyAll($mailrecord, $bodyrule);
// If record matches the conditions fetch body to take action.
$crmid = false;
if($matchresult) {
$mailrecord->fetchBody($mailbox->_imap, $messageid);
$crmid = $mailscannerrule->takeAction($this, $mailrecord, $matchresult);
}
// Return the CRMID
return $crmid;
}
/**
* Mark the email as scanned.
*/
function markMessageScanned($mailrecord, $crmid=false) {
global $adb;
if($crmid === false) $crmid = null;
// TODO Make sure we have unique entry
$adb->pquery("INSERT INTO vtiger_mailscanner_ids(scannerid, messageid, crmid) VALUES(?,?,?)",
Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid, $crmid));
}
/**
* Check if email was scanned.
*/
function isMessageScanned($mailrecord, $lookAtFolder) {
global $adb;
$messages = $adb->pquery("SELECT 1 FROM vtiger_mailscanner_ids WHERE scannerid=? AND messageid=?",
Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid));
$folderRescan = $this->_scannerinfo->needRescan($lookAtFolder);
$isScanned = false;
if($adb->num_rows($messages)) {
$isScanned = true;
// If folder is scheduled for rescan and earlier message was not acted upon?
$relatedCRMId = $adb->query_result($messages, 0, 'crmid');
if($folderRescan && empty($relatedCRMId)) {
$adb->pquery("DELETE FROM vtiger_mailscanner_ids WHERE scannerid=? AND messageid=?",
Array($this->_scannerinfo->scannerid, $mailrecord->_uniqueid));
$isScanned = false;
}
}
return $isScanned;
}
/**
* Update last scan on the folder.
*/
function updateLastscan($folder) {
$this->_scannerinfo->updateLastscan($folder);
}
/**
* Convert string to integer value.
* @param $strvalue
* @returns false if given contain non-digits, else integer value
*/
function __toInteger($strvalue) {
$ival = intval($strvalue);
$intvalstr = "$ival";
if(strlen($strvalue) == strlen($intvalstr)) {
return $ival;
}
return false;
}
/** Lookup functionality. */
var $_cachedContactIds = Array();
var $_cachedLeadIds = Array();
var $_cachedAccountIds = Array();
var $_cachedTicketIds = Array();
var $_cachedAccounts = Array();
var $_cachedContacts = Array();
var $_cachedLeads = Array();
var $_cachedTickets = Array();
/**
* Lookup Contact record based on the email given.
*/
function LookupContact($email) {
global $adb;
if($this->_cachedContactIds[$email]) {
$this->log("Reusing Cached Contact Id for email: $email");
return $this->_cachedContactIds[$email];
}
$contactid = false;
$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));
if($adb->num_rows($contactres)) {
$deleted = $adb->query_result($contactres, 0, 'deleted');
if ($deleted != 1) {
$contactid = $adb->query_result($contactres, 0, 'contactid');
}
}
if($contactid) {
$this->log("Caching Contact Id found for email: $email");
$this->_cachedContactIds[$email] = $contactid;
} else {
$this->log("No matching Contact found for email: $email");
}
return $contactid;
}
/**
* Lookup Lead record based on the email given.
*/
function LookupLead($email) {
global $adb;
if ($this->_cachedLeadIds[$email]) {
$this->log("Reusing Cached Lead Id for email: $email");
return $this->_cachedLeadIds[$email];
}
$leadid = false;
$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));
if ($adb->num_rows($leadres)) {
$deleted = $adb->query_result($leadres, 0, 'deleted');
if ($deleted != 1) {
$leadid = $adb->query_result($leadres, 0, 'leadid');
}
}
if ($leadid) {
$this->log("Caching Lead Id found for email: $email");
$this->_cachedLeadIds[$email] = $leadid;
} else {
$this->log("No matching Lead found for email: $email");
}
return $leadid;
}
/**
* Lookup Account record based on the email given.
*/
function LookupAccount($email) {
global $adb;
if($this->_cachedAccountIds[$email]) {
$this->log("Reusing Cached Account Id for email: $email");
return $this->_cachedAccountIds[$email];
}
$accountid = false;
$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));
if($adb->num_rows($accountres)) {
$deleted = $adb->query_result($accountres, 0, 'deleted');
if ($deleted != 1) {
$accountid = $adb->query_result($accountres, 0, 'accountid');
}
}
if($accountid) {
$this->log("Caching Account Id found for email: $email");
$this->_cachedAccountIds[$email] = $accountid;
} else {
$this->log("No matching Account found for email: $email");
}
return $accountid;
}
/**
* Lookup Ticket record based on the subject or id given.
*/
function LookupTicket($subjectOrId) {
global $adb;
$checkTicketId = $this->__toInteger($subjectOrId);
if(!$checkTicketId) {
$ticketres = $adb->pquery("SELECT ticketid FROM vtiger_troubletickets WHERE title = ? OR ticket_no = ?", Array($subjectOrId, $subjectOrId));
if($adb->num_rows($ticketres)) $checkTicketId = $adb->query_result($ticketres, 0, 'ticketid');
}
// Try with ticket_no before CRMID (case where ticket_no is also just number)
if(!$checkTicketId) {
$ticketres = $adb->pquery("SELECT ticketid FROM vtiger_troubletickets WHERE ticket_no = ?", Array($subjectOrId));
if($adb->num_rows($ticketres)) $checkTicketId = $adb->query_result($ticketres, 0, 'ticketid');
}
// Nothing found?
if(!$checkTicketId) return false;
if($this->_cachedTicketIds[$checkTicketId]) {
$this->log("Reusing Cached Ticket Id for: $subjectOrId");
return $this->_cachedTicketIds[$checkTicketId];
}
// Verify ticket is not deleted
$ticketid = false;
if($checkTicketId) {
$crmres = $adb->pquery("SELECT setype, deleted FROM vtiger_crmentity WHERE crmid=?", Array($checkTicketId));
if($adb->num_rows($crmres)) {
if($adb->query_result($crmres, 0, 'setype') == 'HelpDesk' &&
$adb->query_result($crmres, 0, 'deleted') == '0') $ticketid = $checkTicketId;
}
}
if($ticketid) {
$this->log("Caching Ticket Id found for: $subjectOrId");
$this->_cachedTicketIds[$checkTicketId] = $ticketid;
} else {
$this->log("No matching Ticket found for: $subjectOrId");
}
return $ticketid;
}
/**
* Get Account record information based on email.
*/
function GetAccountRecord($email, $accountid = false) {
require_once('modules/Accounts/Accounts.php');
if(!$accountid)
$accountid = $this->LookupAccount($email);
$account_focus = false;
if($accountid) {
if($this->_cachedAccounts[$accountid]) {
$account_focus = $this->_cachedAccounts[$accountid];
$this->log("Reusing Cached Account [" . $account_focus->column_fields[accountname] . "]");
} else {
$account_focus = CRMEntity::getInstance('Accounts');
$account_focus->retrieve_entity_info($accountid, 'Accounts');
$account_focus->id = $accountid;
$this->log("Caching Account [" . $account_focus->column_fields[accountname] . "]");
$this->_cachedAccounts[$accountid] = $account_focus;
}
}
return $account_focus;
}
/**
* Get Contact record information based on email.
*/
function GetContactRecord($email, $contactid = false) {
require_once('modules/Contacts/Contacts.php');
if(!$contactid)
$contactid = $this->LookupContact($email);
$contact_focus = false;
if($contactid) {
if($this->_cachedContacts[$contactid]) {
$contact_focus = $this->_cachedContacts[$contactid];
$this->log("Reusing Cached Contact [" . $contact_focus->column_fields[lastname] .
'-' . $contact_focus->column_fields[firstname] . "]");
} else {
$contact_focus = CRMEntity::getInstance('Contacts');
$contact_focus->retrieve_entity_info($contactid, 'Contacts');
$contact_focus->id = $contactid;
$this->log("Caching Contact [" . $contact_focus->column_fields[lastname] .
'-' . $contact_focus->column_fields[firstname] . "]");
$this->_cachedContacts[$contactid] = $contact_focus;
}
}
return $contact_focus;
}
/**
* Get Lead record information based on email.
*/
function GetLeadRecord($email) {
require_once('modules/Leads/Leads.php');
$leadid = $this->LookupLead($email);
$lead_focus = false;
if ($leadid) {
if ($this->_cachedLeads[$leadid]) {
$lead_focus = $this->_cachedLeads[$leadid];
$this->log("Reusing Cached Lead [" . $lead_focus->column_fields[lastname] .
'-' . $lead_focus->column_fields[firstname] . "]");
} else {
$lead_focus = CRMEntity::getInstance('Leads');
$lead_focus->retrieve_entity_info($leadid, 'Leads');
$lead_focus->id = $leadid;
$this->log("Caching Lead [" . $lead_focus->column_fields[lastname] .
'-' . $lead_focus->column_fields[firstname] . "]");
$this->_cachedLeads[$leadid] = $lead_focus;
}
}
return $lead_focus;
}
/**
* Lookup Contact or Account based on from email and with respect to given CRMID
*/
function LookupContactOrAccount($fromemail, $checkWith) {
$recordid = $this->LookupContact($fromemail);
if ($checkWith['contact_id'] && $recordid != $checkWith['contact_id']) {
$recordid = $this->LookupAccount($fromemail);
if (($checkWith['parent_id'] && $recordid != $checkWith['parent_id']))
$recordid = false;
}
return $recordid;
}
/**
* Get Ticket record information based on subject or id.
*/
function GetTicketRecord($subjectOrId, $fromemail=false) {
require_once('modules/HelpDesk/HelpDesk.php');
$ticketid = $this->LookupTicket($subjectOrId);
$ticket_focus = false;
if($ticketid) {
if($this->_cachedTickets[$ticketid]) {
$ticket_focus = $this->_cachedTickets[$ticketid];
// Check the parentid association if specified.
if ($fromemail && !$this->LookupContactOrAccount($fromemail, $ticket_focus->column_fields)) {
$ticket_focus = false;
}
if($ticket_focus) {
$this->log("Reusing Cached Ticket [" . $ticket_focus->column_fields[ticket_title] ."]");
}
} else {
$ticket_focus = CRMEntity::getInstance('HelpDesk');
$ticket_focus->retrieve_entity_info($ticketid, 'HelpDesk');
$ticket_focus->id = $ticketid;
// Check the parentid association if specified.
if ($fromemail && !$this->LookupContactOrAccount($fromemail, $ticket_focus->column_fields)) {
$ticket_focus = false;
}
if($ticket_focus) {
$this->log("Caching Ticket [" . $ticket_focus->column_fields[ticket_title] . "]");
$this->_cachedTickets[$ticketid] = $ticket_focus;
}
}
}
return $ticket_focus;
}
function getAccountId($contactId) {
global $adb;
$result = $adb->pquery("SELECT accountid FROM vtiger_contactdetails WHERE contactid=?", array($contactId));
$accountId = $adb->query_result($result, 0, 'accountid');
return $accountId;
}
function disableMailScanner(){
global $adb;
$scannerId = $this->_scannerinfo->scannerid;
$adb->pquery("UPDATE vtiger_mailscanner SET isvalid=? WHERE scannerid=?", array(0,$scannerId));
}
}
?>