* email: improve connection handling (targeting failed connects), apply connection timeout on data retrieval as well.

This commit is contained in:
Klaus Leithoff 2011-09-28 11:30:59 +00:00
parent 4aa7788581
commit 4e0ae73a73
8 changed files with 114 additions and 33 deletions

View File

@ -146,7 +146,7 @@ class Net_Socket extends PEAR {
}
$this->fp = $fp;
$this->setTimeout($this->timeout, 0);
return $this->setBlocking($this->blocking);
}
@ -273,7 +273,6 @@ class Net_Socket extends PEAR {
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return @fgets($this->fp, $size);
}

View File

@ -402,7 +402,7 @@ class defaultimap extends Net_IMAP
return false;
}
static $nameSpace;
if (is_null($nameSpace)) $nameSpace =& egw_cache::getSession('emailadmin','defaultimap_nameSpace');
if (is_null($nameSpace)) $nameSpace =& egw_cache::getSession('email','defaultimap_nameSpace');
if (isset($nameSpace[$this->ImapServerId])) return $nameSpace[$this->ImapServerId];
$retrieveDefault = false;
@ -506,7 +506,7 @@ class defaultimap extends Net_IMAP
*
* @return resource the imap connection
*/
function openConnection($_adminConnection=false)
function openConnection($_adminConnection=false, $_timeout=20)
{
//error_log(__METHOD__.function_backtrace());
//error_log(__METHOD__.__LINE__.($_adminConnection?' Adminconnection':'').array2string($this));
@ -525,7 +525,7 @@ class defaultimap extends Net_IMAP
}
$this->setStreamContextOptions($this->_getTransportOptions());
$this->setTimeout(20);
$this->setTimeout($_timeout);
if( PEAR::isError($status = parent::connect($this->_getTransportString(), $this->port, $this->encryption == 1)) ) {
if ($this->debug) error_log(__METHOD__."Could not connect with ".$this->_getTransportString()." on Port ".$this->port." Encryption==1?".$this->encryption);
if ($this->debug) error_log(__METHOD__."Status connect:".$status->message);

View File

@ -300,7 +300,6 @@ class emailadmin_bo extends so_sql
(!isset($this->data['ea_user']) || empty($this->data['ea_user']) ) &&
(isset($this->data['ea_active']) && !empty($this->data['ea_active']) && $this->data['ea_active'] ))
{
//error_log(__METHOD__.__LINE__.' Content to save:'.array2string($this->data));
$new_config = array();
foreach(array(
'ea_imap_server' => 'mail_server',
@ -336,6 +335,8 @@ class emailadmin_bo extends so_sql
//echo "<p>eGW configuration update: ".print_r($new_config,true)."</p>\n";
}
}
//error_log(__METHOD__.__LINE__.' Content to save:'.array2string($this->data));
if (is_numeric($this->data['ea_profile_id'])) self::unsetCachedObjects($this->data['ea_profile_id']*-1);
if (!($result = parent::save()))
{
$GLOBALS['egw']->contenthistory->updateTimeStamp('emailadmin_profiles', $this->data['ea_profile_id'], $old === false ? 'add' : 'modify', time());
@ -570,6 +571,45 @@ class emailadmin_bo extends so_sql
return $retData;
}
/**
* unset certain CachedObjects for the given profile id, unsets the profile for default ID=0 as well
*
* 1) icServerIMAP_connectionError
* 2) icServerSIEVE_connectionError
* 3) defaultimap_nameSpace
* 4) INSTANCE OF FELAMIMAIL_BO
*
* @param int $_profileID
* @return void
*/
static function unsetCachedObjects($_profileID)
{
if (!is_array($_profileID) && is_numeric($_profileID))
{
//error_log(__METHOD__.__LINE__.' for Profile:'.$_profileID);
$buff = egw_cache::getSession('email','icServerIMAP_connectionError');
if (isset($buff[$_profileID]))
{
unset($buff[$_profileID]);
egw_cache::setSession('email','icServerIMAP_connectionError',$buff);
}
$isConError = egw_cache::getSession('email','icServerSIEVE_connectionError');
if (isset($isConError[$_profileID]))
{
unset($isConError[$_profileID]);
egw_cache::setSession('email','icServerSIEVE_connectionError');
}
$nameSpace = egw_cache::getSession('email','defaultimap_nameSpace');
if (isset($nameSpace[$_profileID]))
{
unset($nameSpace[$_profileID]);
egw_cache::setSession('email','defaultimap_nameSpace',$nameSpace);
}
felamimail_bo::unsetInstance($_profileID);
if ($_profileID != 0) self::unsetCachedObjects(0); // reset the default ServerID as well
}
}
/**
* Get EMailAdmin profile for a user
*

View File

@ -67,6 +67,15 @@ class emailadmin_sieve extends Net_Sieve
*/
function _connect($_icServer,$euser='')
{
static $isConError;
if (is_null($isConError)) $isConError =& egw_cache::getSession('email','icServerSIEVE_connectionError');
if ( isset($isConError[$_icServerID]) )
{
error_log(__METHOD__.__LINE__.' failed for Reason:'.$isConError[$_icServerID]);
//$this->errorMessage = $isConError[$_icServerID];
return false;
}
if ($this->debug) error_log(__CLASS__.'::'.__METHOD__.array2string($euser));
if(($_icServer instanceof defaultimap) && $_icServer->enableSieve) {
if (!empty($_icServer->sieveHost))
@ -94,11 +103,13 @@ class emailadmin_sieve extends Net_Sieve
if(PEAR::isError($this->error = $this->connect($sieveHost , $sievePort, null, $useTLS) ) ){
if ($this->debug) error_log(__CLASS__.'::'.__METHOD__.": error in connect($sieveHost,$sievePort): ".$this->error->getMessage());
$isConError[$_icServerID] = "SIEVE: error in connect($sieveHost,$sievePort): ".$this->error->getMessage();
return false;
}
if(PEAR::isError($this->error = $this->login($username, $password, null, $euser) ) ){
if ($this->debug) error_log(__CLASS__.'::'.__METHOD__.array2string($this->icServer));
if ($this->debug) error_log(__CLASS__.'::'.__METHOD__.": error in login($username,$password,null,$euser): ".$this->error->getMessage());
$isConError[$_icServerID] = "SIEVE: error in login($username,$password,null,$euser): ".$this->error->getMessage();
return false;
}
return true;

View File

@ -377,8 +377,12 @@
if(isset($_icServer->host)) {
$_icServer->sieveHost = $_icServer->host;
}
// unset the session data
$this->sessionData = array();
$this->saveSessionData();
//error_log(__METHOD__.__LINE__.array2string($_icServer));
emailadmin_bo::unsetCachedObjects($_identity->id);
return parent::saveAccountData($GLOBALS['egw_info']['user']['account_id'], $_icServer, $_ogServer, $_identity);
}

View File

@ -30,6 +30,13 @@ class felamimail_bo
// message types
var $type = array("text", "multipart", "message", "application", "audio", "image", "video", "other");
/**
* errorMessage
*
* @var string $errorMessage
*/
var $errorMessage;
// message encodings
var $encoding = array("7bit", "8bit", "binary", "base64", "quoted-printable", "other");
static $displayCharset;
@ -102,7 +109,7 @@ class felamimail_bo
*
* @param boolean $_restoreSession=true
* @param int $_profileID=0
* @param boolean $_validate=true - flag wether the profileid should be validatet or not, if validation is true, you may receive a profile
* @param boolean $_validate=true - flag wether the profileid should be validated or not, if validation is true, you may receive a profile
* not matching the input profileID, if we can not find a profile matching the given ID
* @return object instance of felamimail_bo
*/
@ -145,6 +152,17 @@ class felamimail_bo
return self::$instances[$_profileID];
}
/**
* unset the private static instances by profileID
*
* @param int $_profileID=0
* @return void
*/
public static function unsetInstance($_profileID=0)
{
if (isset(self::$instances[$_profileID])) unset(self::$instances[$_profileID]);
}
/**
* validate the given profileId to make sure it is valid for the active user
*
@ -985,7 +1003,7 @@ class felamimail_bo
static $folderStatus;
if (isset($folderStatus[$this->icServer->ImapServerId][$folderName]))
{
//error_log(__METHOD__.__LINE__.' Using cache for status on Server:'.$this->icServer->ImapServerId.' for folder:'.$folderName);
//error_log(__METHOD__.__LINE__.' Using cache for status on Server:'.$this->icServer->ImapServerId.' for folder:'.$folderName.'->'.array2string($folderStatus[$this->icServer->ImapServerId][$folderName]));
return $folderStatus[$this->icServer->ImapServerId][$folderName];
}
$folderStatus[$this->icServer->ImapServerId][$folderName] = $this->icServer->getStatus($folderName);
@ -1610,7 +1628,9 @@ class felamimail_bo
function getErrorMessage()
{
return $this->icServer->_connectionErrorObject->message;
$rv =$this->icServer->_connectionErrorObject->message;
if (empty($rv)) $rv =$this->errorMessage;
return $rv;
}
/**
@ -2090,7 +2110,7 @@ class felamimail_bo
} elseif ($mimePart->type == 'MULTIPART' && $mimePart->subType == 'RELATED' && is_array($mimePart->subParts)) {
// in a multipart alternative we treat the multipart/related as html part
#$partHTML = array($mimePart);
error_log(__METHOD__." process MULTIPART/RELATED with array as subparts");
if (self::$debug) error_log(__METHOD__." process MULTIPART/RELATED with array as subparts");
$partHTML = $mimePart;
} elseif ($mimePart->type == 'MULTIPART' && $mimePart->subType == 'ALTERNATIVE' && is_array($mimePart->subParts)) {
//cascading multipartAlternative structure, assuming only the first one is to be used
@ -3366,8 +3386,14 @@ class felamimail_bo
function openConnection($_icServerID=0, $_adminConnection=false)
{
static $isError;
if ( PEAR::isError($isError[$_icServerID]) ) return false;
//error_log(__METHOD__.__LINE__.'->'.$_icServerID.' called from '.function_backtrace());
if (is_null($isError)) $isError =& egw_cache::getSession('email','icServerIMAP_connectionError');
if ( isset($isError[$_icServerID]) || PEAR::isError($this->icServer->_connectionErrorObject))
{
//error_log(__METHOD__.__LINE__.' failed for Reason:'.$isError[$_icServerID]);
$this->errorMessage = ($isError[$_icServerID]?$isError[$_icServerID]:$this->icServer->_connectionErrorObject->message);
return false;
}
if (!is_object($this->mailPreferences))
{
if (self::$debug) error_log(__METHOD__." No Object for MailPreferences found.". function_backtrace());
@ -3377,7 +3403,7 @@ class felamimail_bo
}
if(!$this->icServer = $this->mailPreferences->getIncomingServer((int)$_icServerID)) {
$this->errorMessage .= lang('No active IMAP server found!!');
$isError[$_icServerID] = new PEAR_Error($this->errorMessage);
$isError[$_icServerID] = $this->errorMessage;
return false;
}
//error_log(__METHOD__.__LINE__.'->'.array2string($this->icServer->ImapServerId));
@ -3389,22 +3415,21 @@ class felamimail_bo
$errormessage .= "<br>".lang('Please ask the administrator to correct the emailadmin IMAP Server Settings for you.');
}
$this->icServer->_connectionErrorObject->message .= $this->errorMessage .= $errormessage;
$isError[$_icServerID] = new PEAR_Error($this->errorMessage);
$isError[$_icServerID] = $this->errorMessage;
return false;
}
//error_log( "-------------------------->open connection ".function_backtrace());
//error_log(__METHOD__.__LINE__.' ->'.array2string($this->icServer));
if ($this->icServer->_connected == 1) {
$tretval = $this->icServer->selectMailbox($this->icServer->currentMailbox);
if ( PEAR::isError($tretval) ) $isError[$_icServerID] = $tretval;
if ( PEAR::isError($tretval) ) $isError[$_icServerID] = $tretval->message;
//error_log(__METHOD__." using existing Connection ProfileID:".$_icServerID.' Status:'.print_r($this->icServer->_connected,true));
} else {
//error_log( "-------------------------->open connection for Server with profileID:".$_icServerID.function_backtrace());
$this->icServer->_timeout = 5;
$tretval = $this->icServer->openConnection($_adminConnection);
$tretval = $this->icServer->openConnection($_adminConnection,5);
if ( PEAR::isError($tretval) || $tretval===false)
{
$isError[$_icServerID] = $this->icServer->_connectionErrorObject;
$isError[$_icServerID] = ($tretval?$tretval->message:$this->icServer->_connectionErrorObject->message);
if (self::$debug)
{
error_log(__METHOD__.__LINE__." # failed to open new Connection ProfileID:".$_icServerID.' Status:'.print_r($this->icServer->_connected,true).' Message:'.$this->icServer->_connectionErrorObject->message.' called from '.function_backtrace());

View File

@ -43,9 +43,9 @@
{
$this->t = $GLOBALS['egw']->template;
$this->charset = translation::charset();
$this->bofelamimail = felamimail_bo::getInstance();
$this->bopreferences = $this->bofelamimail->bopreferences;
$this->uiwidgets = CreateObject('felamimail.uiwidgets');
if (is_object($this->bofelamimail->mailPreferences))
@ -221,6 +221,7 @@
if (!isset($this->bofelamimail)) $this->bofelamimail = felamimail_bo::getInstance();
if (!isset($this->bopreferences)) $this->bopreferences = $this->bofelamimail->bopreferences;
$preferences =& $this->bopreferences->getPreferences();
$referer = '../index.php?menuaction=felamimail.uipreferences.listAccountData';
if(!($preferences->userDefinedAccounts || $preferences->userDefinedIdentities)) {
die('you are not allowed to be here');
@ -287,24 +288,14 @@
$GLOBALS['egw']->redirect_link($referer,array('msg' => lang('aborted')));
return;
}
$folderList = array();
if (!isset($this->bofelamimail) || (int)$_POST['active']) $this->bofelamimail = felamimail_bo::getInstance();
if($this->bofelamimail->openConnection()) {
$folderObjects = $this->bofelamimail->getFolderObjects();
foreach($folderObjects as $folderName => $folderInfo) {
//_debug_array($folderInfo);
$folderList[$folderName] = $folderInfo->displayName;
}
$this->bofelamimail->closeConnection();
}
$this->display_app_header(TRUE);
$this->t->set_file(array("body" => "edit_account_data.tpl"));
$this->t->set_block('body','main');
if ($msg) $this->t->set_var("message", $msg); else $this->t->set_var("message", '');
$this->translate();
// initalize the folderList array
$folderList = array();
// if there is no accountID with the call of the edit method, retrieve an active account
if ((int)$_GET['accountID']) {
@ -319,6 +310,15 @@
$ogServer =& $accountData['ogServer'];
$identity =& $accountData['identity'];
//_debug_array($identity);
if (!isset($this->bofelamimail) || ((int)$_POST['active'] && !empty($icServer->host))) $this->bofelamimail = felamimail_bo::getInstance(false,$icServer->ImapServerId);
if((int)$_POST['active'] && !empty($icServer->host) && $this->bofelamimail->openConnection(($icServer->ImapServerId?$icServer->ImapServerId:0))) {
$folderObjects = $this->bofelamimail->getFolderObjects();
foreach($folderObjects as $folderName => $folderInfo) {
//_debug_array($folderInfo);
$folderList[$folderName] = $folderInfo->displayName;
}
$this->bofelamimail->closeConnection();
}
}
else
{

View File

@ -146,7 +146,8 @@ class notifications_ajax {
*
* @return boolean true or false
*/
private function check_mailbox() {
private function check_mailbox()
{
//error_log(__METHOD__.__LINE__.array2string($this->preferences[self::_mailappname]['notify_folders']));
if(!isset($this->preferences[self::_mailappname]['notify_folders'])||$this->preferences[self::_mailappname]['notify_folders']=='none') {
return true; //no pref set for notifying - exit
@ -162,9 +163,10 @@ class notifications_ajax {
$activeProfile = $GLOBALS['egw_info']['user']['preferences']['felamimail']['ActiveProfileID'] = $bofelamimail->profileID;
// buffer felamimail sessiondata, as they are needed for information exchange by the app itself
$bufferFMailSession = $bofelamimail->sessionData;
if(!$bofelamimail->openConnection($activeProfile)) {
if( !$bofelamimail->openConnection($activeProfile) ) {
// TODO: This is ugly. Log a bit nicer!
error_log(__METHOD__.__LINE__.' #'.self::_appname.' (user: '.$this->recipient->account_lid.'): cannot connect to mailbox with Profile:'.$activeProfile.'. Please check your prefs!');
error_log(__METHOD__.__LINE__.' # '.$bofelamimail->getErrorMessage());
error_log(__METHOD__.__LINE__.' # '.self::_appname.' (user: '.$this->recipient->account_lid.'): cannot connect to mailbox with Profile:'.$activeProfile.'. Please check your prefs!');
error_log(__METHOD__.__LINE__.' # Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid']);
return false; // cannot connect to mailbox
}