- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
429 lines
12 KiB
PHP
429 lines
12 KiB
PHP
<?php
|
|
/*+**********************************************************************************
|
|
* The contents of this file are subject to the vtiger CRM Public License Version 1.1
|
|
* ("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.
|
|
************************************************************************************/
|
|
|
|
vimport ('~modules/MailManager/models/Message.php');
|
|
|
|
class MailManager_Connector_Connector {
|
|
|
|
/*
|
|
* Cache interval time
|
|
*/
|
|
static $DB_CACHE_CLEAR_INTERVAL = "-1 day"; // strtotime
|
|
|
|
/*
|
|
* Mail Box URL
|
|
*/
|
|
public $mBoxUrl;
|
|
|
|
/*
|
|
* Mail Box connection instance
|
|
*/
|
|
public $mBox;
|
|
|
|
/*
|
|
* Last imap error
|
|
*/
|
|
protected $mError;
|
|
|
|
/*
|
|
* Mail Box folders
|
|
*/
|
|
protected $mFolders = false;
|
|
|
|
/**
|
|
* Modified Time of the mail
|
|
*/
|
|
protected $mModified = false;
|
|
|
|
/*
|
|
* Base URL of the Mail Box excluding folder name
|
|
*/
|
|
protected $mBoxBaseUrl;
|
|
|
|
|
|
/**
|
|
* Connects to the Imap server with the given parameters
|
|
* @param $model MailManager_Model_Mailbox Instance
|
|
* $param $folder String optional - mail box folder name
|
|
* @returns MailManager_Connector Object
|
|
*/
|
|
public static function connectorWithModel($model, $folder='') {
|
|
$port = 143; // IMAP
|
|
if (strcasecmp($model->protocol(), 'pop') === 0) $port = 110; // NOT IMPLEMENTED
|
|
else if (strcasecmp($model->ssltype(), 'ssl') === 0) $port = 993; // IMAP SSL
|
|
|
|
$url = sprintf('{%s:%s/%s/%s/%s}%s', $model->server(), $port, $model->protocol(),
|
|
$model->ssltype(), $model->certvalidate(), $folder);
|
|
$baseUrl = sprintf('{%s:%s/%s/%s/%s}', $model->server(), $port, $model->protocol(),
|
|
$model->ssltype(), $model->certvalidate());
|
|
return new self($url, $model->username(), $model->password(), $baseUrl, $model->serverName());
|
|
}
|
|
|
|
|
|
/**
|
|
* Opens up imap connection to the specified url
|
|
* @param $url String - mail server url
|
|
* @param $username String - user name of the mail box
|
|
* @param $password String - pass word of the mail box
|
|
* @param $baseUrl Optional - url of the mailserver excluding folder name.
|
|
* This is used to fetch the folders of the mail box
|
|
*/
|
|
public function __construct($url, $username, $password, $baseUrl=false, $serverName = '') {
|
|
$boxUrl = $this->convertCharacterEncoding(html_entity_decode($url),'UTF7-IMAP','UTF-8'); //handle both utf8 characters and html entities
|
|
$this->mBoxUrl = $boxUrl;
|
|
$this->mBoxBaseUrl = $baseUrl; // Used for folder List
|
|
|
|
/**
|
|
* disabled Kerberos authentication
|
|
* reference : http://sugarcrmsolutions.blogspot.in/2013/12/problems-in-email-integration.html
|
|
*/
|
|
|
|
if($serverName == 'gmail') {
|
|
$this->mBox = @imap_open($boxUrl, $username, $password);
|
|
} else {
|
|
$this->mBox = @imap_open($boxUrl, $username, $password, NULL, 1, array('DISABLE_AUTHENTICATOR' => 'GSSAPI'));
|
|
}
|
|
|
|
$this->isError();
|
|
}
|
|
|
|
|
|
/**
|
|
* Closes the connection
|
|
*/
|
|
public function __destruct() {
|
|
$this->close();
|
|
}
|
|
|
|
|
|
/**
|
|
* Closes the imap connection
|
|
*/
|
|
public function close() {
|
|
if (!empty($this->mBox)) {
|
|
|
|
if ($this->mModified) imap_close($this->mBox, CL_EXPUNGE);
|
|
else imap_close($this->mBox);
|
|
|
|
$this->mBox = null;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks for the connection
|
|
*/
|
|
public function isConnected() {
|
|
return !empty($this->mBox);
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the last imap error
|
|
*/
|
|
public function isError() {
|
|
$errors = imap_errors();
|
|
if($errors !== false) {
|
|
$this->mError = implode(', ',$errors);
|
|
} else {
|
|
$this->mError = imap_last_error();
|
|
}
|
|
|
|
return $this->hasError();
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if the error exists
|
|
*/
|
|
public function hasError() {
|
|
return !empty($this->mError);
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the error
|
|
*/
|
|
public function lastError() {
|
|
return $this->mError;
|
|
}
|
|
|
|
|
|
/**
|
|
* Reads mail box folders
|
|
* @param string $ref Optional -
|
|
*/
|
|
public function folders($ref="{folder}") {
|
|
if ($this->mFolders) return $this->mFolders;
|
|
|
|
$result = imap_getmailboxes($this->mBox, $ref, "*");
|
|
if ($this->isError()) return false;
|
|
|
|
$folders = array();
|
|
foreach($result as $row) {
|
|
$folderName = str_replace($ref, "", $row->name);
|
|
$folder = $this->convertCharacterEncoding( $folderName, "UTF-8", "UTF7-IMAP" ); //Decode folder name
|
|
$folders[] = $this->folderInstance($folder);
|
|
}
|
|
$this->mFolders = $folders;
|
|
return $folders;
|
|
}
|
|
|
|
|
|
/**
|
|
* Used to update the folders optionus
|
|
* @param imap_stats flag $options
|
|
*/
|
|
public function updateFolders($options=SA_UNSEEN) {
|
|
$this->folders(); // Initializes the folder Instance
|
|
foreach($this->mFolders as $folder) {
|
|
$this->updateFolder($folder, $options);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Updates the mail box's folder
|
|
* @param MailManager_Model_Folder $folder - folder instance
|
|
* @param $options imap_status flags like SA_UNSEEN, SA_MESSAGES etc
|
|
*/
|
|
public function updateFolder($folder, $options) {
|
|
$mailbox = $this->convertCharacterEncoding($folder->name($this->mBoxUrl), "UTF7-IMAP","ISO-8859-1"); //Encode folder name
|
|
$result = @imap_status($this->mBox, $mailbox, $options);
|
|
if ($result) {
|
|
if (isset($result->unseen)) $folder->setUnreadCount($result->unseen);
|
|
if (isset($result->messages)) $folder->setCount($result->messages);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns MailManager_Model_Folder Instance
|
|
* @param String $name - folder name
|
|
*/
|
|
public function folderInstance($name) {
|
|
vimport('modules/MailManager/models/Folder.php');
|
|
return new MailManager_Folder_Model($name);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets a list of mails with paging
|
|
* @param String $folder - MailManager_Model_Folder Instance
|
|
* @param Integer $start - Page number
|
|
* @param Integer $maxLimit - Number of mails
|
|
*/
|
|
public function folderMails($folder, $start, $maxLimit) {
|
|
$folderCheck = @imap_check($this->mBox);
|
|
if ($folderCheck->Nmsgs) {
|
|
|
|
$reverse_start = $folderCheck->Nmsgs - ($start*$maxLimit);
|
|
$reverse_end = $reverse_start - $maxLimit + 1;
|
|
|
|
if ($reverse_start < 1) $reverse_start = 1;
|
|
if ($reverse_end < 1) $reverse_end = 1;
|
|
|
|
$sequence = sprintf("%s:%s", $reverse_start, $reverse_end);
|
|
|
|
$records = imap_fetch_overview($this->mBox, $sequence);
|
|
$mails = array();
|
|
$mailIds = array();
|
|
|
|
// to make sure this should not break in Vtiger6
|
|
$layout = Vtiger_Viewer::getDefaultLayoutName();
|
|
if($layout == "v7"){
|
|
$mbox = false;
|
|
} else {
|
|
$mbox = $this->mBox;
|
|
}
|
|
|
|
foreach($records as $result) {
|
|
$message = MailManager_Message_Model::parseOverview($result,$mbox);
|
|
$mailIds[] = $message->msgNo();
|
|
array_unshift($mails, $message);
|
|
}
|
|
$folder->setMails($mails);
|
|
$folder->setMailIds($mailIds);
|
|
$folder->setPaging($reverse_end, $reverse_start, $maxLimit, $folderCheck->Nmsgs, $start);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Return the cache interval
|
|
*/
|
|
public function clearDBCacheInterval() {
|
|
// TODO Provide configuration option.
|
|
if (self::$DB_CACHE_CLEAR_INTERVAL) {
|
|
return strtotime(self::$DB_CACHE_CLEAR_INTERVAL);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Clears the cache data
|
|
*/
|
|
public function clearDBCache() {
|
|
// Trigger purne any older mail saved in DB first
|
|
$interval = $this->clearDBCacheInterval();
|
|
|
|
$timenow = strtotime("now");
|
|
|
|
// Optimization to avoid trigger for ever mail open (with interval specified)
|
|
$lastClearTimeFromSession = false;
|
|
if ($interval && isset($_SESSION) && isset($_SESSION['mailmanager_clearDBCacheIntervalLast'])) {
|
|
$lastClearTimeFromSession = intval($_SESSION['mailmanager_clearDBCacheIntervalLast']);
|
|
if (($timenow - $lastClearTimeFromSession) < ($timenow - $interval)) {
|
|
$interval = false;
|
|
}
|
|
}
|
|
if ($interval) {
|
|
MailManager_Message_Model::pruneOlderInDB($interval);
|
|
$_SESSION['mailmanager_clearDBCacheIntervalLast'] = $timenow;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Function which deletes the mails
|
|
* @param String $msgno - List of message number seperated by commas.
|
|
*/
|
|
public function deleteMail($msgno) {
|
|
$msgno = trim($msgno,',');
|
|
$msgno = explode(',',$msgno);
|
|
for($i = 0;$i<php7_count($msgno);$i++) {
|
|
@imap_delete($this->mBox, $msgno[$i]);
|
|
}
|
|
imap_expunge($this->mBox);
|
|
}
|
|
|
|
|
|
/**
|
|
* Function which moves mail to another folder
|
|
* @param String $msgno - List of message number separated by commas
|
|
* @param String $folderName - folder name
|
|
*/
|
|
public function moveMail($msgno, $folderName) {
|
|
$msgno = trim($msgno,',');
|
|
$msgno = explode(',',$msgno);
|
|
$folder = $this->convertCharacterEncoding(html_entity_decode($folderName),'UTF7-IMAP','UTF-8'); //handle both utf8 characters and html entities
|
|
for($i = 0;$i<php7_count($msgno);$i++) {
|
|
@imap_mail_move($this->mBox, $msgno[$i], $folder);
|
|
}
|
|
@imap_expunge($this->mBox);
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates an instance of Message
|
|
* @param String $msgno - Message number
|
|
* @return MailManager_Model_Message
|
|
*/
|
|
public function openMail($msgno, $folder) {
|
|
$this->clearDBCache();
|
|
return new MailManager_Message_Model($this->mBox, $msgno, true, $folder);
|
|
}
|
|
|
|
|
|
/**
|
|
* Marks the mail as Unread
|
|
* @param <String> $msgno - Message Number
|
|
*/
|
|
public function markMailUnread($msgno) {
|
|
imap_clearflag_full( $this->mBox, $msgno, '\\Seen');
|
|
$this->mModified = true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Marks the mail as Read
|
|
* @param String $msgno - Message Number
|
|
*/
|
|
public function markMailRead($msgno) {
|
|
imap_setflag_full($this->mBox, $msgno, '\\Seen');
|
|
$this->mModified = true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Searches the Mail Box with the query
|
|
* @param String $query - imap search format
|
|
* @param MailManager_Model_Folder $folder - folder instance
|
|
* @param Integer $start - Page number
|
|
* @param Integer $maxLimit - Number of mails
|
|
*/
|
|
public function searchMails($query, $folder, $start, $maxLimit) {
|
|
$nos = imap_search($this->mBox, $query);
|
|
|
|
if (!empty($nos)) {
|
|
$nmsgs = php7_count($nos);
|
|
|
|
$reverse_start = $nmsgs - ($start*$maxLimit);
|
|
$reverse_end = $reverse_start - $maxLimit;
|
|
|
|
if ($reverse_start < 1) $reverse_start = 1;
|
|
if ($reverse_end < 1) $reverse_end = 0;
|
|
|
|
if($nmsgs > 1)
|
|
$nos = array_slice($nos, $reverse_end, ($reverse_start-$reverse_end));
|
|
|
|
// Reverse order the messages
|
|
rsort($nos, SORT_NUMERIC);
|
|
|
|
$mails = array();
|
|
$records = imap_fetch_overview($this->mBox, implode(',', $nos));
|
|
|
|
// to make sure this should not break in Vtiger6
|
|
$layout = Vtiger_Viewer::getDefaultLayoutName();
|
|
if($layout == "v7"){
|
|
$mbox = false;
|
|
} else {
|
|
$mbox = $this->mBox;
|
|
}
|
|
|
|
foreach($records as $result) {
|
|
array_unshift($mails, MailManager_Message_Model::parseOverview($result,$mbox));
|
|
}
|
|
$folder->setMails($mails);
|
|
$folder->setMailIds($nos);
|
|
$folder->setPaging($reverse_end, $reverse_start, $maxLimit, $nmsgs, $start); //-1 as it starts from 0
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns list of Folder for the Mail Box
|
|
* @return Array folder list
|
|
*/
|
|
public function getFolderList() {
|
|
if(!empty($this->mBoxBaseUrl)) {
|
|
$list = @imap_list($this->mBox, $this->mBoxBaseUrl, '*');
|
|
if (is_array($list)) {
|
|
foreach ($list as $val) {
|
|
$folder = $this->convertCharacterEncoding( $val, 'UTF-8', 'UTF7-IMAP' ); //Decode folder name
|
|
$folderList[] = preg_replace("/{(.*?)}/", "", $folder);
|
|
}
|
|
}
|
|
}
|
|
return $folderList;
|
|
}
|
|
|
|
public function convertCharacterEncoding($value, $toCharset, $fromCharset) {
|
|
if (function_exists('mb_convert_encoding')) {
|
|
$value = mb_convert_encoding($value, $toCharset, $fromCharset);
|
|
} else {
|
|
$value = iconv($toCharset, $fromCharset, $value);
|
|
}
|
|
return $value;
|
|
}
|
|
}
|
|
?>
|