diff --git a/egw-pear/Net/IMAP.php b/egw-pear/Net/IMAP.php index 3313ab0157..08dc88b666 100644 --- a/egw-pear/Net/IMAP.php +++ b/egw-pear/Net/IMAP.php @@ -381,19 +381,44 @@ class Net_IMAP extends Net_IMAPProtocol { $message_set="1:*"; } if($uidFetch) { - $ret=$this->cmdUidFetch($message_set,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY.PEEK[HEADER.FIELDS (CONTENT-TYPE)])"); + #error_log("egw-pear::NET::IMAP:getSummary->fetch by UID ".$message_set); + $ret=$this->cmdUidFetch($message_set,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY.PEEK[HEADER.FIELDS (CONTENT-TYPE X-PRIORITY)])"); } else { - $ret=$this->cmdFetch($message_set,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY.PEEK[HEADER.FIELDS (CONTENT-TYPE)])"); + #error_log("egw-pear::NET::IMAP:getSummary->fetch message ".$message_set); + $ret=$this->cmdFetch($message_set,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY.PEEK[HEADER.FIELDS (CONTENT-TYPE X-PRIORITY)])"); } + #error_log(print_r($ret['PARSED'][0],true)); #$ret=$this->cmdFetch($message_set,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY[1.MIME])"); - if (PEAR::isError($ret)) { - return $ret; - } - if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){ - return new PEAR_Error($ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]); + if (PEAR::isError($ret) || strtoupper($ret["RESPONSE"]["CODE"]) != "OK") { + error_log("egw-pear::NET::IMAP:getSummary->error after Fetch for message(s):".$message_set." Trying to retrieve single messages."); + unset($ret); + # if there is an error, while retrieving the information for the whole list, try to retrieve the info one by one, to be more error tolerant + foreach (explode(',',$message_set) as $msgid) { + $retloop=$this->cmdUidFetch($msgid,"(RFC822.SIZE UID FLAGS ENVELOPE INTERNALDATE BODY.PEEK[HEADER.FIELDS (CONTENT-TYPE X-PRIORITY)])"); + if (PEAR::isError($retloop)|| strtoupper($retloop["RESPONSE"]["CODE"]) != "OK") { + # log the error, and create a dummy-message as placeholder, this may hold the possibility to read the message anyway + error_log("egw-pear::NET::IMAP:getSummary->error after Fetch for message with id:".$msgid); + error_log($ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]); + $ret['PARSED'][]=array('COMMAND'=>"FETCH",'EXT'=>array('UID'=>$msgid,'ENVELOPE'=>array('SUBJECT'=>"[FELAMIMAIL:ERROR]can not parse this message(header).",))); + } else { + #error_log(print_r($retloop['PARSED'][0],true)); + # renew the response for every message retrieved, since the returnvalue is structured that way + $ret['RESPONSE']=$retloop['RESPONSE']; + $ret['PARSED'][]=$retloop['PARSED'][0]; + } + unset($retloop); + } + #return $ret; } + # this seems to be obsolet, since errors while retrieving header informations are 'covered' above + #if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){ + # error_log("egw-pear::NET::IMAP:getSummary->ResponseCode not OK"); + # return new PEAR_Error($ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]); + #} - #print "
"; var_dump($ret["PARSED"]); print "
"; + #print "
"; + #error_log("egw-pear::NET::IMAP:getSummary->".print_r($ret["PARSED"],TRUE)); + #print "
"; if(isset( $ret["PARSED"] ) ){ for($i=0; $i X-Priority: 5\r\nContent-Type: multipart/alternative;\r\n\tboundary="b1_61838a67749ca51b425e42489adced98"\r\n\r\n\n + if(preg_match('/x-priority: ([0-9])/iU', $ret["PARSED"][$i]['EXT']['BODY[HEADER.FIELDS (CONTENT-TYPE X-PRIORITY)]']['CONTENT'], $matches)) { + $a['PRIORITY']=strtolower($matches[1]); + } + } elseif (isset($ret["PARSED"][$i]['EXT']['BODY[HEADER.FIELDS ("CONTENT-TYPE" "X-PRIORITY")]']['CONTENT'])) { // some versions of cyrus send "CONTENT-TYPE" and CONTENT-TYPE only - if (preg_match('/^content-type: (.*);/iU', $ret["PARSED"][$i]['EXT']['BODY[HEADER.FIELDS ("CONTENT-TYPE")]']['CONTENT'], $matches)) { + if (preg_match('/content-type: (.*);/iU', $ret["PARSED"][$i]['EXT']['BODY[HEADER.FIELDS ("CONTENT-TYPE" "X-PRIORITY")]']['CONTENT'], $matches)) { $a['MIMETYPE']=strtolower($matches[1]); + } + // fetch the priority [CONTENT] => X-Priority: 5\r\nContent-Type: multipart/alternative;\r\n\tboundary="b1_61838a67749ca51b425e42489adced98"\r\n\r\n\n + if (preg_match('/x-priority: ([0-9])/iU', $ret["PARSED"][$i]['EXT']['BODY[HEADER.FIELDS ("CONTENT-TYPE" "X-PRIORITY")]']['CONTENT'], $matches)) { + $a['PRIORITY']=strtolower($matches[1]); } } $env[]=$a; @@ -1218,7 +1251,7 @@ class Net_IMAP extends Net_IMAPProtocol { * @param string $mailbox mailbox name to append to (default is current mailbox) * @param string $flags_list set flags appended message * - * @return mixed true on success / Pear_Error on failure + * @return mixed true (or the uid of the created message) on success / Pear_Error on failure * * @access public * @since 1.0 @@ -1232,9 +1265,16 @@ class Net_IMAP extends Net_IMAPProtocol { if (PEAR::isError($ret)) { return $ret; } + if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){ return new PEAR_Error($ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]); } + // the expected response is something like that: [APPENDUID 1160024220 12] Completed + // the uid of the created message is the number just before the closing bracket + $retcode = explode(' ',$ret["RESPONSE"]["STR_CODE"]); + $retcode = explode(']',$retcode[2]); + if (intval($retcode[0]) > 0) return $retcode[0]; + // this should never happen, exept the parsed response is not as expected return true; } @@ -1636,7 +1676,7 @@ class Net_IMAP extends Net_IMAPProtocol { * @access public * @since 1.0 */ - function getFlags( $msg_id = null ) + function getFlags( $msg_id = null , $uidStore = false) { // You can also provide an array of numbers to those emails if( $msg_id != null){ @@ -1648,9 +1688,13 @@ class Net_IMAP extends Net_IMAPProtocol { }else{ $message_set="1:*"; } + if ($uidStore == true ) { + $ret = $this->cmdUidFetch($message_set, 'FLAGS'); + } else { + $ret = $this->cmdFetch($message_set, 'FLAGS'); + } - - if (PEAR::isError($ret = $this->cmdFetch($message_set, 'FLAGS'))) { + if (PEAR::isError($ret)) { return $ret; } if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){ @@ -1686,6 +1730,7 @@ class Net_IMAP extends Net_IMAPProtocol { */ function setFlags($msg_id, $flags, $mod = 'set', $uidStore = false) { + #error_log("egw-pear::Net::setFlags"); // you can also provide an array of numbers to those emails if ($msg_id == 'all') { $message_set = '1:*'; @@ -1719,7 +1764,7 @@ class Net_IMAP extends Net_IMAPProtocol { return new PEAR_Error('wrong input $mod'); break; } - + #error_log("egw-pear::Net::setFlags for Message: ".print_r($message_set,true)."->".$flaglist); if($uidStore == true) { $ret=$this->cmdUidStore($message_set, $dataitem, $flaglist); } else { diff --git a/egw-pear/Net/IMAPProtocol.php b/egw-pear/Net/IMAPProtocol.php index fb6d7205ee..8460f2c235 100644 --- a/egw-pear/Net/IMAPProtocol.php +++ b/egw-pear/Net/IMAPProtocol.php @@ -538,7 +538,7 @@ class Net_IMAPProtocol { */ function _authDigest_MD5($uid , $pwd , $cmdid) { - + class_exists('Auth_SASL') || require_once 'Auth/SASL.php'; if ( PEAR::isError($error = $this->_putCMD( $cmdid ,"AUTHENTICATE" , "DIGEST-MD5") ) ) { return $error; } @@ -596,7 +596,7 @@ class Net_IMAPProtocol { function _authCRAM_MD5($uid, $pwd, $cmdid) { - + class_exists('Auth_SASL') || require_once 'Auth/SASL.php'; if ( PEAR::isError($error = $this->_putCMD( $cmdid ,"AUTHENTICATE" , "CRAM-MD5") ) ) { return $error; @@ -854,8 +854,11 @@ class Net_IMAPProtocol { $ret=$this->_genericCommand('EXAMINE', $mailbox_name); $parsed=''; if(isset( $ret["PARSED"] ) ){ - for($i=0;$i$parsed,"RESPONSE"=>$ret["RESPONSE"]); @@ -1204,7 +1207,7 @@ class Net_IMAPProtocol { function cmdExpunge() { $ret=$this->_genericCommand('EXPUNGE'); - + if (PEAR::isError($ret)) return new PEAR_Error('could not Expunge!'); if(isset( $ret["PARSED"] ) ){ $parsed=$ret["PARSED"]; unset($ret["PARSED"]); @@ -2343,12 +2346,16 @@ class Net_IMAPProtocol { if ($str[$pos] !== '"') return false; // start condition failed $pos++; - + $delimCount=0; while($str[$pos] !== '"' && $pos < $len) { // this is a fix to stop before the delimiter, in broken string messages containing an odd number of double quotes // the idea is to check for a stopDelimited followed by eiter a new startDelimiter or an other stopDelimiter // that allows to have something like '"Name (Nick)" ' containing one delimiter - if ($str[$pos] === $stopDelim && ($str[$pos+1] === $startDelim || $str[$pos+1] === $stopDelim)) { + // if you have something like "Name ((something))" we must count the delimiters (and hope that they are not unbalanced too) + // and check if we have a negative amount of delimiters or no delimiters to meet the stop condition, before we run into a closing double quote + if ($str[$pos] === $startDelim) $delimCount++; + if ($str[$pos] === $stopDelim) $delimCount--; + if ($str[$pos] === $stopDelim && ($str[$pos+1] === $startDelim || ($str[$pos+1] === $stopDelim && $delimCount<=0))) { $pos--; // stopDelimited need to be parsed outside! return false; } @@ -2559,6 +2566,7 @@ class Net_IMAPProtocol { } break; } + #error_log("egw-pear::NET::IMAPProtocoll:_getNextToken:".$str); return $content_size; } @@ -3065,7 +3073,7 @@ class Net_IMAPProtocol { } $this->_getNextToken($str, $token); - + #error_log(" egw-pear::NET::IMAPProtocoll:_genericIMAPResponseParser: After retrieving the first token:".$token); while ($token != $cmdid && $str != '') { if ($token == '+' ) { //if the token is + ignore the line @@ -3169,6 +3177,7 @@ class Net_IMAPProtocol { $cmdid = $this->_getCmdId(); $this->_putCMD( $cmdid , $command , $params ); $args=$this->_getRawResponse( $cmdid ); + #error_log("egw-pear::NET::IMAPProtocoll:_genericCommand:".$command." result:".print_r($args,TRUE)); return $this->_genericImapResponseParser( $args , $cmdid ); }