pax_global_header00006660000000000000000000000064117017042560014515gustar00rootroot0000000000000052 comment=e58913c9703dd24e308722048f6c42bc8cb85c4b php-net-imap-1.1.1/000077500000000000000000000000001170170425600140145ustar00rootroot00000000000000php-net-imap-1.1.1/Net_IMAP-1.1.1/000077500000000000000000000000001170170425600160045ustar00rootroot00000000000000php-net-imap-1.1.1/Net_IMAP-1.1.1/Net/000077500000000000000000000000001170170425600165325ustar00rootroot00000000000000php-net-imap-1.1.1/Net_IMAP-1.1.1/Net/IMAP.php000066400000000000000000002721621170170425600200030ustar00rootroot00000000000000 * @copyright 1997-2003 The PHP Group * @license PHP license * @version CVS: $Id$ * @link http://pear.php.net/package/Net_IMAP */ /** * IMAPProtocol.php holds protocol implementation for IMAP.php */ require_once 'Net/IMAPProtocol.php'; /** * Provides an implementation of the IMAP protocol using PEAR's * Net_Socket:: class. * * @category Networking * @package Net_IMAP * @author Damian Alejandro Fernandez Sosa * @license PHP license * @link http://pear.php.net/package/Net_IMAP */ class Net_IMAP extends Net_IMAPProtocol { /** * Constructor * * Instantiates a new Net_SMTP object, overriding any defaults * with parameters that are passed in. * * @param string $host The server to connect to. * @param int $port The port to connect to. * @param bool $enableSTARTTLS Enable STARTTLS support * @param string $encoding Character encoding */ function Net_IMAP($host = 'localhost', $port = 143, $enableSTARTTLS = true, $encoding = 'ISO-8859-1') { $this->Net_IMAPProtocol(); $ret = $this->connect($host, $port, $enableSTARTTLS); $this->_encoding = $encoding; } /** * Attempt to connect to the IMAP server located at $host $port * * @param string $host The IMAP server * @param string $port The IMAP port * @param bool $enableSTARTTLS enable STARTTLS support * * It is only useful in a very few circunstances * because the contructor already makes this job * * @return true on success or PEAR_Error * * @access public * @since 1.0 */ function connect($host, $port, $enableSTARTTLS = true) { $ret = $this->cmdConnect($host, $port); if ($ret === true) { // Determine server capabilities $res = $this->cmdCapability(); // check if we can enable TLS via STARTTLS // (requires PHP 5 >= 5.1.0RC1 for stream_socket_enable_crypto) if ($this->hasCapability('STARTTLS') === true && $enableSTARTTLS === true && function_exists('stream_socket_enable_crypto') === true) { if (PEAR::isError($res = $this->cmdStartTLS())) { return $res; } } return $ret; } if (empty($ret)) { return new PEAR_Error("Unexpected response on connection"); } if (PEAR::isError($ret)) { return $ret; } if (isset($ret['RESPONSE']['CODE'])) { if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } } return $ret; } /** * Attempt to authenticate to the IMAP server. * * @param string $user The userid to authenticate as. * @param string $pass The password to authenticate with. * @param string $useauthenticate true: authenticate using * the IMAP AUTHENTICATE command. false: authenticate using * the IMAP AUTHENTICATE command. 'string': authenticate using * the IMAP AUTHENTICATE command but using the authMethod in 'string' * @param boolean $selectMailbox automaticaly select inbox on login * (false does not) * * @return true on success or PEAR_Error * * @access public * @since 1.0 */ function login($user, $pass, $useauthenticate = true, $selectMailbox=true) { if ($useauthenticate) { // $useauthenticate is a string if the user hardcodes an AUTHMethod // (the user calls $imap->login("user","password","CRAM-MD5"); for // example! if (is_string($useauthenticate)) { $method = $useauthenticate; } else { $method = null; } //Try the selected Auth method if (PEAR::isError($ret = $this->cmdAuthenticate($user, $pass, $method))) { // Verify the methods that we have in common with the server if (is_array($this->_serverAuthMethods)) { $commonMethods = array_intersect($this->supportedAuthMethods, $this->_serverAuthMethods); } else { $this->_serverAuthMethods = null; } if ($this->_serverAuthMethods == null || count($commonMethods) == 0 || $this->supportedAuthMethods == null) { // The server does not have any auth method, so I try LOGIN if ( PEAR::isError($ret = $this->cmdLogin($user, $pass))) { return $ret; } } else { return $ret; } } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } } else { //The user request "PLAIN" auth, we use the login command if (PEAR::isError($ret = $this->cmdLogin($user, $pass))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } } if ($selectMailbox) { //Select INBOX if (PEAR::isError($ret = $this->cmdSelect($this->getCurrentMailbox()))) { return $ret; } } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Disconnect function. Sends the QUIT command * and closes the socket. * * @param boolean $expungeOnExit (default = false) * * @return mixed true on success / Pear_Error on failure * * @access public */ function disconnect($expungeOnExit = false) { if ($expungeOnExit) { if (PEAR::isError($ret = $this->cmdExpunge())) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { $ret = $this->cmdLogout(); return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } } if (PEAR::isError($ret = $this->cmdLogout())) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Changes the default/current mailbox to $mailbox * * @param string $mailbox Mailbox to select * * @return mixed true on success / Pear_Error on failure * * @access public */ function selectMailbox($mailbox) { if (PEAR::isError($ret = $this->cmdSelect($mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Checks the mailbox $mailbox * * @param string $mailbox Mailbox to examine * * @return mixed true on success / Pear_Error on failure * * @access public */ function examineMailbox($mailbox) { if (PEAR::isError($ret = $this->cmdExamine($mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } //$ret_aux["EXISTS"]=$ret["PARSED"]["EXISTS"]; //$ret_aux["RECENT"]=$ret["PARSED"]["RECENT"]; $ret = $ret['PARSED']; return $ret; } /** * Returns the raw headers of the specified message. * * @param int $msg_id Message number * @param string $part_id Part ID * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either raw headers or false on error * * @access public */ function getRawHeaders($msg_id, $part_id = '', $uidFetch = false) { if ($part_id != '') { $command = 'BODY[' . $part_id . '.HEADER]'; } else { $command = 'BODY[HEADER]'; } if ($uidFetch == true) { $ret = $this->cmdUidFetch($msg_id, $command); } else { $ret = $this->cmdFetch($msg_id, $command); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret = $ret['PARSED'][0]['EXT'][$command]['CONTENT']; return $ret; } /** * Returns the headers of the specified message in an * associative array. Array keys are the header names, array * values are the header values. In the case of multiple headers * having the same names, eg Received:, the array value will be * an indexed array of all the header values. * * @param int $msg_id Message number * @param boolean $keysToUpper false (default) original header names * true change keys (header names) toupper * @param string $part_id Part ID * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either array of headers or false on error * * @access public */ function getParsedHeaders($msg_id, $keysToUpper = false, $part_id = '', $uidFetch = false) { if (PEAR::isError($ret = $this->getRawHeaders($msg_id, $part_id, $uidFetch))) { return $ret; } $raw_headers = rtrim($ret); // Unfold headers $raw_headers = preg_replace("/\r\n[ \t]+/", ' ', $raw_headers); $raw_headers = explode("\r\n", $raw_headers); foreach ($raw_headers as $value) { $name = substr($value, 0, $pos = strpos($value, ':')); if ($keysToUpper) { $name = strtoupper($name); } $value = ltrim(substr($value, $pos + 1)); if (isset($headers[$name]) && is_array($headers[$name])) { $headers[$name][] = $value; } elseif (isset($headers[$name])) { $headers[$name] = array($headers[$name], $value); } else { $headers[$name] = $value; } } return $headers; } /** * Returns an array containing the message ID, the size and the UID * of each message selected. * message selection can be a valid IMAP command, a number or an array of * messages * * @param string $msg_id Message number * * @return mixed Either array of message data or PearError on error * * @access public */ function getMessagesList($msg_id = null) { if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if (PEAR::isError($ret = $this->cmdFetch($message_set, '(RFC822.SIZE UID)'))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (empty($ret['PARSED'])) { return array(); } foreach ($ret['PARSED'] as $msg) { $ret_aux[] = array('msg_id' => $msg['NRO'], 'size' => $msg['EXT']['RFC822.SIZE'], 'uidl' => $msg['EXT']['UID']); } return $ret_aux; } /** * Message summary * * @param mixed $msg_id Message number * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either array of headers or PEAR::Error on error * * @access public */ function getSummary($msg_id = null, $uidFetch = false) { if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if ($uidFetch) { $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 X-PRIORITY)])'); } // $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 (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" "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; $a = null; } return $env; } //return $ret; } /** * Returns the body of the message with given message number. * * @param string $msg_id Message number * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * @param string $partId Part ID * * @return mixed Either message body or PEAR_Error on failure * @access public */ function getBody($msg_id, $uidFetch = false, $partId = '') { if ($partId != '') { $partId = '.' . strtoupper($partId); } if ($uidFetch) { $ret = $this->cmdUidFetch($msg_id, 'BODY' . $partId . '[TEXT]'); } else { $ret = $this->cmdFetch($msg_id, 'BODY' . $partId . '[TEXT]'); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret = $ret['PARSED'][0]['EXT']['BODY[TEXT]']['CONTENT']; // $ret=$resp["PARSED"][0]["EXT"]["RFC822"]["CONTENT"]; return $ret; } /** * Returns the body of the message with given message number. * * @param int $msg_id Message number * @param string $partId Message number * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either message body or false on error * * @access public */ function getBodyPart($msg_id, $partId, $uidFetch = false) { if ($uidFetch) { $ret = $this->cmdUidFetch($msg_id, 'BODY[' . $partId . ']'); } else { $ret = $this->cmdFetch($msg_id, 'BODY[' . $partId . ']'); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret = $ret['PARSED'][0]['EXT']['BODY[' . $partId . ']']['CONTENT']; //$ret=$resp["PARSED"][0]["EXT"]["RFC822"]["CONTENT"]; return $ret; } /** * Returns the body of the message with given message number. * * @param int $msg_id Message number * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either message body or false on error * * @access public */ function getStructure($msg_id, $uidFetch = false) { // print "IMAP.php::getStructure
";
        // $this->setDebug(true);
        // print "
";
        if ($uidFetch) {
            $ret = $this->cmdUidFetch($msg_id, 'BODYSTRUCTURE');
        } else {
            $ret = $this->cmdFetch($msg_id, 'BODYSTRUCTURE');
        }
        if (PEAR::isError($ret)) {
            return $ret;
        }
        if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') {
            return new PEAR_Error($ret['RESPONSE']['CODE'] 
                                  . ', ' 
                                  . $ret['RESPONSE']['STR_CODE']);
        }
        $ret = $ret['PARSED'][0]['EXT']['BODYSTRUCTURE'][0];

        $mimeParts = array();
        $this->_parseStructureArray($ret, $mimeParts);

        return array_shift($mimeParts);
    }


    /**
     * Parse structure array
     *
     * @param array $_structure  Structure array
     * @param array &$_mimeParts Mime parts
     * @param int   $_partID     Part ID
     *
     * @return nothing
     *
     * @access private
     */
    function _parseStructureArray($_structure, &$_mimeParts, $_partID = '') 
    {
        // something went wrong
        if (!is_array($_structure)) {
            return false;
        }

        // print "Net_IMAP::_parseStructureArray _partID: $_partID";
        $mimeParts = array();
        $subPartID = 1;
        if ($_partID == '') {
            $partID = '';
        } else {
            $partID = $_partID.'.';
        }
        if (is_array($_structure[0])) {
            $this->_parseStructureMultipartArray($_structure, $_mimeParts, $_partID);
        } else {
            switch (strtoupper($_structure[0])) {
            case 'TEXT':
                $this->_parseStructureTextArray($_structure, 
                                                $_mimeParts, 
                                                $partID . $subPartID);
                break;

            case 'MESSAGE':
                $this->_parseStructureMessageArray($_structure, 
                                                   $_mimeParts, 
                                                   $partID . $subPartID);
                break;

            default:
                $this->_parseStructureApplicationArray($_structure, 
                                                       $_mimeParts, 
                                                       $partID . $subPartID);
                break;
            }
        }
    }
    


    /**
     * Parse multibpart structure array
     *
     * @param array   $_structure       Structure array
     * @param array   &$_mimeParts      Mime parts
     * @param int     $_partID          Part ID
     * @param boolean $_parentIsMessage Parent is message/rfc822
     *
     * @return noting
     *
     * @access private
     */
    function _parseStructureMultipartArray($_structure, 
                                           &$_mimeParts, 
                                           $_partID, 
                                           $_parentIsMessage = false) 
    {
        // a multipart/mixed, multipart/report or multipart/alternative 
        // or multipart/related get's no own partid, if the parent 
        // is message/rfc822
        if ($_parentIsMessage == true && is_array($_structure[0])) {
            foreach ($_structure as $structurePart) {
                if (!is_array($structurePart)) {
                    $subType = strtolower($structurePart);
                    break;
                }
            }
            if ($subType == 'mixed' 
                || $subType == 'report' 
                || $subType == 'alternative' 
                || $subType == 'related') {
                $_partID = substr($_partID, 0, strrpos($_partID, '.'));
            }
        }
        
        $subPartID = 1;
        if ($_partID == '') {
            $partID = '';
        } else {
            $partID = $_partID . '.';
        }
        $subMimeParts = array();
        foreach ($_structure as $structurePart) {
            if (is_array($structurePart)) {
                if (is_array($structurePart[0])) {
                    // another multipart inside the multipart
                    $this->_parseStructureMultipartArray($structurePart, 
                                                         $subMimeParts, 
                                                         $partID . $subPartID);
                } else {
                    switch(strtoupper($structurePart[0])) {
                    case 'IMAGE':
                        $this->_parseStructureImageArray($structurePart, 
                                                         $subMimeParts, 
                                                         $partID . $subPartID);
                        break;
                    case 'MESSAGE':
                        $this->_parseStructureMessageArray($structurePart, 
                                                           $subMimeParts, 
                                                           $partID . $subPartID);
                        break;
                    case 'TEXT':
                        $this->_parseStructureTextArray($structurePart, 
                                                        $subMimeParts, 
                                                        $partID . $subPartID);
                        break;
                    default:
                        $this->_parseStructureApplicationArray($structurePart, 
                                                               $subMimeParts, 
                                                               $partID . $subPartID);
                        break;
                    }
                }
                $subPartID++;
            } else {
                $part           = new stdClass;
                $part->type     = 'MULTIPART';
                $part->subType  = strtoupper($structurePart);
                $part->subParts = $subMimeParts;
          
                if ($_partID == '') {
                    $part->partID = 0;
                    $_mimeParts   = array(0 => $part);
                } else {
                    $part->partID         = $_partID;
                    $_mimeParts[$_partID] = $part;
                }
                return;
            }
        }
    }



    /**
     * Parse structure image array
     *
     * @param array $_structure  Structure array
     * @param array &$_mimeParts Mime parts
     * @param int   $_partID     Part ID
     *
     * @return noting
     *
     * @access private
     */
    function _parseStructureImageArray($_structure, &$_mimeParts, $_partID) 
    {
        // print "Net_IMAP::_parseStructureImageArray _partID: $_partID
"; $part = $this->_parseStructureCommonFields($_structure); $part->cid = $_structure[3]; $part->partID = $_partID; $_mimeParts[$_partID] = $part; } /** * Parse structure application array * * @param array $_structure Structure array * @param array &$_mimeParts Mime parts * @param int $_partID Part ID * * @return noting * * @access private */ function _parseStructureApplicationArray($_structure, &$_mimeParts, $_partID) { // print "Net_IMAP::_parseStructureApplicationArray _partID: $_partID
"; $part = $this->_parseStructureCommonFields($_structure); if (is_array($_structure[8])) { if (isset($_structure[8][0]) && $_structure[8][0] != 'NIL') { $part->disposition = strtoupper($_structure[8][0]); } if (is_array($_structure[8][1])) { foreach ($_structure[8][1] as $key => $value) { if ($key%2 == 0) { $part->dparameters[strtoupper($_structure[8][1][$key])] = $_structure[8][1][$key+1]; } } } } $part->partID = $_partID; $_mimeParts[$_partID] = $part; } /** * Parse structure message array * * @param array $_structure Structure array * @param array &$_mimeParts Mime parts * @param int $_partID Part ID * * @return nothing * * @access private */ function _parseStructureMessageArray($_structure, &$_mimeParts, $_partID) { // print "Net_IMAP::_parseStructureMessageArray _partID: $_partID
"; $part = $this->_parseStructureCommonFields($_structure); if (is_array($_structure[8][0])) { $this->_parseStructureMultipartArray($_structure[8], $subMimeParts, $_partID . '.1', true); } else { $this->_parseStructureArray($_structure[8], $subMimeParts, $_partID); } if (is_array($subMimeParts)) { $part->subParts = $subMimeParts; } $part->partID = $_partID; $_mimeParts[$_partID] = $part; } /** * Parse structure text array * * @param array $_structure Structure array * @param array &$_mimeParts Mime parts * @param int $_partID Part ID * * @return nothing * * @access private */ function _parseStructureTextArray($_structure, &$_mimeParts, $_partID) { // print "Net_IMAP::_parseStructureTextArray _partID: $_partID
"; $part = $this->_parseStructureCommonFields($_structure); $part->lines = $_structure[7]; if (is_array($_structure[8])) { if (isset($_structure[8][0]) && $_structure[8][0] != 'NIL') { $part->disposition = strtoupper($_structure[8][0]); } if (is_array($_structure[8][1])) { foreach ($_structure[8][1] as $key => $value) { if ($key%2 == 0) { $part->dparameters[strtoupper($_structure[8][1][$key])] = $_structure[8][1][$key+1]; } } } } if (is_array($_structure[9])) { if (isset($_structure[9][0]) && $_structure[9][0] != 'NIL') { $part->disposition = strtoupper($_structure[9][0]); } if (is_array($_structure[9][1])) { foreach ($_structure[9][1] as $key => $value) { if ($key%2 == 0) { $part->dparameters[strtoupper($_structure[9][1][$key])] = $_structure[9][1][$key+1]; } } } } $part->partID = $_partID; $_mimeParts[$_partID] = $part; } /** * Parse structure common fields * * @param array &$_structure Structure array * * @return object part object (stdClass) * * @access private */ function _parseStructureCommonFields(&$_structure) { // print "Net_IMAP::_parseStructureTextArray _partID: $_partID
"; $part = new stdClass; $part->type = strtoupper($_structure[0]); $part->subType = strtoupper($_structure[1]); if (is_array($_structure[2])) { foreach ($_structure[2] as $key => $value) { if ($key%2 == 0) { $part->parameters[strtoupper($_structure[2][$key])] = $_structure[2][$key+1]; } } } $part->filename = $_structure[4]; $part->encoding = strtoupper($_structure[5]); $part->bytes = $_structure[6]; return $part; } /** * Returns the entire message with given message number. * * @param int $msg_id Message number (default = null) * @param boolean $indexIsMessageNumber true if index is a message number * (default = true) * * @return mixed Either entire message or false on error * * @access public */ function getMessages($msg_id = null, $indexIsMessageNumber=true) { // $resp=$this->cmdFetch($msg_id,"(BODY[TEXT] BODY[HEADER])"); if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if (!$indexIsMessageNumber) { $ret = $this->cmdUidFetch($message_set, 'RFC822'); } else { $ret = $this->cmdFetch($message_set, 'RFC822'); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED'])) { foreach ($ret['PARSED'] as $msg) { if (isset($msg['EXT']['RFC822']['CONTENT'])) { if ($indexIsMessageNumber) { $ret_aux[$msg['NRO']] = $msg['EXT']['RFC822']['CONTENT']; } else { $ret_aux[] = $msg['EXT']['RFC822']['CONTENT']; } } } return $ret_aux; } return array(); } /** * Returns number of messages in this mailbox * * @param string $mailbox the mailbox (default is current mailbox) * * @return mixed Either number of messages or Pear_Error on failure * * @access public */ function getNumberOfMessages($mailbox = '') { if ($mailbox == '' || $mailbox == null) { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdStatus($mailbox, 'MESSAGES'))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES'])) { if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES'])) { // if this array does not exists means that there is no // messages in the mailbox return 0; } else { return $ret['PARSED']['STATUS']['ATTRIBUTES']['MESSAGES']; } } return 0; } /** * Returns number of UnSeen messages in this mailbox * * @param string $mailbox the mailbox (default is current mailbox) * * @return mixed Either number of messages or Pear_Error on failure * * @access public */ function getNumberOfUnSeenMessages($mailbox = '') { if ($mailbox == '' ) { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdStatus($mailbox, 'UNSEEN'))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret["RESPONSE"]["CODE"] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN'])) { if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN'])) { // if this array does not exists means that there is // no messages in the mailbox return 0; } else { return $ret['PARSED']['STATUS']['ATTRIBUTES']['UNSEEN']; } } return 0; } /** * Returns number of UnSeen messages in this mailbox * * @param string $mailbox the mailbox (default is current mailbox) * * @return mixed Either number of messages or Pear_Error on failure * * @access public */ function getNumberOfRecentMessages($mailbox = '') { if ($mailbox == '' ) { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdStatus($mailbox, 'RECENT'))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'])) { if (!is_numeric($ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'])) { // if this array does not exists means that there is no messages in the mailbox return 0; } else { return $ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT']; } } return 0; } /** * Returns number of UnSeen messages in this mailbox * * @param string $mailbox the mailbox (default is current mailbox) * * @return mixed Either number of messages or Pear_Error on error * * @access public */ function getStatus($mailbox = '') { if ($mailbox == '') { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdStatus($mailbox, array('MESSAGES', 'RECENT', 'UIDNEXT', 'UIDVALIDITY', 'UNSEEN')))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['STATUS']['ATTRIBUTES']['RECENT'])) { return $ret['PARSED']['STATUS']['ATTRIBUTES']; } return 0; } /** * Returns an array containing the message envelope * * @param string $mailbox get's not used anywhere (will be removed * with next major release) * @param mixed $msg_id Message number (default = null) * @param boolean $uidFetch msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed Either the envelopes or Pear_Error on error * * @access public */ function getEnvelope($mailbox = '', $msg_id = null, $uidFetch = false) { if ($mailbox == '') { $mailbox = $this->getCurrentMailbox(); } if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if ($uidFetch) { $ret = $this->cmdUidFetch($message_set, 'ENVELOPE'); } else { $ret = $this->cmdFetch($message_set, 'ENVELOPE'); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED'])) { for ($i=0; $igetCurrentMailbox()) { // store the actual selected mailbox name $mailbox_aux = $this->getCurrentMailbox(); if (PEAR::isError($ret = $this->selectMailbox($mailbox))) { return $ret; } } $ret = $this->cmdFetch('1:*', 'RFC822.SIZE'); if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { // Restore the default mailbox if it was changed if ($mailbox != '' && $mailbox != $this->getCurrentMailbox()) { if (PEAR::isError($ret = $this->selectMailbox($mailbox_aux))) { return $ret; } } // return 0 because the server says that there is no message // in the mailbox return 0; } $sum = 0; if (!isset($ret['PARSED'])) { // if the server does not return a "PARSED" part // we think that it does not suppoprt select or has no messages // in it. return 0; } foreach ($ret['PARSED'] as $msgSize) { if (isset($msgSize['EXT']['RFC822.SIZE'])) { $sum += $msgSize['EXT']['RFC822.SIZE']; } } if ($mailbox != '' && $mailbox != $this->getCurrentMailbox()) { // re-select the mailbox if (PEAR::isError($ret = $this->selectMailbox($mailbox_aux))) { return $ret; } } return $sum; } /** * Marks a message for deletion. Only will be deleted if the * disconnect() method is called with auto-expunge on true or expunge() * method is called. * * @param int $msg_id Message to delete (default = null) * @param boolean $uidStore msg_id contains UID's instead of Message * Sequence Number if set to true (default = false) * * @return mixed true on success / Pear_Error on failure * * @access public */ function deleteMessages($msg_id = null, $uidStore = false) { /* As said in RFC2060... C: A003 STORE 2:4 +FLAGS (\Deleted) S: * 2 FETCH FLAGS (\Deleted \Seen) S: * 3 FETCH FLAGS (\Deleted) S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) S: A003 OK STORE completed */ // Called without parammeters deletes all the messages in the mailbox // You can also provide an array of numbers to delete those emails if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } $dataitem = '+FLAGS.SILENT'; $value = '\Deleted'; if ($uidStore == true) { $ret = $this->cmdUidStore($message_set, $dataitem, $value); } else { $ret = $this->cmdStore($message_set, $dataitem, $value); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Copies mail from one folder to another * * @param string $dest_mailbox mailbox name to copy sessages to * @param mixed $msg_id the messages that I want to copy (all * by default) it also can be an array * @param string $source_mailbox mailbox name from where the messages are * copied (default is current mailbox) * @param boolean $uidCopy msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed true on Success/PearError on Failure * * @access public * @since 1.0 */ function copyMessages($dest_mailbox, $msg_id = null, $source_mailbox = null, $uidCopy = false) { if ($source_mailbox == null) { $source_mailbox = $this->getCurrentMailbox(); } else { if (PEAR::isError($ret = $this->selectMailbox($source_mailbox))) { return $ret; } } // Called without parammeters copies all messages in the mailbox // You can also provide an array of numbers to copy those emails if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if ($uidCopy == true) { $ret = $this->cmdUidCopy($message_set, $dest_mailbox); } else { $ret = $this->cmdCopy($message_set, $dest_mailbox); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Appends a mail to a mailbox * * @param string $rfc_message the message to append in RFC822 format * @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 * * @access public * @since 1.0 */ function appendMessage($rfc_message, $mailbox = null, $flags_list = '') { if ($mailbox == null) { $mailbox = $this->getCurrentMailbox(); } $ret = $this->cmdAppend($mailbox, $rfc_message, $flags_list); if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Returns the namespace * * @return mixed namespace or PearError on failure * * @access public * @since 1.1 */ function getNamespace() { if (PEAR::isError($ret = $this->cmdNamespace())) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } foreach ($ret['PARSED']['NAMESPACES'] as $type => $singleNameSpace) { if (!is_array($singleNameSpace)) { continue; } foreach ($singleNameSpace as $nameSpaceData) { $nameSpaces[$type][] = array( 'name' => $this->utf7Decode($nameSpaceData[0]), 'delimter' => $this->utf7Decode($nameSpaceData[1]) ); } } return $nameSpaces; } /****************************************************************** ** ** ** MAILBOX RELATED METHODS ** ** ** ******************************************************************/ /** * Gets the HierachyDelimiter character used to create subfolders * cyrus users "." * and wu-imapd uses "/" * * @param string $mailbox The mailbox to get the hierarchy from * * @return string The hierarchy delimiter * * @access public * @since 1.0 */ function getHierarchyDelimiter($mailbox = '') { /* RFC2060 says: "the command LIST "" "" means get the hierachy delimiter: An empty ("" string) mailbox name argument is a special request to return the hierarchy delimiter and the root name of the name given in the reference. The value returned as the root MAY be null if the reference is non-rooted or is null. In all cases, the hierarchy delimiter is returned. This permits a client to get the hierarchy delimiter even when no mailboxes by that name currently exist." */ if (PEAR::isError($ret = $this->cmdList($mailbox, ''))) { return $ret; } if (isset($ret['PARSED'][0]['EXT']['LIST']['HIERACHY_DELIMITER'])) { return $ret['PARSED'][0]['EXT']['LIST']['HIERACHY_DELIMITER']; } return new PEAR_Error('the IMAP Server does not support ' . 'HIERACHY_DELIMITER!'); } /** * Returns an array containing the names of the selected mailboxes * * @param string $reference base mailbox to start the search * (default is current mailbox) * @param string $restriction_search false or 0 means return all mailboxes * true or 1 return only the mailbox that * contains that exact name * 2 return all mailboxes in that * hierarchy level * @param string $returnAttributes true means return an assoc array * containing mailbox names and mailbox * attributes,false - the default - means * return an array of mailboxes * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function getMailboxes($reference = '', $restriction_search = 0, $returnAttributes = false) { if (is_bool($restriction_search)) { $restriction_search = (int) $restriction_search; } if (is_int($restriction_search)) { switch ($restriction_search) { case 0: $mailbox = '*'; break; case 1: $mailbox = $reference; $reference = ''; break; case 2: $mailbox = '%'; break; } } else { if (is_string($restriction_search)) { $mailbox = $restriction_search; } else { return new PEAR_Error('Wrong data for 2nd parameter'); } } if (PEAR::isError($ret = $this->cmdList($reference, $mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret_aux = array(); if (isset($ret['PARSED'])) { foreach ($ret['PARSED'] as $mbox) { // If the folder has the \NoSelect atribute we don't put in // the list // it solves a bug in wu-imap that crash the IMAP server if // we select that mailbox if (isset($mbox['EXT']['LIST']['NAME_ATTRIBUTES'])) { // if (!in_array('\NoSelect', // $mbox['EXT']['LIST']['NAME_ATTRIBUTES'])) { if ($returnAttributes) { $ret_aux[] = array( 'MAILBOX' => $mbox['EXT']['LIST']['MAILBOX_NAME'], 'ATTRIBUTES' => $mbox['EXT']['LIST']['NAME_ATTRIBUTES'], 'HIERACHY_DELIMITER' => $mbox['EXT']['LIST']['HIERACHY_DELIMITER']); } else { $ret_aux[] = $mbox['EXT']['LIST']['MAILBOX_NAME']; } // } } } } return $ret_aux; } /** * Check if the mailbox name exists * * @param string $mailbox Mailbox name to check existance * * @return mixed boolean true/false or PEAR_Error on failure * * @access public * @since 1.0 */ function mailboxExist($mailbox) { // true means do an exact match if (PEAR::isError($ret = $this->getMailboxes($mailbox, true))) { return $ret; } if (count($ret) > 0) { foreach ($ret as $mailbox_name) { if ($mailbox_name == $mailbox) { return true; } } } return false; } /** * Creates the mailbox $mailbox * * @param string $mailbox Mailbox name to create * @param array $options Options to pass to create (default is no options) * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function createMailbox($mailbox, $options = null) { if (PEAR::isError($ret = $this->cmdCreate($mailbox, $options))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Deletes the mailbox $mailbox * * @param string $mailbox Name of the Mailbox that should be deleted * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function deleteMailbox($mailbox) { // TODO verificar que el mailbox se encuentra vacio y, sino borrar los // mensajes antes~!!!!!! // ToDo find someone who can translate the above todo if (PEAR::isError($ret = $this->cmdDelete($mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Renames the mailbox $mailbox * * @param string $oldmailbox mailbox name to rename * @param string $newmailbox new name for the mailbox * @param array $options options to pass to rename * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function renameMailbox($oldmailbox, $newmailbox, $options = null) { if (PEAR::isError($ret = $this->cmdRename($oldmailbox, $newmailbox, $options))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /****************************************************************** ** ** ** SUBSCRIPTION METHODS ** ** ** ******************************************************************/ /** * Subscribes to the selected mailbox * * @param string $mailbox Mailbox name to subscribe (default is current * mailbox) * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function subscribeMailbox($mailbox = null) { if ($mailbox == null) { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdSubscribe($mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Removes the subscription to a mailbox * * @param string $mailbox Mailbox name to unsubscribe (default is current * mailbox) * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function unsubscribeMailbox($mailbox = null) { if ($mailbox == null) { $mailbox = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdUnsubscribe($mailbox))) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Lists the subscription to mailboxes * * @param string $reference Mailbox name start the search (see to * getMailboxes() ) * @param string $restriction_search Mailbox_name Mailbox name filter the * search (see to getMailboxes() ) * @param boolean $returnAttributes Return the attributes * * @return mixed true on success/PearError on failure * * @access public * @since 1.0 */ function listsubscribedMailboxes($reference = '', $restriction_search = 0, $returnAttributes = false) { if (is_bool($restriction_search)) { $restriction_search = (int) $restriction_search; } if (is_int($restriction_search)) { switch ($restriction_search) { case 0: $mailbox = '*'; break; case 1: $mailbox = $reference; $reference = '%'; break; case 2: $mailbox = '%'; break; } } else { if (is_string($restriction_search)) { $mailbox = $restriction_search; } else { return new PEAR_Error('UPS... you '); } } if (PEAR::isError($ret = $this->cmdLsub($reference, $mailbox))) { return $ret; } // $ret=$this->cmdLsub($mailbox_base, $mailbox_name); if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret_aux = array(); if (isset($ret['PARSED'])) { foreach ($ret['PARSED'] as $mbox) { if (isset($mbox['EXT']['LSUB']['MAILBOX_NAME'])) { if ($returnAttributes) { $ret_aux[] = array( 'MAILBOX' => $mbox['EXT']['LSUB']['MAILBOX_NAME'], 'ATTRIBUTES' => $mbox['EXT']['LSUB']['NAME_ATTRIBUTES'], 'HIERACHY_DELIMITER' => $mbox['EXT']['LSUB']['HIERACHY_DELIMITER'] ); } else { $ret_aux[] = $mbox['EXT']['LSUB']['MAILBOX_NAME']; } } } } return $ret_aux; } /****************************************************************** ** ** ** FLAGS METHODS ** ** ** ******************************************************************/ /** * Lists the flags of the selected messages * * @param mixed $msg_id the message list * @param boolean $includeUid include uid in result * * @return mixed array on success/PearError on failure * * @access public * @since 1.0 */ function getFlags($msg_id = null, $includeUid = false) { // You can also provide an array of numbers to those emails if ($msg_id != null) { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } else { $message_set = '1:*'; } if ($includeUid) { $ret = $this->cmdUidFetch($message_set, 'FLAGS'); } else { $ret = $this->cmdFetch($message_set, 'FLAGS'); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $flags = array(); if (isset($ret['PARSED'])) { foreach ($ret['PARSED'] as $msg_flags) { if (isset($msg_flags['EXT']['FLAGS'])) { $flags[] = $msg_flags['EXT']['FLAGS']; } } } return $flags; } /** * Sets the flags of the selected messages * * @param mixed $msg_id the message list or string "all" for all * @param mixed $flags flags to set (space separated String or array) * @param string $mod "set" to set flags (default), * "add" to add flags, * "remove" to remove flags * @param boolean $uidStore msg_id contains UID's instead of Message * Sequence Number if set to true * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function setFlags($msg_id, $flags, $mod = 'set', $uidStore = false) { // you can also provide an array of numbers to those emails if ($msg_id == 'all') { $message_set = '1:*'; } else { if (is_array($msg_id)) { $message_set = $this->_getSearchListFromArray($msg_id); } else { $message_set = $msg_id; } } $flaglist = ''; if (is_array($flags)) { $flaglist = implode(' ', $flags); } else { $flaglist = $flags; } switch ($mod) { case 'set': $dataitem = 'FLAGS'; break; case 'add': $dataitem = '+FLAGS'; break; case 'remove': $dataitem = '-FLAGS'; break; default: // Wrong Input return new PEAR_Error('wrong input for $mod'); break; } if ($uidStore == true) { $ret = $this->cmdUidStore($message_set, $dataitem, $flaglist); } else { $ret = $this->cmdStore($message_set, $dataitem, $flaglist); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * adds flags to the selected messages * * @param mixed $msg_id The message list or string "all" for all * @param mixed $flags Flags to set (space separated String or array) * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addFlags($msg_id, $flags) { return $this->setFlags($msg_id, $flags, $mod = 'add'); } /** * adds the Seen flag (\Seen) to the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addSeen($msg_id) { return $this->setFlags($msg_id, '\Seen', $mod = 'add'); } /** * adds the Answered flag (\Answered) to the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addAnswered($msg_id) { return $this->setFlags($msg_id, '\Answered', $mod = 'add'); } /** * adds the Deleted flag (\Deleted) to the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addDeleted($msg_id) { return $this->setFlags($msg_id, '\Deleted', $mod = 'add'); } /** * adds the Flagged flag (\Flagged) to the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addFlagged($msg_id) { return $this->setFlags($msg_id, '\Flagged', $mod = 'add'); } /** * adds the Draft flag (\Draft) to the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function addDraft($msg_id) { return $this->setFlags($msg_id, '\Draft', $mod = 'add'); } /** * remove flags from the selected messages * * @param mixed $msg_id The message list or string "all" for all * @param mixed $flags Flags to remove (space separated string or array) * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeFlags($msg_id, $flags) { return $this->setFlags($msg_id, $flags, $mod = 'remove'); } /** * remove the Seen flag (\Seen) from the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeSeen($msg_id) { return $this->setFlags($msg_id, '\Seen', $mod = 'remove'); } /** * remove the Answered flag (\Answered) from the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeAnswered($msg_id) { return $this->setFlags($msg_id, '\Answered', $mod = 'remove'); } /** * remove the Deleted flag (\Deleted) from the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeDeleted($msg_id) { return $this->setFlags($msg_id, '\Deleted', $mod = 'remove'); } /** * remove the Flagged flag (\Flagged) from the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeFlagged($msg_id) { return $this->setFlags($msg_id, '\Flagged', $mod = 'remove'); } /** * remove the Draft flag (\Draft) from the selected messages * * @param mixed $msg_id The message list or string "all" for all * * @return mixed true on success/PearError on failure * * @access public * @since 1.1 */ function removeDraft($msg_id) { return $this->setFlags($msg_id, '\Draft', $mod = 'remove'); } /** * check the Seen flag * * @param mixed $message_nro The message to check * * @return mixed true or false if the flag is set PearError on Failure * * @access public * @since 1.0 */ function isSeen($message_nro) { return $this->hasFlag($message_nro, '\Seen'); } /** * check the Answered flag * * @param mixed $message_nro The message to check * * @return mixed true or false if the flag is set PearError on failure * * @access public * @since 1.0 */ function isAnswered($message_nro) { return $this->hasFlag($message_nro, '\Answered'); } /** * check the flagged flag * * @param mixed $message_nro The message to check * * @return mixed true or false if the flag is set PearError on failure * * @access public * @since 1.0 */ function isFlagged($message_nro) { return $this->hasFlag($message_nro, '\Flagged'); } /** * check the Draft flag * * @param mixed $message_nro The message to check * * @return mixed true or false if the flag is set PearError on failure * * @access public * @since 1.0 */ function isDraft($message_nro) { return $this->hasFlag($message_nro, '\Draft'); } /** * check the Deleted flag * * @param mixed $message_nro The message to check * * @return mixed true or false if the flag is set PearError on failure * * @access public * @since 1.0 */ function isDeleted($message_nro) { return $this->hasFlag($message_nro, '\Deleted'); } /** * checks if a flag is set * * @param mixed $message_nro The message to check * @param string $flag The flag that should be checked * * @return mixed true or false if the flag is set PearError on Failure * * @access public * @since 1.0 */ function hasFlag($message_nro, $flag) { if (PEAR::isError($resp = $this->getFlags($message_nro))) { return $resp; } if (isset($resp[0])) { if (is_array($resp[0])) { if (in_array($flag, $resp[0])) { return true; } } } return false; } /****************************************************************** ** ** ** MISC METHODS ** ** ** ******************************************************************/ /** * expunge function. Sends the EXPUNGE command * * @return mixed true on success / PEAR Error on failure * * @access public * @since 1.0 */ function expunge() { if (PEAR::isError($ret = $this->cmdExpunge())) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * Search function. Sends the SEARCH command * * @param string $search_list Search criterias * @param boolean $uidSearch If set to true UID SEARCH is send * instead of SEARCH * * @return mixed Message array or PEAR Error on failure * * @access public * @since 1.0 */ function search($search_list, $uidSearch = false) { if ($uidSearch) { $ret = $this->cmdUidSearch($search_list); } else { $ret = $this->cmdSearch($search_list); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return $ret['PARSED']['SEARCH']['SEARCH_LIST']; } /** * sort function. Sends the SORT command * * @param string $sort_list sort program * @param string $charset charset specification (default = 'US-ASCII') * @param string $search_list searching criteria * @param boolean $uidSort if set to true UID SORT is send instead * of SORT * * @return mixed message array or PEAR Error on failure * * @access public * @since 1.1 */ function sort($sort_list, $charset = 'US-ASCII', $search_list = '', $uidSort = false) { $sort_command = sprintf("(%s) %s %s", $sort_list, strtoupper($charset), $search_list); if ($uidSort) { $ret = $this->cmdUidSort($sort_command); } else { $ret = $this->cmdSort($sort_command); } if (PEAR::isError($ret)) { return $ret; } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return $ret['PARSED']['SORT']['SORT_LIST']; } /****************************************************************** ** ** ** QUOTA METHODS ** ** ** ******************************************************************/ /** * Returns STORAGE quota details * * @param string $mailbox_name Mailbox to get quota info. (default is * current mailbox) * * @return assoc array contaning the quota info on success or * PEAR_Error on failure * * @access public * @since 1.0 */ function getStorageQuotaRoot($mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdGetQuotaRoot($mailbox_name))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { // if the error is that the user does not have quota set // return an array and not pear error if (substr(strtoupper($ret['RESPONSE']['STR_CODE']), 0, 9) == 'QUOTAROOT') { return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['EXT']['QUOTA']['STORAGE'])) { return $ret['PARSED']['EXT']['QUOTA']['STORAGE']; } return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } /** * Returns STORAGE quota details * * @param string $mailbox_name Mailbox to get quota info. (default is * current mailbox) * * @return assoc array contaning the quota info on success or PEAR_Error * on failure * * @access public * @since 1.0 */ function getStorageQuota($mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdGetQuota($mailbox_name))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { // if the error is that the user does not have quota set // return an array and not pear error if (substr(strtoupper($ret['RESPONSE']['STR_CODE']), 0, 5) == 'QUOTA') { return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['EXT']['QUOTA']['STORAGE'])) { return $ret['PARSED']['EXT']['QUOTA']['STORAGE']; } return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } /** * Returns MESSAGES quota details * * @param string $mailbox_name Mailbox to get quota info. (default is * current mailbox) * * @return assoc array contaning the quota info on success or PEAR_Error * on failure * * @access public * @since 1.0 */ function getMessagesQuota($mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdGetQuota($mailbox_name))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { // if the error is that the user does not have quota set return // an array and not pear error if (substr(strtoupper($ret['RESPONSE']['STR_CODE']), 0, 5) == 'QUOTA') { return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['EXT']['QUOTA']['MESSAGES'])) { return $ret['PARSED']['EXT']['QUOTA']['MESSAGES']; } return array('USED'=>'NOT SET', 'QMAX'=>'NOT SET'); } /** * sets STORAGE quota * * @param string $mailbox_name Mailbox to set quota * @param int $quota Quotasize * * @return true on success or PEAR_Error on failure * * @access public * @since 1.0 */ function setStorageQuota($mailbox_name, $quota) { if (PEAR::isError($ret = $this->cmdSetQuota($mailbox_name, $quota))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * sets MESSAGES quota * * @param string $mailbox_name Mailbox to set quota * @param int $quota Quotasize * * @return true on success or PEAR_Error on failure * * @access public * @since 1.0 */ function setMessagesQuota($mailbox_name, $quota) { if (PEAR::isError($ret = $this->cmdSetQuota($mailbox_name, '', $quota))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /****************************************************************** ** ** ** ACL METHODS ** ** ** ******************************************************************/ /** * get the Access Control List details * * @param string $mailbox_name Mailbox to get ACL info. (default is * current mailbox) * * @return mixed string on success or false or PEAR_Error on failure * * @access public * @since 1.0 */ function getACL($mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdGetACL($mailbox_name))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['USERS'])) { return $ret['PARSED']['USERS']; } else { return false; } } /** * Set ACL on a mailbox * * @param string $mailbox_name The mailbox * @param string $user User to set the ACL * @param string $acl ACL list * * @return mixed true on success or PEAR_Error on failure * * @access public * @since 1.0 */ function setACL($mailbox_name, $user, $acl) { if (PEAR::isError($ret = $this->cmdSetACL($mailbox_name, $user, $acl))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * deletes the ACL on a mailbox * * @param string $mailbox_name The mailbox * @param string $user User to delete the ACL * * @return mixed true on success, or PEAR_Error on failure * * @access public * @since 1.0 */ function deleteACL($mailbox_name, $user) { if (PEAR::isError($ret = $this->cmdDeleteACL($mailbox_name, $user))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * returns the rights that the user logged on has on the mailbox * this method can be used by any user, not only the administrator * * @param string $mailbox_name The mailbox to query rights (default is * current mailbox) * * @return mixed string containing the list of rights on success, or * PEAR_Error on failure * * @access public * @since 1.0 */ function getMyRights($mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdMyRights($mailbox_name))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['GRANTED'])) { return $ret['PARSED']['GRANTED']; } return new PEAR_Error('Bogus response from server!'); } /** * returns an array containing the rights for given user on the mailbox * this method can be used by any user, not only the administrator * * @param string $user The user to query rights * @param string $mailbox_name The mailbox to query rights (default is * current mailbox) * * @return mixed string containing the list of rights on success, or * PEAR_Error on failure * * @access public * @since 1.0 */ function getACLRights($user,$mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdListRights($mailbox_name, $user))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } if (isset($ret['PARSED']['GRANTED'])) { return $ret['PARSED']['GRANTED']; } return new PEAR_Error('Bogus response from server!'); } /****************************************************************** ** ** ** ANNOTATEMORE METHODS ** ** ** ******************************************************************/ /** * set annotation * * @param string $entry Entry * @param array $values Values * @param string $mailbox_name Mailbox name (default is current mailbox) * * @return mixed true on success or PEAR Error on failure * * @access public * @since 1.0.2 */ function setAnnotation($entry, $values, $mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdSetAnnotation($mailbox_name, $entry, $values))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * delete annotation * * @param string $entry Entry * @param array $values Values * @param string $mailbox_name Mailbox name (default is current mailbox) * * @return mixed true on success or PEAR Error on failure * * @access public * @since 1.0.2 */ function deleteAnnotation($entry, $values, $mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (PEAR::isError($ret = $this->cmdDeleteAnnotation($mailbox_name, $entry, $values))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } return true; } /** * get annotation * * @param string $entries Entries * @param array $values Values * @param string $mailbox_name Mailbox name (default is current mailbox) * * @return mixed array containing annotations on success or PEAR Error * on failure * * @access public * @since 1.0.2 */ function getAnnotation($entries, $values, $mailbox_name = null) { if ($mailbox_name == null) { $mailbox_name = $this->getCurrentMailbox(); } if (!is_array($entries)) { $entries = array($entries); } if (!is_array($values)) { $values = array($values); } if (PEAR::isError($ret = $this->cmdGetAnnotation($mailbox_name, $entries, $values))) { return new PEAR_Error($ret->getMessage()); } if (strtoupper($ret['RESPONSE']['CODE']) != 'OK') { return new PEAR_Error($ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']); } $ret_aux = array(); if (isset($ret['PARSED'])) { foreach ($ret['PARSED'] as $mbox) { $rawvalues = $mbox['EXT']['ATTRIBUTES']; $values = array(); for ($i = 0; $i < count($rawvalues); $i += 2) { $values[$rawvalues[$i]] = $rawvalues[$i + 1]; } $mbox['EXT']['ATTRIBUTES'] = $values; $ret_aux[] = $mbox['EXT']; } } if (count($ret_aux) == 1 && $ret_aux[0]['MAILBOX'] == $mailbox_name) { if (count($entries) == 1 && $ret_aux[0]['ENTRY'] == $entries[0]) { if (count($ret_aux[0]['ATTRIBUTES']) == 1 && count($values) == 1) { $attrs = array_keys($ret_aux[0]['ATTRIBUTES']); $vals = array_keys($values); if ($attrs[0] == $vals[0]) { return $ret_aux[0]['ATTRIBUTES'][$attrs[0]]; } } } } return $ret_aux; } /** * Transform an array to a list to be used in the cmdFetch method * * @param array $arr Array that should be transformed * * @return string transformed array * * @access private */ function _getSearchListFromArray($arr) { $txt = implode(',', $arr); return $txt; } /***************************************************** Net_POP3 Compatibility functions: Warning!!! Those functions could dissapear in the future *********************************************************/ /** * same as getMailboxSize() * Net_POP3 Compatibility function * * @return same as getMailboxSize(); * * @access public */ function getSize() { return $this->getMailboxSize(); } /** * same as getNumberOfMessages($mailbox) * Net_POP3 Compatibility function * * @param string $mailbox Mailbox (default is current mailbox) * * @return same as getNumberOfMessages($mailbox) * * @access public */ function numMsg($mailbox = null) { return $this->getNumberOfMessages($mailbox); } /** * Returns the entire message with given message number. * Net_POP3 Compatibility function * * @param int $msg_id Message number * * @return mixed Either entire message or PEAR Error on failure * * @access public */ function getMsg($msg_id) { if (PEAR::isError($ret = $this->getMessages($msg_id, false))) { return $ret; } // false means that getMessages() must not use the msg number as array key if (isset($ret[0])) { return $ret[0]; } else { return $ret; } } /** * same as getMessagesList($msg_id) * Net_POP3 Compatibility function * * @param int $msg_id Message number * * @return same as getMessagesList() * * @access public */ function getListing($msg_id = null) { return $this->getMessagesList($msg_id); } /** * same as deleteMessages($msg_id) * Net_POP3 Compatibility function * * @param int $msg_id Message number * * @return same as deleteMessages() * * @access public */ function deleteMsg($msg_id) { return $this->deleteMessages($msg_id); } } ?> php-net-imap-1.1.1/Net_IMAP-1.1.1/Net/IMAPProtocol.php000066400000000000000000003503401170170425600215200ustar00rootroot00000000000000 * @copyright 1997-2003 The PHP Group * @license PHP license * @version CVS: $Id$ * @link http://pear.php.net/package/Net_IMAP */ /** * Net_IMAP requires Net_Socket */ require_once 'Net/Socket.php'; /** * Provides an implementation of the IMAP protocol using PEAR's * Net_Socket:: class. * * @category Networking * @package Net_IMAP * @author Damian Alejandro Fernandez Sosa * @license PHP license * @link http://pear.php.net/package/Net_IMAP */ class Net_IMAPProtocol { /** * The auth methods this class support * @var array */ var $supportedAuthMethods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN'); /** * The auth methods this class support * @var array */ var $supportedSASLAuthMethods = array('DIGEST-MD5', 'CRAM-MD5'); /** * _serverAuthMethods * @var boolean * @access private */ var $_serverAuthMethods = null; /** * The the current mailbox * @var string */ var $currentMailbox = 'INBOX'; /** * The socket resource being used to connect to the IMAP server. * @var resource * @access private */ var $_socket = null; /** * The timeout for the connection to the IMAP server. * @var int * @access private */ var $_timeout = null; /** * The options for SSL/TLS connection * (see documentation for stream_context_create) * @var array * @access private */ var $_streamContextOptions = null; /** * To allow class debuging * @var boolean * @access private */ var $_debug = false; var $dbgDialog = ''; /** * Print error messages * @var boolean * @access private */ var $_printErrors = false; /** * Command Number * @var int * @access private */ var $_cmd_counter = 1; /** * Command Number for IMAP commands * @var int * @access private */ var $_lastCmdID = 1; /** * Command Number * @var boolean * @access private */ var $_unParsedReturn = false; /** * _connected: checks if there is a connection made to a imap server or not * @var boolean * @access private */ var $_connected = false; /** * Capabilities * @var boolean * @access private */ var $_serverSupportedCapabilities = null; /** * Use UTF-7 funcionallity * @var boolean * @access private */ var $_useUTF_7 = true; /** * Character encoding * @var string * @access private */ var $_encoding = 'ISO-8859-1'; /** * Constructor * * Instantiates a new Net_IMAP object. * * @since 1.0 */ function Net_IMAPProtocol() { $this->_socket = new Net_Socket(); /* * Include the Auth_SASL package. If the package is not available, * we disable the authentication methods that depend upon it. */ if ((@include_once 'Auth/SASL.php') == false) { foreach ($this->supportedSASLAuthMethods as $SASLMethod) { $pos = array_search($SASLMethod, $this->supportedAuthMethods); unset($this->supportedAuthMethods[$pos]); } } } /** * Attempt to connect to the IMAP server. * * @param string $host Hostname of the IMAP server * @param int $port Port of the IMAP server (default = 143) * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdConnect($host = 'localhost', $port = 143) { if ($this->_connected) { return new PEAR_Error('already connected, logout first!'); } if (PEAR::isError($error = $this->_socket->connect($host, $port, null, $this->_timeout, $this->_streamContextOptions))) { return $error; } if ($port == 993) { if (!$this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { return new PEAR_Error('Failed to set crypto'); } } if (PEAR::isError($this->_getRawResponse())) { return new PEAR_Error('unable to open socket'); } $this->_connected = true; return true; } /** * get the cmd ID * * @return string Returns the CmdID and increment the counter * * @access private * @since 1.0 */ function _getCmdId() { $this->_lastCmdID = 'A000' . $this->_cmd_counter; $this->_cmd_counter++; return $this->_lastCmdID; } /** * get the last cmd ID * * @return string Returns the last cmdId * * @access public * @since 1.0 */ function getLastCmdId() { return $this->_lastCmdID; } /** * get current mailbox name * * @return string Returns the current mailbox * * @access public * @since 1.0 */ function getCurrentMailbox() { return $this->currentMailbox; } /** * Sets the debuging information on or off * * @param boolean $debug Turn debug on (true) or off (false) * * @return nothing * @access public * @since 1.0 */ function setDebug($debug = true) { $this->_debug = $debug; } /** * get the debug dialog * * @return string debug dialog * @access public */ function getDebugDialog() { return $this->dbgDialog; } /** * Sets printed output of errors on or of * * @param boolean $printErrors true to turn on, * false to turn off printed output * * @return nothing * @access public * @since 1.1 */ function setPrintErrors($printErrors = true) { $this->_printErrors = $printErrors; } /** * Send the given string of data to the server. * * @param string $data The string of data to send. * * @return mixed True on success or a PEAR_Error object on failure. * * @access private * @since 1.0 */ function _send($data) { if ($this->_socket->eof()) { return new PEAR_Error('Failed to write to socket: (connection lost!)'); } if (PEAR::isError($error = $this->_socket->write($data))) { return new PEAR_Error('Failed to write to socket: ' . $error->getMessage()); } if ($this->_debug) { // C: means this data was sent by the client (this class) echo 'C: ' . $data; $this->dbgDialog .= 'C: ' . $data; } return true; } /** * Receive the given string of data from the server. * * @return mixed a line of response on success or a PEAR_Error object on failure. * * @access private * @since 1.0 */ function _recvLn() { if (PEAR::isError($this->lastline = $this->_socket->gets(8192))) { return new PEAR_Error('Failed to write to socket: ' . $this->lastline->getMessage()); } if ($this->_debug) { // S: means this data was sent by the IMAP Server echo 'S: ' . $this->lastline; $this->dbgDialog .= 'S: ' . $this->lastline; } if ($this->lastline == '') { return new PEAR_Error('Failed to receive from the socket: '); } return $this->lastline; } /** * Send a command to the server with an optional string of arguments. * A carriage return / linefeed (CRLF) sequence will be appended to each * command string before it is sent to the IMAP server. * * @param string $commandId The IMAP cmdID to send to the server. * @param string $command The IMAP command to send to the server. * @param string $args A string of optional arguments to append * to the command. * * @return mixed The result of the _send() call. * * @access private * @since 1.0 */ function _putCMD($commandId , $command, $args = '') { if (!empty($args)) { return $this->_send($commandId . ' ' . $command . ' ' . $args . "\r\n"); } return $this->_send($commandId . ' ' . $command . "\r\n"); } /** * Get a response from the server with an optional string of commandID. * A carriage return / linefeed (CRLF) sequence will be appended to each * command string before it is sent to the IMAP server. * * @param string $commandId The IMAP commandid retrive from the server. * * @return string The result response. * @access private */ function _getRawResponse($commandId = '*') { $arguments = ''; while (!PEAR::isError($this->_recvLn())) { $reply_code = strtok($this->lastline, ' '); $arguments .= $this->lastline; if (!(strcmp($commandId, $reply_code))) { return $arguments; } } return $arguments; } /** * get the "returning of the unparsed response" feature status * * @return boolean return if the unparsed response is returned or not * * @access public * @since 1.0 * */ function getUnparsedResponse() { return $this->_unParsedReturn; } /** * set the options for a SSL/TLS connection * (see documentation for stream_context_create) * * @param array $options The options for the SSL/TLS connection * * @return nothing * @access public * @since 1.1 */ function setStreamContextOptions($options) { $this->_streamContextOptions = $options; } /** * set the the timeout for the connection to the IMAP server. * * @param int $timeout The timeout * * @return nothing * @access public * @since 1.1 */ function setTimeout($timeout) { $this->_timeout = $timeout; } /** * set the "returning of the unparsed response" feature on or off * * @param boolean $status true: feature is on * * @return nothing * @access public * @since 1.0 */ function setUnparsedResponse($status) { $this->_unParsedReturn = $status; } /** * Attempt to login to the iMAP server. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdLogin($uid, $pwd) { $param = '"' . $uid . '" "'. $pwd .'"'; return $this->_genericCommand('LOGIN', $param); } /** * Attempt to authenticate to the iMAP server. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * @param string $userMethod The cmdID. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdAuthenticate($uid, $pwd, $userMethod = null) { if (!$this->_connected) { return new PEAR_Error('not connected!'); } $cmdid = $this->_getCmdId(); if (PEAR::isError($method = $this->_getBestAuthMethod($userMethod))) { return $method; } switch ($method) { case 'DIGEST-MD5': $result = $this->_authDigestMD5($uid, $pwd, $cmdid); break; case 'CRAM-MD5': $result = $this->_authCramMD5($uid, $pwd, $cmdid); break; case 'LOGIN': $result = $this->_authLOGIN($uid, $pwd, $cmdid); break; default: $result = new PEAR_Error($method . ' is not a supported authentication' . ' method'); break; } $args = $this->_getRawResponse($cmdid); return $this->_genericImapResponseParser($args, $cmdid); } /** * Authenticates the user using the DIGEST-MD5 method. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * @param string $cmdid The cmdID. * * @return array Returns an array containing the response * @access private * @since 1.0 */ function _authDigestMD5($uid, $pwd, $cmdid) { if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'DIGEST-MD5'))) { return $error; } if (PEAR::isError($args = $this->_recvLn())) { return $args; } $this->_getNextToken($args, $plus); $this->_getNextToken($args, $space); $this->_getNextToken($args, $challenge); $challenge = base64_decode($challenge); $digest = &Auth_SASL::factory('digestmd5'); $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, 'localhost', 'imap')); if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { return $error; } if (PEAR::isError($args = $this->_recvLn())) { return $args; } // We don't use the protocol's third step because IMAP doesn't allow // subsequent authentication, so we just silently ignore it. if (PEAR::isError($error = $this->_send("\r\n"))) { return $error; } } /** * Authenticates the user using the CRAM-MD5 method. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * @param string $cmdid The cmdID. * * @return array Returns an array containing the response * @access private * @since 1.0 */ function _authCramMD5($uid, $pwd, $cmdid) { if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'CRAM-MD5'))) { return $error; } if (PEAR::isError($args = $this->_recvLn())) { return $args; } $this->_getNextToken($args, $plus); $this->_getNextToken($args, $space); $this->_getNextToken($args, $challenge); $challenge = base64_decode($challenge); $cram = &Auth_SASL::factory('crammd5'); $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { return $error; } } /** * Authenticates the user using the LOGIN method. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. * @param string $cmdid The cmdID. * * @return array Returns an array containing the response * @access private * @since 1.0 */ function _authLOGIN($uid, $pwd, $cmdid) { if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'LOGIN'))) { return $error; } if (PEAR::isError($args = $this->_recvLn())) { return $args; } $this->_getNextToken($args, $plus); $this->_getNextToken($args, $space); $this->_getNextToken($args, $challenge); $challenge = base64_decode($challenge); $auth_str = base64_encode($uid); if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { return $error; } if (PEAR::isError($args = $this->_recvLn())) { return $args; } $auth_str = base64_encode($pwd); if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { return $error; } } /** * Returns the name of the best authentication method that the server * has advertised. * * @param string $userMethod If !=null, authenticate with this * method ($userMethod). * * @return mixed Returns a string containing the name of the best * supported authentication method or a PEAR_Error object * if a failure condition is encountered. * @access private * @since 1.0 */ function _getBestAuthMethod($userMethod = null) { $this->cmdCapability(); if ($userMethod != null) { $methods = array(); $methods[] = $userMethod; } else { $methods = $this->supportedAuthMethods; } if (($methods != null) && ($this->_serverAuthMethods != null)) { foreach ($methods as $method) { if (in_array($method, $this->_serverAuthMethods)) { return $method; } } $serverMethods = implode(',', $this->_serverAuthMethods); $myMethods = implode(',', $this->supportedAuthMethods); return new PEAR_Error($method . ' NOT supported authentication' . ' method! This IMAP server supports these' . ' methods: ' . $serverMethods . ', but I' . ' support ' . $myMethods); } else { return new PEAR_Error('This IMAP server don\'t support any Auth' . ' methods'); } } /** * Attempt to disconnect from the iMAP server. * * @return array Returns an array containing the response * * @access public * @since 1.0 */ function cmdLogout() { if (!$this->_connected) { return new PEAR_Error('not connected!'); } if (PEAR::isError($args = $this->_genericCommand('LOGOUT'))) { return $args; } if (PEAR::isError($this->_socket->disconnect())) { return new PEAR_Error('socket disconnect failed'); } return $args; // not for now //return $this->_genericImapResponseParser($args,$cmdid); } /** * Send the NOOP command. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdNoop() { return $this->_genericCommand('NOOP'); } /** * Send the CHECK command. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdCheck() { return $this->_genericCommand('CHECK'); } /** * Send the Select Mailbox Command * * @param string $mailbox The mailbox to select. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdSelect($mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); if (!PEAR::isError($ret = $this->_genericCommand('SELECT', $mailbox_name))) { $this->currentMailbox = $mailbox; } return $ret; } /** * Send the EXAMINE Mailbox Command * * @param string $mailbox The mailbox to examine. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdExamine($mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); $ret = $this->_genericCommand('EXAMINE', $mailbox_name); $parsed = ''; if (isset($ret['PARSED'])) { for ($i=0; $i $parsed, 'RESPONSE' => $ret['RESPONSE']); } /** * Send the CREATE Mailbox Command * * @param string $mailbox The mailbox to create. * @param array $options Options to pass to create * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdCreate($mailbox, $options = null) { $args = ''; $mailbox_name = $this->_createQuotedString($mailbox); $args = $this->_getCreateParams($options); return $this->_genericCommand('CREATE', $mailbox_name . $args); } /** * Send the RENAME Mailbox Command * * @param string $mailbox The old mailbox name. * @param string $new_mailbox The new (renamed) mailbox name. * @param array $options options to pass to create * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdRename($mailbox, $new_mailbox, $options = null) { $mailbox_name = $this->_createQuotedString($mailbox); $new_mailbox_name = $this->_createQuotedString($new_mailbox); $args = $this->_getCreateParams($options); return $this->_genericCommand('RENAME', $mailbox_name . ' ' . $new_mailbox_name . $args); } /** * Send the DELETE Mailbox Command * * @param string $mailbox The mailbox name to delete. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdDelete($mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); return $this->_genericCommand('DELETE', $mailbox_name); } /** * Send the SUSCRIBE Mailbox Command * * @param string $mailbox The mailbox name to suscribe. * * @return array Returns an array containing the response * @access public * @since 1.0 */ function cmdSubscribe($mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); return $this->_genericCommand('SUBSCRIBE', $mailbox_name); } /** * Send the UNSUBSCRIBE Mailbox Command * * @param string $mailbox The mailbox name to unsubscribe * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdUnsubscribe($mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); return $this->_genericCommand('UNSUBSCRIBE', $mailbox_name); } /** * Send the FETCH Command * * @param string $msgset msgset * @param string $fetchparam fetchparam * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdFetch($msgset, $fetchparam) { return $this->_genericCommand('FETCH', $msgset . ' ' . $fetchparam); } /** * Send the CAPABILITY Command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdCapability() { $ret = $this->_genericCommand('CAPABILITY'); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']['CAPABILITY']; // fill the $this->_serverAuthMethods // and $this->_serverSupportedCapabilities arrays foreach ($ret['PARSED']['CAPABILITIES'] as $auth_method) { if (strtoupper(substr($auth_method, 0, 5)) == 'AUTH=') { $this->_serverAuthMethods[] = substr($auth_method, 5); } } // Keep the capabilities response to use ir later $this->_serverSupportedCapabilities = $ret['PARSED']['CAPABILITIES']; } return $ret; } /** * Send the CAPABILITY Command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdNamespace() { $ret = $this->_genericCommand('NAMESPACE'); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']['NAMESPACE']; // Keep the namespace response for later use $this->_namespace = $ret['PARSED']['NAMESPACES']; } return $ret; } /** * Send the STATUS Mailbox Command * * @param string $mailbox The mailbox name * @param mixed $request The request status * it could be an array or space separated string of * MESSAGES | RECENT | UIDNEXT * UIDVALIDITY | UNSEEN * * @return array Returns a Parsed Response * @access public * @since 1.0 */ function cmdStatus($mailbox, $request) { $mailbox_name = $this->_createQuotedString($mailbox); // make array from $request if it is none if (!is_array($request)) { $request = explode(' ', $request); } // see RFC 3501 $valid_status_data = array('MESSAGES', 'RECENT', 'UIDNEXT', 'UIDVALIDITY', 'UNSEEN'); foreach ($request as $status_data) { if (!in_array($status_data, $valid_status_data)) { $this->_protError('request "' . $status_data . '" is invalid! ' . 'See RFC 3501!!!!', __LINE__, __FILE__); } } // back to space separated string $request = implode(' ', $request); $ret = $this->_genericCommand('STATUS', $mailbox_name . ' (' . $request . ')'); if (!PEAR::isError($ret) && isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][count($ret['PARSED'])-1]['EXT']; } return $ret; } /** * Send the LIST Command * * @param string $mailbox_base mailbox_base * @param string $mailbox The mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdList($mailbox_base, $mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); $mailbox_base = $this->_createQuotedString($mailbox_base); return $this->_genericCommand('LIST', $mailbox_base . ' ' . $mailbox_name); } /** * Send the LSUB Command * * @param string $mailbox_base mailbox_base * @param string $mailbox The mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdLsub($mailbox_base, $mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); $mailbox_base = $this->_createQuotedString($mailbox_base); return $this->_genericCommand('LSUB', $mailbox_base . ' ' . $mailbox_name); } /** * Send the APPEND Command * * @param string $mailbox Mailbox name * @param string $msg Message * @param string $flags_list Flags list * @param string $time Time * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdAppend($mailbox, $msg, $flags_list = '', $time = '') { if (!$this->_connected) { return new PEAR_Error('not connected!'); } $cmdid = $this->_getCmdId(); $msg_size = $this->_getLineLength($msg); $mailbox_name = $this->_createQuotedString($mailbox); if ($flags_list != '') { $flags_list = ' (' . $flags_list . ')'; } if ($this->hasCapability('LITERAL+') == true) { if ($time != '') { $timeAsString = date("d-M-Y H:i:s O", $time); $param = sprintf("%s %s\"%s\"{%s+}\r\n%s", $mailbox_name, $flags_list, $timeAsString, $msg_size, $msg); } else { $param = sprintf("%s%s {%s+}\r\n%s", $mailbox_name, $flags_list, $msg_size, $msg); } if (PEAR::isError($error = $this->_putCMD($cmdid, 'APPEND', $param))) { return $error; } } else { $param = sprintf("%s%s {%s}", $mailbox_name, $flags_list, $msg_size); if (PEAR::isError($error = $this->_putCMD($cmdid, 'APPEND', $param))) { return $error; } if (PEAR::isError($error = $this->_recvLn())) { return $error; } if (PEAR::isError($error = $this->_send($msg . "\r\n"))) { return $error; } } $args = $this->_getRawResponse($cmdid); $ret = $this->_genericImapResponseParser($args, $cmdid); return $ret; } /** * Send the CLOSE command. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdClose() { return $this->_genericCommand('CLOSE'); } /** * Send the EXPUNGE command. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ 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"]); foreach ($parsed as $command) { if (strtoupper($command['COMMAND']) == 'EXPUNGE') { $ret['PARSED'][$command['COMMAND']][] = $command['NRO']; } else { $ret['PARSED'][$command['COMMAND']] = $command['NRO']; } } } return $ret; } /** * Send the SEARCH command. * * @param string $search_cmd Search command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdSearch($search_cmd) { /* if($_charset != '' ) $_charset = "[$_charset] "; $param=sprintf("%s%s",$charset,$search_cmd); */ $ret = $this->_genericCommand('SEARCH', $search_cmd); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the SORT command. * * @param string $sort_cmd Sort command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.1 */ function cmdSort($sort_cmd) { /* if ($_charset != '' ) $_charset = "[$_charset] "; $param = sprintf("%s%s",$charset,$search_cmd); */ $ret = $this->_genericCommand('SORT', $sort_cmd); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the STORE command. * * @param string $message_set The sessage_set * @param string $dataitem The way we store the flags * FLAGS: replace the flags whith $value * FLAGS.SILENT: replace the flags whith $value * but don't return untagged responses * +FLAGS: Add the flags whith $value * +FLAGS.SILENT: Add the flags whith $value * but don't return untagged responses * -FLAGS: Remove the flags whith $value * -FLAGS.SILENT: Remove the flags whith $value * but don't return untagged responses * @param string $value Value * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdStore($message_set, $dataitem, $value) { /* As said in RFC2060... C: A003 STORE 2:4 +FLAGS (\Deleted) S: * 2 FETCH FLAGS (\Deleted \Seen) S: * 3 FETCH FLAGS (\Deleted) S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) S: A003 OK STORE completed */ if ($dataitem != 'FLAGS' && $dataitem != 'FLAGS.SILENT' && $dataitem != '+FLAGS' && $dataitem != '+FLAGS.SILENT' && $dataitem != '-FLAGS' && $dataitem != '-FLAGS.SILENT') { $this->_protError('dataitem "' . $dataitem . '" is invalid! ' . 'See RFC2060!!!!', __LINE__, __FILE__); } $param = sprintf("%s %s (%s)", $message_set, $dataitem, $value); return $this->_genericCommand('STORE', $param); } /** * Send the COPY command. * * @param string $message_set Message set * @param string $mailbox Mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdCopy($message_set, $mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); return $this->_genericCommand('COPY', sprintf("%s %s", $message_set, $mailbox_name)); } /** * The UID FETH command * * @param string $msgset Msgset * @param string $fetchparam Fetchparm * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdUidFetch($msgset, $fetchparam) { return $this->_genericCommand('UID FETCH', sprintf("%s %s", $msgset, $fetchparam)); } /** * The UID COPY command * * @param string $message_set Msgset * @param string $mailbox Mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdUidCopy($message_set, $mailbox) { $mailbox_name = $this->_createQuotedString($mailbox); return $this->_genericCommand('UID COPY', sprintf("%s %s", $message_set, $mailbox_name)); } /** * Send the UID STORE command. * * @param string $message_set The sessage_set * @param string $dataitem The way we store the flags * FLAGS: replace the flags whith $value * FLAGS.SILENT: replace the flags whith $value * but don't return untagged responses * +FLAGS: Add the flags whith $value * +FLAGS.SILENT: Add the flags whith $value * but don't return untagged responses * -FLAGS: Remove the flags whith $value * -FLAGS.SILENT: Remove the flags whith $value * but don't return untagged responses * @param string $value Value * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdUidStore($message_set, $dataitem, $value) { /* As said in RFC2060... C: A003 STORE 2:4 +FLAGS (\Deleted) S: * 2 FETCH FLAGS (\Deleted \Seen) S: * 3 FETCH FLAGS (\Deleted) S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) S: A003 OK STORE completed */ if ($dataitem != 'FLAGS' && $dataitem != 'FLAGS.SILENT' && $dataitem != '+FLAGS' && $dataitem != '+FLAGS.SILENT' && $dataitem != '-FLAGS' && $dataitem != '-FLAGS.SILENT') { $this->_protError('dataitem "' . $dataitem . '" is invalid! ' . 'See RFC2060!!!!', __LINE__, __FILE__); } return $this->_genericCommand('UID STORE', sprintf("%s %s (%s)", $message_set, $dataitem, $value)); } /** * Send the SEARCH command. * * @param string $search_cmd Search command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdUidSearch($search_cmd) { $ret = $this->_genericCommand('UID SEARCH', sprintf("%s", $search_cmd)); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the UID SORT command. * * @param string $sort_cmd Sort command * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.1 */ function cmdUidSort($sort_cmd) { $ret = $this->_genericCommand('UID SORT', sprintf("%s", $sort_cmd)); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the X command. * * @param string $atom Atom * @param string $parameters Parameters * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @access public * @since 1.0 */ function cmdX($atom, $parameters) { return $this->_genericCommand('X' . $atom, $parameters); } /******************************************************************** *** ** HERE ENDS the RFC2060 IMAPS FUNCTIONS ** AND BEGIN THE EXTENSIONS FUNCTIONS ** *******************************************************************/ /******************************************************************* ** RFC2087 IMAP4 QUOTA extension BEGINS HERE *******************************************************************/ /** * Send the GETQUOTA command. * * @param string $mailbox_name The mailbox name to query for quota data * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or quota data on success * @access public * @since 1.0 */ function cmdGetQuota($mailbox_name) { //Check if the IMAP server has QUOTA support if (!$this->hasQuotaSupport()) { return new PEAR_Error('This IMAP server doen\'t support QUOTA\'s!'); } $mailbox_name = sprintf("%s", $this->utf7Encode($mailbox_name)); $ret = $this->_genericCommand('GETQUOTA', $mailbox_name); if (isset($ret['PARSED'])) { // remove the array index because the quota response returns // only 1 line of output $ret['PARSED'] = $ret['PARSED'][0]; } return $ret; } /** * Send the GETQUOTAROOT command. * * @param string $mailbox_name The ailbox name to query for quota data * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or quota data on success * @access public * @since 1.0 */ function cmdGetQuotaRoot($mailbox_name) { //Check if the IMAP server has QUOTA support if (!$this->hasQuotaSupport()) { return new PEAR_Error('This IMAP server doesn\'t support QUOTA\'s!'); } $mailbox_name = sprintf("%s", $this->utf7Encode($mailbox_name)); $ret = $this->_genericCommand('GETQUOTAROOT', $mailbox_name); if (isset($ret['PARSED'])) { // remove the array index because the quota response returns // only 1 line of output $ret['PARSED'] = $ret['PARSED'][1]; } return $ret; } /** * Send the SETQUOTA command. * * @param string $mailbox_name The mailbox name to query for quota data * @param string $storageQuota Sets the max number of bytes this mailbox * can handle * @param string $messagesQuota Sets the max number of messages this * mailbox can handle * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or quota data on success * @access public * @since 1.0 */ function cmdSetQuota($mailbox_name, $storageQuota = null, $messagesQuota = null) { // ToDo: implement the quota by number of emails!! //Check if the IMAP server has QUOTA support if (!$this->hasQuotaSupport()) { return new PEAR_Error('This IMAP server doesn\'t support QUOTA\'s!'); } if (($messagesQuota == null) && ($storageQuota == null)) { return new PEAR_Error('$storageQuota and $messagesQuota parameters ' . 'can\'t be both null if you want to use ' . 'quota'); } $mailbox_name = $this->_createQuotedString($mailbox_name); //Make the command request $param = sprintf("%s (", $mailbox_name); if ($storageQuota != null) { if ($storageQuota == -1) { // set -1 to remove a quota $param = sprintf("%s", $param); } elseif ($storageQuota == strtolower('remove')) { // this is a cyrus rmquota specific feature // see http://email.uoa.gr/projects/cyrus/quota-patches/rmquota/ $param = sprintf("%sREMOVE 1", $param); } else { $param = sprintf("%sSTORAGE %s", $param, $storageQuota); } if ($messagesQuota != null) { // if we have both types of quota on the same call we must // append an space between those parameters $param = sprintf("%s ", $param); } } if ($messagesQuota != null) { $param = sprintf("%sMESSAGES %s", $param, $messagesQuota); } $param = sprintf("%s)", $param); return $this->_genericCommand('SETQUOTA', $param); } /** * Send the SETQUOTAROOT command. * * @param string $mailbox_name The mailbox name to query for quota data * @param string $storageQuota Sets the max number of bytes this mailbox * can handle * @param string $messagesQuota Sets the max number of messages this * mailbox can handle * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or quota data on success * @access public * @since 1.0 */ function cmdSetQuotaRoot($mailbox_name, $storageQuota = null, $messagesQuota = null) { //Check if the IMAP server has QUOTA support if (!$this->hasQuotaSupport()) { return new PEAR_Error('This IMAP server doesn\'t support QUOTA\'s!'); } if (($messagesQuota == null) && ($storageQuota == null)) { return new PEAR_Error('$storageQuota and $messagesQuota parameters ' . 'can\'t be both null if you want to use ' . 'quota'); } $mailbox_name = $this->_createQuotedString($mailbox_name); //Make the command request $param = sprintf("%s (", $mailbox_name); if ($storageQuota != null) { $param = sprintf("%sSTORAGE %s", $param, $storageQuota); if ($messagesQuota != null) { // if we have both types of quota on the same call we must // append an space between those parameters $param = sprintf("%s ", $param); } } if ($messagesQuota != null) { $param = sprintf("%sMESSAGES %s", $param, $messagesQuota); } $param = sprintf("%s)", $param); return $this->_genericCommand('SETQUOTAROOT', $param); } /******************************************************************** *** RFC2087 IMAP4 QUOTA extension ENDS HERE ********************************************************************/ /******************************************************************** *** RFC2086 IMAP4 ACL extension BEGINS HERE ********************************************************************/ /** * Send the SETACL command. * * @param string $mailbox_name Mailbox name * @param string $user User * @param string $acl ACL string * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success * @access public * @since 1.0 */ function cmdSetACL($mailbox_name, $user, $acl) { //Check if the IMAP server has ACL support if (!$this->hasAclSupport()) { return new PEAR_Error('This IMAP server does not support ACL\'s!'); } $mailbox_name = $this->_createQuotedString($mailbox_name); $user_name = $this->_createQuotedString($user); if (is_array($acl)) { $acl = implode('', $acl); } return $this->_genericCommand('SETACL', sprintf("%s %s \"%s\"", $mailbox_name, $user_name, $acl)); } /** * Send the DELETEACL command. * * @param string $mailbox_name Mailbox name * @param string $user User * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success * @access public * @since 1.0 */ function cmdDeleteACL($mailbox_name, $user) { //Check if the IMAP server has ACL support if (!$this->hasAclSupport()) { return new PEAR_Error('This IMAP server does not support ACL\'s!'); } $mailbox_name = $this->_createQuotedString($mailbox_name); return $this->_genericCommand('DELETEACL', sprintf("%s \"%s\"", $mailbox_name, $user)); } /** * Send the GETACL command. * * @param string $mailbox_name Mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or ACL list on success * @access public * @since 1.0 */ function cmdGetACL($mailbox_name) { //Check if the IMAP server has ACL support if (!$this->hasAclSupport()) { return new PEAR_Error('This IMAP server does not support ACL\'s!'); } $mailbox_name = $this->_createQuotedString($mailbox_name); $ret = $this->_genericCommand('GETACL', sprintf("%s", $mailbox_name)); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the LISTRIGHTS command. * * @param string $mailbox_name Mailbox name * @param string $user User * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or list of users rights * @access public * @since 1.0 */ function cmdListRights($mailbox_name, $user) { //Check if the IMAP server has ACL support if (!$this->hasAclSupport()) { return new PEAR_Error('This IMAP server does not support ACL\'s!'); } $mailbox_name = $this->_createQuotedString($mailbox_name); $ret = $this->_genericCommand('LISTRIGHTS', sprintf("%s \"%s\"", $mailbox_name, $user)); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /** * Send the MYRIGHTS command. * * @param string $mailbox_name Mailbox name * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or MYRIGHTS response on success * @access public * @since 1.0 */ function cmdMyRights($mailbox_name) { // Check if the IMAP server has ACL support if (!$this->hasAclSupport()) { return new PEAR_Error('This IMAP server does not support ACL\'s!'); } $mailbox_name = $this->_createQuotedString($mailbox_name); $ret = $this->_genericCommand('MYRIGHTS', sprintf("%s", $mailbox_name)); if (isset($ret['PARSED'])) { $ret['PARSED'] = $ret['PARSED'][0]['EXT']; } return $ret; } /******************************************************************** *** RFC2086 IMAP4 ACL extension ENDs HERE ********************************************************************/ /******************************************************************** *** draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension *** BEGINS HERE ********************************************************************/ /** * Send the SETANNOTATION command. * * @param string $mailboxName Mailbox name * @param string $entry Entry * @param string $values Value * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success * @access public * @since 1.0 */ function cmdSetAnnotation($mailboxName, $entry, $values) { // Check if the IMAP server has ANNOTATEMORE support if (!$this->hasAnnotateMoreSupport()) { return new PEAR_Error('This IMAP server does not support the ' . 'ANNOTATEMORE extension!'); } if (!is_array($values)) { return new PEAR_Error('Invalid $values argument passed to ' . 'cmdSetAnnotation'); } $mailboxName = $this->_createQuotedString($mailboxName); $vallist = ''; foreach ($values as $name => $value) { $vallist .= '"' . $name . '" "' . $value . '"'; } $vallist = rtrim($vallist); return $this->_genericCommand('SETANNOTATION', sprintf('%s "%s" (%s)', $mailboxName, $entry, $vallist)); } /** * Send the DELETEANNOTATION command. * * @param string $mailboxName Mailbox name * @param string $entry Entry * @param string $values Value * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success * @access public * @since 1.0 */ function cmdDeleteAnnotation($mailboxName, $entry, $values) { // Check if the IMAP server has ANNOTATEMORE support if (!$this->hasAnnotateMoreSupport()) { return new PEAR_Error('This IMAP server does not support the ' . 'ANNOTATEMORE extension!'); } if (!is_array($values)) { return new PEAR_Error('Invalid $values argument passed to ' . 'cmdDeleteAnnotation'); } $mailboxName = $this->_createQuotedString($mailboxName); $vallist = ''; foreach ($values as $name) { $vallist .= '"' . $name . '" NIL'; } $vallist = rtrim($vallist); return $this->_genericCommand('SETANNOTATION', sprintf('%s "%s" (%s)', $mailboxName, $entry, $vallist)); } /** * Send the GETANNOTATION command. * * @param string $mailboxName Mailbox name * @param string $entries Entries * @param string $values Value * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or GETANNOTATION result on success * @access public * @since 1.0 */ function cmdGetAnnotation($mailboxName, $entries, $values) { // Check if the IMAP server has ANNOTATEMORE support if (!$this->hasAnnotateMoreSupport()) { return new PEAR_Error('This IMAP server does not support the ' . 'ANNOTATEMORE extension!'); } $entlist = ''; if (!is_array($entries)) { $entries = array($entries); } foreach ($entries as $name) { $entlist .= '"' . $name . '"'; } $entlist = rtrim($entlist); if (count($entries) > 1) { $entlist = '(' . $entlist . ')'; } $vallist = ''; if (!is_array($values)) { $values = array($values); } foreach ($values as $name) { $vallist .= '"' . $name . '"'; } $vallist = rtrim($vallist); if (count($values) > 1) { $vallist = '(' . $vallist . ')'; } $mailboxName = $this->_createQuotedString($mailboxName); return $this->_genericCommand('GETANNOTATION', sprintf('%s %s %s', $mailboxName, $entlist, $vallist)); } /*********************************************************************** *** draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension *** ENDs HERE ************************************************************************/ /******************************************************************** *** *** HERE ENDS THE EXTENSIONS FUNCTIONS *** AND BEGIN THE AUXILIARY FUNCTIONS *** ********************************************************************/ /** * tell if the server has capability $capability * * @return true or false * @access public * @since 1.0 */ function getServerAuthMethods() { if ($this->_serverAuthMethods == null) { $this->cmdCapability(); return $this->_serverAuthMethods; } return false; } /** * tell if the server has capability $capability * * @param string $capability Capability * * @return true or false * @access public * @since 1.0 */ function hasCapability($capability) { if ($this->_serverSupportedCapabilities == null) { $this->cmdCapability(); } if ($this->_serverSupportedCapabilities != null) { if (in_array($capability, $this->_serverSupportedCapabilities)) { return true; } } return false; } /** * tell if the server has Quota support * * @return true or false * @access public * @since 1.0 */ function hasQuotaSupport() { return $this->hasCapability('QUOTA'); } /** * tell if the server has Quota support * * @return true or false * @access public * @since 1.0 */ function hasAclSupport() { return $this->hasCapability('ACL'); } /** * tell if the server has support for the ANNOTATEMORE extension * * @return true or false * @access public * @since 1.0 */ function hasAnnotateMoreSupport() { return $this->hasCapability('ANNOTATEMORE'); } /** * Create a quoted string * * @param string $str String * * @return string Quoted $str * @access public * @since 1.0 */ function _createQuotedString($str) { $search = array('\\', '"'); $replace = array('\\\\', '\\"'); $mailbox_name = str_replace($search, $replace, $str); $mailbox_name = sprintf("\"%s\"", $this->utf7Encode($mailbox_name)); return $mailbox_name; } /** * Parses the responses like RFC822.SIZE and INTERNALDATE * * @param string &$str The IMAP's server response * @param int $line Line number * @param string $file File * * @return string next token * @access private * @since 1.0 */ function _parseOneStringResponse(&$str, $line, $file) { $this->_parseSpace($str, $line, $file); $size = $this->_getNextToken($str, $uid); return $uid; } /** * Parses the FLAG response * * @param string &$str The IMAP's server response * * @return Array containing the parsed response * @access private * @since 1.0 */ function _parseFLAGSresponse(&$str) { $this->_parseSpace($str, __LINE__, __FILE__); $params_arr[] = $this->_arrayfyContent($str); $flags_arr = array(); for ($i = 0; $i < count($params_arr[0]); $i++) { $flags_arr[] = $params_arr[0][$i]; } return $flags_arr; } /** * Parses the BODY response * * @param string &$str The IMAP's server response * @param string $command Command * * @return array The parsed response * @access private * @since 1.0 */ function _parseBodyResponse(&$str, $command) { $this->_parseSpace($str, __LINE__, __FILE__); while ($str[0] != ')' && $str != '') { $params_arr[] = $this->_arrayfyContent($str); } return $params_arr; } /** * Makes the content an Array * * @param string &$str The IMAP's server response * * @return array The parsed response * @access private * @since 1.0 */ function _arrayfyContent(&$str) { $params_arr = array(); $this->_getNextToken($str, $params); if ($params != '(') { return $params; } $this->_getNextToken($str, $params, false, false); while ($str != '' && $params != ')') { if ($params != '') { if ($params[0] == '(') { $params = $this->_arrayfyContent($params); } if ($params != ' ') { // I don't remove the colons (") to handle the case of // retriving " " // If I remove the colons the parser will interpret this // field as an imap separator (space) instead of a valid // field so I remove the colons here if ($params == '""') { $params = ''; } else { if ($params[0] == '"') { $params = $this->_getSubstr($params, 1, $this->_getLineLength($params)-2); } } $params_arr[] = $params; } } else { // if params if empty (for example i'm parsing 2 quotes ("") // I'll append an array entry to mantain compatibility $params_arr[] = $params; } $this->_getNextToken($str, $params, false, false); } return $params_arr; } /** * Parses the BODY[],BODY[TEXT],.... responses * * @param string &$str The IMAP's server response * @param string $command Command * * @return array The parsed response * @access private * @since 1.0 */ function _parseContentresponse(&$str, $command) { $content = ''; $this->_parseSpace($str, __LINE__, __FILE__); $size = $this->_getNextToken($str, $content); return array('CONTENT' => $content, 'CONTENT_SIZE' => $size); } /** * Parses the ENVELOPE response * * @param string &$str The IMAP's server response * * @return array The parsed response * @access private * @since 1.0 */ function _parseENVELOPEresponse(&$str) { $content = ''; $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $parenthesis); if ($parenthesis != '(') { $this->_protError('must be a "(" but is a "' . $parenthesis .'" ' . '!!!!', __LINE__, __FILE__); } // Get the email's Date $this->_getNextToken($str, $date); $this->_parseSpace($str, __LINE__, __FILE__); // Get the email's Subject: $this->_getNextToken($str, $subject); //$subject = $this->decode($subject); $this->_parseSpace($str, __LINE__, __FILE__); //FROM LIST; $from_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); //"SENDER LIST\n"; $sender_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); //"REPLY-TO LIST\n"; $reply_to_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); //"TO LIST\n"; $to_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); //"CC LIST\n"; $cc_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); //"BCC LIST|$str|\n"; $bcc_arr = $this->_getAddressList($str); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $in_reply_to); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $message_id); $this->_getNextToken($str, $parenthesis); if ($parenthesis != ')') { $this->_protError('must be a ")" but is a "' . $parenthesis .'" ' . '!!!!', __LINE__, __FILE__); } return array('DATE' => $date, 'SUBJECT' => $subject, 'FROM' => $from_arr, 'SENDER' => $sender_arr, 'REPLY_TO' => $reply_to_arr, 'TO' => $to_arr, 'CC' => $cc_arr, 'BCC' => $bcc_arr, 'IN_REPLY_TO' => $in_reply_to, 'MESSAGE_ID' => $message_id); } /** * Parses the ARRDLIST as defined in RFC * * @param string &$str The IMAP's server response * * @return array The parsed response * @access private * @since 1.0 */ function _getAddressList(&$str) { $params_arr = $this->_arrayfyContent($str); if (!isset($params_arr)) { return $params_arr; } if (is_array($params_arr)) { foreach ($params_arr as $index => $address_arr) { $personal_name = $address_arr[0]; $at_domain_list = $address_arr[1]; $mailbox_name = $address_arr[2]; $host_name = $address_arr[3]; if ($mailbox_name != '' && $host_name != '') { $email = $mailbox_name . "@" . $host_name; } else { $email = false; } if ($email == false) { $rfc822_email = false; } else { if (!isset($personal_name)) { $rfc822_email = '<' . $email . '>'; } else { $rfc822_email = '"' . $personal_name . '" <' . $email . '>'; } } $email_arr[] = array('PERSONAL_NAME' => $personal_name, 'AT_DOMAIN_LIST' => $at_domain_list, 'MAILBOX_NAME' => $this->utf7Decode($mailbox_name), 'HOST_NAME' => $host_name, 'EMAIL' => $email , 'RFC822_EMAIL' => $rfc822_email ); } return $email_arr; } return array(); } /** * Utility funcion to find the closing parenthesis ")" Position it takes * care of quoted ones * * @param string $str_line String * @param string $startDelim Start delimiter * @param string $stopDelim Stop delimiter * * @return int the pos of the closing parenthesis ")" * @access private * @since 1.0 */ function _getClosingBracesPos($str_line, $startDelim = '(', $stopDelim = ')') { $len = $this->_getLineLength($str_line); $pos = 0; // ignore all extra characters // If inside of a string, skip string -- Boundary IDs and other // things can have ) in them. if ($str_line[$pos] != $startDelim) { $this->_protError('_getClosingParenthesisPos: must start with a ' . '"' . $startDelim . '" but is a ' . '"' . $str_line[$pos] . '"!!!!' . 'STR_LINE: ' . $str_line . ' |size: ' . $len . ' |POS: ' . $pos, __LINE__, __FILE__); return( $len ); } for ($pos = 1; $pos < $len; $pos++) { if ($str_line[$pos] == $stopDelim) { break; } if ($str_line[$pos] == '"') { $this->_advanceOverStr($str_line, $pos, $len, $startDelim, $stopDelim); } if ($str_line[$pos] == $startDelim) { $str_line_aux = $this->_getSubstr($str_line, $pos); $pos_aux = $this->_getClosingBracesPos($str_line_aux); $pos += $pos_aux; if ($pos == $len-1) { break; } } } if ($str_line[$pos] != $stopDelim) { $this->_protError('_getClosingBracesPos: must be a ' . '"' . $stopDelim . '" but is a ' . '"' . $str_line[$pos] . '"' . ' |POS: ' . $pos . ' |STR_LINE: ' . $str_line . '!!!!', __LINE__, __FILE__); } if ($pos >= $len) { return false; } return $pos; } /** * Advances the position $pos in $str over an correct escaped string * * Examples: $str='"\\\"First Last\\\""', $pos=0 * --> returns true and $pos=strlen($str)-1 * * @param string $str String * @param int &$pos Current position in $str pointing to a * double quote ("), on return pointing * on the closing double quote * @param int $len Length of $str in bytes(!) * @param string $startDelim Start delimiter * @param string $stopDelim Stop delimiter * * @return boolean true if we advanced over a correct string, * false otherwise * @access private * @author Nigel Vickers * @author Ralf Becker * @since 1.1 */ function _advanceOverStr($str, &$pos, $len, $startDelim ='(', $stopDelim = ')') { if ($str[$pos] !== '"') { // start condition failed return false; } $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 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)) { // stopDelimited need to be parsed outside! $pos--; return false; } // all escaped chars are overread (eg. \\, \", \x) if ($str[$pos] === '\\') { $pos++; } $pos++; } return $pos < $len && $str[$pos] === '"'; } /** * Utility funcion to get from here to the end of the line * * @param string &$str String * @param boolean $including true for Including EOL * false to not include EOL * * @return string The string to the first EOL * @access private * @since 1.0 */ function _getToEOL(&$str, $including = true) { $len = $this->_getLineLength($str); if ($including) { for ($i=0; $i<$len; $i++) { if ($str[$i] == "\n") { break; } } $content = $this->_getSubstr($str, 0, $i + 1); $str = $this->_getSubstr($str, $i + 1); } else { for ($i = 0 ; $i < $len ; $i++ ) { if ($str[$i] == "\n" || $str[$i] == "\r") { break; } } $content = $this->_getSubstr($str, 0, $i); $str = $this->_getSubstr($str, $i); } return $content; } /** * Fetches the next IMAP token or parenthesis * * @param string &$str The IMAP's server response * @param string &$content The next token * @param boolean $parenthesisIsToken true: the parenthesis IS a token, * false: I consider all the response * in parenthesis as a token * @param boolean $colonIsToken true: the colin IS a token * false: * * @return int The content size * @access private * @since 1.0 */ function _getNextToken(&$str, &$content, $parenthesisIsToken = true, $colonIsToken = true) { $len = $this->_getLineLength($str); $pos = 0; $content_size = false; $content = false; if ($str == '' || $len < 2) { $content = $str; return $len; } switch ($str[0]) { case '{': if (($posClosingBraces = $this->_getClosingBracesPos($str, '{', '}')) == false) { $this->_protError('_getClosingBracesPos() error!!!', __LINE__, __FILE__); } if (!is_numeric(($strBytes = $this->_getSubstr($str, 1, $posClosingBraces - 1)))) { $this->_protError('must be a number but is a ' . '"' . $strBytes . '" !!!', __LINE__, __FILE__); } if ($str[$posClosingBraces] != '}') { $this->_protError('must be a "}" but is a ' . '"' . $str[$posClosingBraces] . '"!!!', __LINE__, __FILE__); } if ($str[$posClosingBraces + 1] != "\r") { $this->_protError('must be a "\r" but is a ' . '"' . $str[$posClosingBraces + 1] . '"!!!', __LINE__, __FILE__); } if ($str[$posClosingBraces + 2] != "\n") { $this->_protError('must be a "\n" but is a ' . '"' . $str[$posClosingBraces + 2] . '"!!!', __LINE__, __FILE__); } $content = $this->_getSubstr($str, $posClosingBraces + 3, $strBytes); if ($this->_getLineLength($content) != $strBytes) { $this->_protError('content size is ' . '"' . $this->_getLineLength($content) . '"' . ' but the string reports a size of ' . $strBytes .'!!!!', __LINE__, __FILE__); } $content_size = $strBytes; //Advance the string $str = $this->_getSubstr($str, $posClosingBraces + $strBytes + 3); break; case '"': if ($colonIsToken) { for ($pos=1; $pos<$len; $pos++) { if ($str[$pos] == '"') { break; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == '"') { $pos++; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\\") { $pos++; } } if ($str[$pos] != '"') { $this->_protError('must be a "\"" but is a ' . '"' . $str[$pos] . '"!!!!', __LINE__, __FILE__); } $content_size = $pos; $content = $this->_getSubstr($str, 1, $pos - 1); //Advance the string $str = $this->_getSubstr($str, $pos + 1); } else { for ($pos=1; $pos<$len; $pos++) { if ($str[$pos] == '"') { break; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == '"' ) { $pos++; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\\" ) { $pos++; } } if ($str[$pos] != '"') { $this->_protError('must be a "\"" but is a ' . '"' . $str[$pos] . '"!!!!', __LINE__, __FILE__); } $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos + 1); //Advance the string $str = $this->_getSubstr($str, $pos + 1); } // we need to strip slashes for a quoted string $content = stripslashes($content); break; case "\r": $pos = 1; if ($str[1] == "\n") { $pos++; } $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); $str = $this->_getSubstr($str, $pos); break; case "\n": $pos = 1; $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); $str = $this->_getSubstr($str, $pos); break; case '(': if ($parenthesisIsToken == false) { $pos = $this->_getClosingBracesPos($str); $content_size = $pos + 1; $content = $this->_getSubstr($str, 0, $pos + 1); $str = $this->_getSubstr($str, $pos + 1); } else { $pos = 1; $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); $str = $this->_getSubstr($str, $pos); } break; case ')': $pos = 1; $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); $str = $this->_getSubstr($str, $pos); break; case ' ': $pos = 1; $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); $str = $this->_getSubstr($str, $pos); break; default: for ($pos = 0; $pos < $len; $pos++) { if ($this->_getSubstr($str, 0, 5) == 'BODY[' || $this->_getSubstr($str, 0, 5) == 'BODY.') { if ($str[$pos] == ']') { $pos++; break; } } elseif ($str[$pos] == ' ' || $str[$pos] == "\r" || $str[$pos] == ')' || $str[$pos] == '(' || $str[$pos] == "\n" ) { break; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == ' ') { $pos++; } if ($str[$pos] == "\\" && $str[$pos + 1 ] == "\\") { $pos++; } } //Advance the string if ($pos == 0) { $content_size = 1; $content = $this->_getSubstr($str, 0, 1); $str = $this->_getSubstr($str, 1); } else { $content_size = $pos; $content = $this->_getSubstr($str, 0, $pos); if ($pos < $len) { $str = $this->_getSubstr($str, $pos); } else { //if this is the end of the string... exit the switch break; } } break; } return $content_size; } /** * Utility funcion to display to console the protocol errors * printErrors() additionally has to be set to true * * @param string $str The error message * @param int $line The line producing the error * @param string $file File where the error was produced * @param boolean $printError true: print the error * false: do not print the error * * @return nothing * @access private * @since 1.0 */ function _protError($str , $line , $file, $printError = true) { // ToDo: all real errors should be returned as PEAR error, others // hidden by default // NO extra output from this class! if ($this->_printErrors && $printError) { echo "$line,$file,PROTOCOL ERROR!:$str\n"; } } /** * get EXT array from string * * @param string &$str String * @param string $startDelim Start delimiter * @param string $stopDelim Stop delimiter * * @return array EXT array * @access private * @since 1.0 */ function _getEXTarray(&$str, $startDelim = '(', $stopDelim = ')') { /* I let choose the $startDelim and $stopDelim to allow parsing the OK response so I also can parse a response like this * OK [UIDNEXT 150] Predicted next UID */ $this->_getNextToken($str, $parenthesis); if ($parenthesis != $startDelim) { $this->_protError('must be a "' . $startDelim . '" but is a ' . '"' . $parenthesis . '" !!!!', __LINE__, __FILE__); } $parenthesis = ''; $struct_arr = array(); while ($parenthesis != $stopDelim && $str != '') { // The command $this->_getNextToken($str, $token); $token = strtoupper($token); if (($ret = $this->_retrParsedResponse($str, $token)) != false) { //$struct_arr[$token] = $ret; $struct_arr = array_merge($struct_arr, $ret); } $parenthesis = $token; } //While if ($parenthesis != $stopDelim ) { $this->_protError('1_must be a "' . $stopDelim . '" but is a ' . '"' . $parenthesis . '"!!!!', __LINE__, __FILE__); } return $struct_arr; } /** * retrieve parsed response * * @param string &$str String * @param string $token Token * @param string $previousToken Previous token * * @return array Parsed response * @access private * @since 1.0 */ function _retrParsedResponse(&$str, $token, $previousToken = null) { //echo "\n\nTOKEN:$token\r\n"; $token = strtoupper($token); switch ($token) { case 'RFC822.SIZE': return array($token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)); break; // case 'RFC822.TEXT': // case 'RFC822.HEADER': case 'RFC822': return array($token => $this->_parseContentresponse($str, $token)); break; case 'FLAGS': case 'PERMANENTFLAGS': return array($token => $this->_parseFLAGSresponse($str)); break; case 'ENVELOPE': return array($token => $this->_parseENVELOPEresponse($str)); break; case 'EXPUNGE': return false; break; case 'NOMODSEQ': // ToDo: implement RFC 4551 return array($token=>''); break; case 'UID': case 'UIDNEXT': case 'UIDVALIDITY': case 'UNSEEN': case 'MESSAGES': case 'UIDNEXT': case 'UIDVALIDITY': case 'UNSEEN': case 'INTERNALDATE': return array($token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)); break; case 'BODY': case 'BODYSTRUCTURE': return array($token => $this->_parseBodyResponse($str, $token)); break; case 'RECENT': if ($previousToken != null) { $aux['RECENT'] = $previousToken; return $aux; } else { return array($token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)); } break; case 'EXISTS': return array($token => $previousToken); break; case 'READ-WRITE': case 'READ-ONLY': return array($token => $token); break; case 'QUOTA': /* A tipical GETQUOTA DIALOG IS AS FOLLOWS C: A0004 GETQUOTA user.damian S: * QUOTA user.damian (STORAGE 1781460 4000000) S: A0004 OK Completed another example of QUOTA response from GETQUOTAROOT: C: A0008 GETQUOTAROOT INBOX S: * QUOTAROOT INBOX "" S: * QUOTA "" (STORAGE 0 1024000 MESSAGE 0 40000) S: A0008 OK GETQUOTAROOT finished. RFC 2087 section 5.1 says the list could be empty: C: A0004 GETQUOTA user.damian S: * QUOTA user.damian () S: A0004 OK Completed quota_list ::= "(" #quota_resource ")" quota_resource ::= atom SP number SP number quota_response ::= "QUOTA" SP astring SP quota_list */ $mailbox = $this->_parseOneStringResponse($str, __LINE__, __FILE__); $ret_aux = array('MAILBOX' => $this->utf7Decode($mailbox)); // courier fix if ($str[0] . $str[1] == "\r\n") { return array($token => $ret_aux); } // end courier fix $this->_parseSpace($str, __LINE__, __FILE__); $this->_parseString($str, '(', __LINE__, __FILE__); // fetching quota resources // (BNF ::= #quota_resource but space separated instead of comma) $this->_getNextToken($str, $quota_resp); while ($quota_resp != ')') { if (($ext = $this->_retrParsedResponse($str, $quota_resp)) == false) { $this->_protError('bogus response!!!!', __LINE__, __FILE__); } $ret_aux = array_merge($ret_aux, $ext); $this->_getNextToken($str, $quota_resp); if ($quota_resp == ' ') { $this->_getNextToken($str, $quota_resp); } } // if empty list, apparently no STORAGE or MESSAGE quota set return array($token => $ret_aux); break; case 'QUOTAROOT': /* A tipical GETQUOTA DIALOG IS AS FOLLOWS C: A0004 GETQUOTA user.damian S: * QUOTA user.damian (STORAGE 1781460 4000000) S: A0004 OK Completed */ $mailbox = $this->utf7Decode($this->_parseOneStringResponse($str, __LINE__, __FILE__)); $str_line = rtrim(substr($this->_getToEOL($str, false), 0)); if (empty($str_line)) { $ret = @array('MAILBOX' => $this->utf7Decode($mailbox)); } else { $quotaroot = $this->_parseOneStringResponse($str_line, __LINE__, __FILE__); $ret = @array('MAILBOX' => $this->utf7Decode($mailbox), $token => $quotaroot); } return array($token => $ret); break; case 'STORAGE': $used = $this->_parseOneStringResponse($str, __LINE__, __FILE__); $qmax = $this->_parseOneStringResponse($str, __LINE__, __FILE__); return array($token => array('USED' => $used, 'QMAX' => $qmax)); break; case 'MESSAGE': $mused = $this->_parseOneStringResponse($str, __LINE__, __FILE__); $mmax = $this->_parseOneStringResponse($str, __LINE__, __FILE__); return array($token=>array("MUSED"=> $mused, "MMAX" => $mmax)); break; case 'FETCH': $this->_parseSpace($str, __LINE__, __FILE__); // Get the parsed pathenthesis $struct_arr = $this->_getEXTarray($str); return $struct_arr; break; case 'NAMESPACE': $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $personal, false); $struct_arr['NAMESPACES']['personal'] = $this->_arrayfyContent($personal); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $others, false); $struct_arr['NAMESPACES']['others'] = $this->_arrayfyContent($others); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $shared, false); $struct_arr['NAMESPACES']['shared'] = $this->_arrayfyContent($shared); return array($token => $struct_arr); break; case 'CAPABILITY': $this->_parseSpace($str, __LINE__, __FILE__); $str_line = rtrim(substr($this->_getToEOL($str, false), 0)); $struct_arr['CAPABILITIES'] = explode(' ', $str_line); return array($token => $struct_arr); break; case 'STATUS': $mailbox = $this->_parseOneStringResponse($str, __LINE__, __FILE__); $this->_parseSpace($str, __LINE__, __FILE__); $ext = $this->_getEXTarray($str); $struct_arr['MAILBOX'] = $this->utf7Decode($mailbox); $struct_arr['ATTRIBUTES'] = $ext; return array($token => $struct_arr); break; case 'LIST': $this->_parseSpace($str, __LINE__, __FILE__); $params_arr = $this->_arrayfyContent($str); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $hierarchydelim); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox_name); $result_array = array('NAME_ATTRIBUTES' => $params_arr, 'HIERACHY_DELIMITER' => $hierarchydelim, 'MAILBOX_NAME' => $this->utf7Decode($mailbox_name)); return array($token => $result_array); break; case 'LSUB': $this->_parseSpace($str, __LINE__, __FILE__); $params_arr = $this->_arrayfyContent($str); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $hierarchydelim); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox_name); $result_array = array('NAME_ATTRIBUTES' => $params_arr, 'HIERACHY_DELIMITER' => $hierarchydelim, 'MAILBOX_NAME' => $this->utf7Decode($mailbox_name)); return array($token => $result_array); break; case 'SEARCH': case 'SORT': $str_line = rtrim(substr($this->_getToEOL($str, false), 1)); $struct_arr[$token . '_LIST'] = explode(' ', $str_line); if (count($struct_arr[$token . '_LIST']) == 1 && $struct_arr[$token . '_LIST'][0] == '') { $struct_arr[$token . '_LIST'] = null; } return array($token => $struct_arr); break; case 'OK': /* TODO: parse the [ .... ] part of the response, use the method _getEXTarray(&$str,'[',$stopDelim=']') */ $str_line = rtrim(substr($this->_getToEOL($str, false), 1)); if ($str_line[0] == '[') { $braceLen = $this->_getClosingBracesPos($str_line, '[', ']'); $str_aux = '('. substr($str_line, 1, $braceLen -1). ')'; $ext_arr = $this->_getEXTarray($str_aux); //$ext_arr=array($token=>$this->_getEXTarray($str_aux)); } else { $ext_arr = $str_line; //$ext_arr=array($token=>$str_line); } $result_array = $ext_arr; return $result_array; break; case 'NO': /* TODO: parse the [ .... ] part of the response, use the method _getEXTarray(&$str,'[',$stopDelim=']') */ $str_line = rtrim(substr($this->_getToEOL($str, false), 1)); $result_array[] = @array('COMMAND' => $token, 'EXT' => $str_line); return $result_array; break; case 'BAD': /* TODO: parse the [ .... ] part of the response, use the method _getEXTarray(&$str,'[',$stopDelim=']') */ $str_line = rtrim(substr($this->_getToEOL($str, false), 1)); $result_array[] = array('COMMAND' => $token, 'EXT' => $str_line); return $result_array; break; case 'BYE': /* TODO: parse the [ .... ] part of the response, use the method _getEXTarray(&$str,'[',$stopDelim=']') */ $str_line = rtrim(substr($this->_getToEOL($str, false), 1)); $result_array[] = array('COMMAND' => $token, 'EXT' => $str_line); return $result_array; break; case 'LISTRIGHTS': $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $user); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $granted); $ungranted = explode(' ', rtrim(substr($this->_getToEOL($str, false), 1))); $result_array = @array('MAILBOX' => $this->utf7Decode($mailbox), 'USER' => $user, 'GRANTED' => $granted, 'UNGRANTED' => $ungranted); return $result_array; break; case 'MYRIGHTS': $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox); // Patch to handle the alternate MYRIGHTS response from // Courier-IMAP if ($str==')') { $granted = $mailbox; $mailbox = $this->currentMailbox; } else { $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $granted); } // End Patch $result_array = array('MAILBOX' => $this->utf7Decode($mailbox), 'GRANTED' => $granted); return $result_array; break; case 'ACL': /* RFC 4314: acl-data = "ACL" SP mailbox *(SP identifier SP rights) identifier = astring rights = astring ;; only lowercase ASCII letters and digits are allowed. */ //$str = " INBOX\r\nA0006 OK Completed\r\n"; $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox); $arr = array(); while (substr($str, 0, 2) != "\r\n") { $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $acl_user); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $acl_rights); $arr[] = array('USER' => $acl_user, 'RIGHTS' => $acl_rights); } $result_array = array('MAILBOX' => $this->utf7Decode($mailbox), 'USERS' => $arr); return $result_array; break; case 'ANNOTATION': $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $mailbox); $this->_parseSpace($str, __LINE__, __FILE__); $this->_getNextToken($str, $entry); $this->_parseSpace($str, __LINE__, __FILE__); $attrs = $this->_arrayfyContent($str); $result_array = array('MAILBOX' => $this->utf7Decode($mailbox), 'ENTRY' => $entry, 'ATTRIBUTES' => $attrs); return $result_array; break; case '': $this->_protError('PROTOCOL ERROR!:str empty!!', __LINE__, __FILE__); break; case '(': $this->_protError('OPENING PARENTHESIS ERROR!!!', __LINE__, __FILE__); break; case ')': //"CLOSING PARENTHESIS BREAK!!!!!!!" break; case "\r\n": $this->_protError('BREAK!!!', __LINE__, __FILE__); break; case ' ': // this can happen and we just ignore it // This happens when - for example - fetch returns more than 1 // parammeter // for example you ask to get RFC822.SIZE and UID // $this->_protError('SPACE BREAK!!!', __LINE__, __FILE__); break; default: $body_token = strtoupper(substr($token, 0, 5)); $rfc822_token = strtoupper(substr($token, 0, 7)); if ($body_token == 'BODY[' || $body_token == 'BODY.' || $rfc822_token == 'RFC822.') { //echo "TOKEN:$token\n"; //$this->_getNextToken( $str , $mailbox ); return array($token => $this->_parseContentresponse($str, $token)); } else { $this->_protError('UNIMPLEMMENTED! I don\'t know the ' . 'parameter "' . $token . '"!!!', __LINE__, __FILE__); } break; } return false; } /** * Verifies that the next character IS a space * * @param string &$str String * @param int $line Line number * @param string $file File name * @param boolean $printError Print errors * * @return string First character of $str * @access private */ function _parseSpace(&$str, $line, $file, $printError = true) { /* This code repeats a lot in this class so i make it a function to make all the code shorter */ $this->_getNextToken($str, $space); if ($space != ' ') { $this->_protError('must be a " " but is a "' . $space . '"!!!!', $line, $file, $printError); } return $space; } /** * parse string for next character after token * * @param string &$str String * @param string $char Next character * @param int $line Line number * @param string $file File name * * @return string Character after next token * @access private */ function _parseString(&$str, $char, $line, $file) { /* This code repeats a lot in this class so i make it a function to make all the code shorter */ $this->_getNextToken($str, $char_aux); if (strtoupper($char_aux) != strtoupper($char)) { $this->_protError('must be a "' . $char . '" but is a ' . '"' . $char_aux . '"!!!!', $line, $file); } return $char_aux; } /** * parse IMAP response * * @param string &$str Response string * @param int $cmdid Command ID * * @return array Response array * @access private */ function _genericImapResponseParser(&$str, $cmdid = null) { $result_array = array(); if ($this->_unParsedReturn) { $unparsed_str = $str; } $this->_getNextToken($str, $token); while ($token != $cmdid && $str != '') { if ($token == '+' ) { //if the token is + ignore the line // TODO: verify that this is correct!!! $this->_getToEOL($str); $this->_getNextToken($str, $token); } $this->_parseString($str, ' ', __LINE__, __FILE__); $this->_getNextToken($str, $token); if ($token == '+') { $this->_getToEOL($str); $this->_getNextToken($str, $token); } else { if (is_numeric($token)) { // The token is a NUMBER so I store it $msg_nro = $token; $this->_parseSpace($str, __LINE__, __FILE__); // I get the command $this->_getNextToken($str, $command); if (($ext_arr = $this->_retrParsedResponse($str, $command, $msg_nro)) == false) { // if this bogus response is a FLAGS () or EXPUNGE // response the ignore it if ($command != 'FLAGS' && $command != 'EXPUNGE') { $this->_protError('bogus response!!!!', __LINE__, __FILE__, false); } } $result_array[] = array('COMMAND' => $command, 'NRO' => $msg_nro, 'EXT' => $ext_arr); } else { // OK the token is not a NUMBER so it MUST be a COMMAND $command = $token; /* Call the parser return the array take care of bogus responses! */ if (($ext_arr = $this->_retrParsedResponse($str, $command)) == false) { $this->_protError('bogus response!!!! (COMMAND:' . $command. ')', __LINE__, __FILE__); } $result_array[] = array('COMMAND' => $command, 'EXT' => $ext_arr); } } $this->_getNextToken($str, $token); $token = strtoupper($token); if ($token != "\r\n" && $token != '') { $this->_protError('PARSE ERROR!!! must be a "\r\n" here but ' . 'is a "' . $token . '"!!!! (getting the ' . 'next line)|STR:|' . $str. '|', __LINE__, __FILE__); } $this->_getNextToken($str, $token); if ($token == '+') { //if the token is + ignore the line // TODO: verify that this is correct!!! $this->_getToEOL($str); $this->_getNextToken($str, $token); } } //While // OK we finish the UNTAGGED Response now we must parse // the FINAL TAGGED RESPONSE // TODO: make this a litle more elegant! $this->_parseSpace($str, __LINE__, __FILE__, false); $this->_getNextToken($str, $cmd_status); $str_line = rtrim(substr($this->_getToEOL($str), 1)); $response['RESPONSE'] = array('CODE' => $cmd_status, 'STR_CODE' => $str_line, 'CMDID' => $cmdid); $ret = $response; if (!empty($result_array)) { $ret = array_merge($ret, array('PARSED' => $result_array)); } if ($this->_unParsedReturn) { $unparsed['UNPARSED'] = $unparsed_str; $ret = array_merge($ret, $unparsed); } if (isset($status_arr)) { $status['STATUS'] = $status_arr; $ret = array_merge($ret, $status); } return $ret; } /** * Send generic command * * @param string $command Command * @param string $params Parameters * * @return array Parsed response * @access private */ function _genericCommand($command, $params = '') { if (!$this->_connected) { return new PEAR_Error('not connected! (CMD:$command)'); } $cmdid = $this->_getCmdId(); $this->_putCMD($cmdid, $command, $params); $args = $this->_getRawResponse($cmdid); return $this->_genericImapResponseParser($args, $cmdid); } /** * Encode string to UTF7 * * Use utf7Encode() instead. This method is only for BC. * * @param string $str String * * @return string UTF7 encoded string * @access public * @deprecated Use utf7Encode() instead */ function utf_7_encode($str) { return utf7Encode($str); } /** * Encode string to UTF7 * * @param string $str String * * @return string UTF7 encoded string * @access public */ function utf7Encode($str) { if ($this->_useUTF_7 == false) { return $str; } if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($str, 'UTF7-IMAP', $this->_encoding); } $encoded_utf7 = ''; $base64_part = ''; if (is_array($str)) { return new PEAR_Error('error'); } for ($i = 0; $i < $this->_getLineLength($str); $i++) { //those chars should be base64 encoded if (((ord($str[$i]) >= 39) && (ord($str[$i]) <= 126)) || ((ord($str[$i]) >= 32) && (ord($str[$i]) <= 37))) { if ($base64_part) { $encoded_utf7 = sprintf("%s&%s-", $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); $base64_part = ''; } $encoded_utf7 = sprintf("%s%s", $encoded_utf7, $str[$i]); } else { //handle & if (ord($str[$i]) == 38 ) { if ($base64_part) { $encoded_utf7 = sprintf("%s&%s-", $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); $base64_part = ''; } $encoded_utf7 = sprintf("%s&-", $encoded_utf7); } else { $base64_part = sprintf("%s%s", $base64_part, $str[$i]); //$base64_part = sprintf("%s%s%s", // $base64_part, // chr(0), // $str[$i]); } } } if ($base64_part) { $encoded_utf7 = sprintf("%s&%s-", $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); $base64_part = ''; } return $encoded_utf7; } /** * Decode string from UTF7 * * Use utf7Decode() instead. This method is only for BC. * * @param string $str UTF7 encoded string * * @return string Decoded string * @access public * @deprecated Use utf7Decode() instead */ function utf_7_decode($str) { utf7Decode($str); } /** * Decode string from UTF7 * * @param string $str UTF7 encoded string * * @return string Decoded string * @access public */ function utf7Decode($str) { if ($this->_useUTF_7 == false) { return $str; } //return imap_utf7_decode($str); if (function_exists('mb_convert_encoding')) { return mb_convert_encoding($str, $this->_encoding, 'UTF7-IMAP'); } $base64_part = ''; $decoded_utf7 = ''; for ($i = 0; $i < $this->_getLineLength($str); $i++) { if ($this->_getLineLength($base64_part) > 0) { if ($str[$i] == '-') { if ($base64_part == '&') { $decoded_utf7 = sprintf("%s&", $decoded_utf7); } else { $next_part_decoded = base64_decode(substr($base64_part, 1)); $decoded_utf7 = sprintf("%s%s", $decoded_utf7, $next_part_decoded); } $base64_part = ''; } else { $base64_part = sprintf("%s%s", $base64_part, $str[$i]); } } else { if ($str[$i] == '&') { $base64_part = '&'; } else { $decoded_utf7 = sprintf("%s%s", $decoded_utf7, $str[$i]); } } } return $decoded_utf7; } /** * Make CREATE/RENAME compatible option params * * @param array $options options to format * * @return string Returns a string for formatted parameters * @access private * @since 1.1 */ function _getCreateParams($options) { $args = ''; if (is_null($options) === false && is_array($options) === true) { foreach ($options as $opt => $data) { switch (strtoupper($opt)) { case 'PARTITION': $args .= sprintf(" %s", $this->utf7Encode($data)); break; default: // ignore any unknown options break; } } } return $args; } /** * Return true if the TLS negotiation was successful * * @access public * @return mixed true on success, PEAR_Error on failure */ function cmdStartTLS() { if (PEAR::isError($res = $this->_genericCommand('STARTTLS'))) { return $res; } if (stream_socket_enable_crypto($this->_socket->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT) == false) { $msg = 'Failed to establish TLS connection'; return new PEAR_Error($msg); } if ($this->_debug === true) { echo "STARTTLS Negotiation Successful\n"; } // RFC says we need to query the server capabilities again if (PEAR::isError($res = $this->cmdCapability())) { $msg = 'Failed to connect, server said: ' . $res->getMessage(); return new PEAR_Error($msg); } return true; } /** * get the length of string * * @param string $string String * * @return int Line length * @access private */ function _getLineLength($string) { if (extension_loaded('mbstring')) { return mb_strlen($string, 'latin1'); } else { return strlen($string); } } /** * get substring from string * * @param string $string String * @param int $start Position to start from * @param int $length Number of characters * * @return string Substring * @access private */ function _getSubstr($string, $start, $length = false) { if (extension_loaded('mbstring')) { if ($length !== false) { return mb_substr($string, $start, $length, 'latin1'); } else { $strlen = mb_strlen($string, 'latin1'); return mb_substr($string, $start, $strlen, 'latin1'); } } else { if ($length !== false) { return substr($string, $start, $length); } else { return substr($string, $start); } } } }//Class ?> php-net-imap-1.1.1/Net_IMAP-1.1.1/README000066400000000000000000000010161170170425600166620ustar00rootroot00000000000000This package is http://pear.php.net/package/Net_IMAP and has been migrated from https://svn.php.net/repository/pear/packages/Net_IMAP Please report all new issues via the PEAR bug tracker. If this package is marked as unmaintained and you have fixes, please submit your pull requests and start discussion on the pear-qa mailing list. To test, run either $ phpunit tests/ or $ pear run-tests -r To build, simply $ pear package To install from scratch $ pear install package.xml To upgrade $ pear upgrade -f package.xml php-net-imap-1.1.1/Net_IMAP-1.1.1/docs/000077500000000000000000000000001170170425600167345ustar00rootroot00000000000000php-net-imap-1.1.1/Net_IMAP-1.1.1/docs/test_IMAP.php000066400000000000000000000234661170170425600212450ustar00rootroot00000000000000 | // +----------------------------------------------------------------------+ /* This sample shows the use of the IMAP methods this is only useful for testing and to high level IMAP access example use */ include_once('Net/IMAP.php'); error_reporting(E_ALL); $user="user"; $passwd="password"; $host="localhost"; $port="143"; //you can create a file called passwords.php and store your $user,$pass,$host and $port values in it // or you can modify this script @require_once("../passwords.php"); $imap= new Net_IMAP($host,$port); //The the Protocol debug feature //$imap->setDebug(); //$imap->setUnparsedResponse(true); //print_r($imap->cmdCapability()); // Login to the IMAP Server Using plain passwords ($authMethod=false) // $authMethod can be true (dafault) , false or a string /*$authMethod=false; if ( PEAR::isError( $ret = $imap->login( $user , $passwd , $authMethod ) ) ) { echo "Unable to login! reason:" . $ret->getMessage() . "\n"; exit(); } */ if ( PEAR::isError( $ret = $imap->login( $user , $passwd ) ) ) { echo "Unable to login! reason:" . $ret->getMessage() . "\n"; exit(); } /********************* *** Let's show the Mailbox related methods *** *********************/ $imap->selectMailbox('inbox'); //$mailboxes=$imap->getMailboxes(''); $mailboxes=$imap->getMailboxes('inbox.INBOX2',2); $mailboxes=$imap->getMailboxes('inbox'); //$mailboxes=$imap->listsubscribedMailboxes('inbox'); echo "Here is the list of all mailboxes:\n\n"; prettyMailboxList($imap,$mailboxes); $mailboxes=$imap->listsubscribedMailboxes('inbox'); echo "Here is the list of all mailboxes you are subscribed:\n\n"; prettyMailboxList($imap,$mailboxes); //$mailboxes=0; //echo "PITERROR|" . print_r( $imap->_socket->eof()) . "|\n"; //echo $imap->getDebugDialog(); //exit(); $folder_delim=$imap->getHierarchyDelimiter(); echo "Folder Delim:|$folder_delim|\n"; $mailbox='INBOX'.$folder_delim .'INBOX2'; echo "Getting the summary of message 1\n"; $aa=$imap->getSummary(1); //print_r($aa); $aaa=$imap->examineMailbox("inbox"); //print_r($aaa); echo "creating mailbox $mailbox ...."; if( ! $ret = $imap->createMailbox($mailbox) ){ echo "\nCan't create the mailbox '$mailbox' because " . $ret->getMessage() . "\n"; } else{ echo "OK!\n"; } echo "\n\n\n+-----------------------------------------------------------------------------+\n"; //$mailbox='INBOX.INBOX2'; //print_r($imap->cmdList("","*")); //$mailbox='INBOX'.$folder_delim .'INBOX2'; if( $imap->mailboxExist($mailbox) ){ echo "The mailbox $mailbox exists\n"; }else{ echo "The mailbox $mailbox don't exists!\n"; } $email="From: \r\n"; $email.="To: \r\n"; $email.="Subject: Test\r\n"; $email.="\r\n"; $email.="\r\n"; $email.="test\r\n"; echo "APPEND\n"; //$imap->cmdAppend("inbox",$email); $mailbox='inbox'; echo "Now lets check the flags of messages in $mailbox\n"; if ( !PEAR::isError( $num_messages = $imap->getNumberOfMessages( $mailbox ) ) ){ for($i=1; $i<=$num_messages;$i++) { print_r($imap->getFlags($i)); //echo "AAAA\n"; /* if ($imap->isSeen($i)) { echo "message $i has been read before...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isFlagged($i)) { echo "message $i has been Flagged...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isDeleted($i)) { echo "message $i is marked as Deleted...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } */ } }else{ echo "Or $mailbox has no messages or there was an error!\n"; } $imap->selectMailbox('inbox'); $nummsg = $imap->getNumberOfMessages(); for($i=1; $i<=$nummsg;$i++) { if ($imap->isSeen($i)) { echo "message $i has been read before...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isFlagged($i)) { echo "message $i has been Flagged...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isDeleted($i)) { echo "message $i is marked as Deleted...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } } /* echo "renaming mailbox INBOX2 to INBOX3 :
\n"; $imap->renameMailbox('INBOX2', 'INBOX3'); echo "deleting mailbox INBOX3 :
\n"; $imap->deleteMailbox('INBOX3'); //echo 'deleting msg 1 :
\n'; //$imap->delete(1); echo "creating mailbox TESTING :
\n"; $imap->createMailbox('TESTING'); echo "copying msg 1 INBOX to TESTING :
\n"; $imap->copyMessages(1, 'TESTING'); */ // Get the raw headers of message 1 echo "

getRawHeaders()

\n"; echo "
" . htmlspecialchars($imap->getRawHeaders(1)) . "
\n"; //* Get structured headers of message 1 echo "

getParsedHeaders()

\n";
print_r($imap->getParsedHeaders(1));
echo "
\n"; //* Get body of message 1 echo "

getBody()

\n"; echo "
" . htmlspecialchars($imap->getBody(1)) . "
\n"; //* Get number of messages in maildrop echo "

getNumMsg

\n"; echo "
" . $imap->numMsg('') . "
\n"; //* Get entire message echo "

getMsg()

\n"; if(!PEAR::isError($msg=$imap->getMsg(1))){ print_r($msg); echo '
' . htmlspecialchars($msg) . '
\n'; } //* Get listing details of the maildrop echo "

getListing()

\n"; echo "
\n";
print_r($imap->getListing());
echo "
\n"; //* Get size of maildrop echo "

getSize()

\n"; echo "
" . $imap->getSize() . "
\n"; //* Delete a msg //echo '

delete()

\n'; // Use with CARE!!! //echo '
' . $imap->deleteMsg(1) . '
\n'; $mailbox="inbox"; $imap->selectMailbox($mailbox); $nummsg=$imap->numMsg(); echo "You have $nummsg in $mailbox folder\n"; //echo "See header in message number 1: " . $imap->top(1) . '
'; echo "See header in message number 1: " . htmlspecialchars($imap->getRawHeaders(1)) . '
\n'; if(!PEAR::isError($msg=$imap->getMsg(1))){ print_r($msg); echo "Read message number 1: " . htmlspecialchars($msg) . '
\n'; } for($i=1; $i<=$nummsg;$i++) { if ($imap->isSeen($i)) { echo "message $i has been read before...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isFlagged($i)) { echo "message $i has been Flagged...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } if ($imap->isDeleted($i)) { echo "message $i is marked as Deleted...
\n"; //$msg = $imap->getMsg($i); #echo $msg; } } //print_r($imap->getMailboxes('')); echo "creating mailbox INBOX2 :
\n"; $imap->createMailbox('INBOX2'); echo "renaming mailbox INBOX2 to INBOX3 :
\n"; $imap->renameMailbox('INBOX2', 'INBOX3'); echo "deleting mailbox INBOX3 :
\n"; $imap->deleteMailbox('INBOX3'); //echo 'deleting msg 1 :
\n'; //$imap->delete(1); echo "creating mailbox TESTING :
\n"; $imap->createMailbox('TESTING'); echo "copying msg 1 INBOX to TESTING :
\n"; $imap->copyMessages('TESTING', 1); //* Disconnect $imap->disconnect(); function prettyMailboxList($imap,$mailboxes){ if( count($mailboxes) > 0 ){ echo "You have " . count($mailboxes) . " Mailboxes\n\n"; echo "+-----------------------------------------------------------------------------+\n"; echo "|Mailbox | Mbox Size | Cant Mesages|\n"; echo "+-----------------------------------------------------------------------------+\n"; foreach($mailboxes as $mailbox){ if ( PEAR::isError( $mbox_size =$imap->getMailboxSize( $mailbox ) ) ){ //echo "Unable to retr msg size" . $mbox_size->getMessage() . "|\n"; $mbox_size="[ERROR]"; } //print_r($mbox_size); if ( PEAR::isError( $num_messages = $imap->getNumberOfMessages( $mailbox ) ) ){ //echo "Unable to rert msg" . $num_messages->getMessage() . "|\n"; $num_messages="[ERROR]"; } echo "|"; echo $mailbox; // Align the output for($i=strlen($mailbox) ; $i< 50 ; $i++) echo ' '; echo "|"; // Align the output for($i=strlen($mbox_size) ; $i< 12 ; $i++) echo ' '; echo $mbox_size; echo "|"; // Align the output //print_r($num_messages); for($i=strlen($num_messages) ; $i< 13 ; $i++) echo ' '; echo $num_messages; echo "|"; echo "\n"; } echo "+-----------------------------------------------------------------------------+\n"; }else{ echo "Warning!:\n You have any mailboxes!!\n"; } } ?> php-net-imap-1.1.1/Net_IMAP-1.1.1/docs/test_IMAPProtocol.php000066400000000000000000000154621170170425600227640ustar00rootroot00000000000000 | // +----------------------------------------------------------------------+ /* This sample shows the parsed returning of the IMAPProtocol methods this is only useful for testing and to low level IMAP access example */ require_once('Net/IMAPProtocol.php'); error_reporting(E_ALL); $user="user"; $passwd="password"; $host="localhost"; $port="143"; //you can create a file called passwords.php and store your $user,$pass,$host and $port values in it // or you can modify this script @require_once("../passwords.php"); $a= new Net_IMAPProtocol(); $a->setDebug(true); //$a->setUnparsedResponse(true); //$a->setUnparsedResponse(false); $aaa=$a->cmdConnect($host,$port); //Choose your auth method... //$aaa=$a->cmdAuthenticate($user,$passwd); //$aaa=$a->cmdAuthenticate($user,$passwd, "CRAM-MD5"); $aaa=$a->cmdLogin($user,$passwd); //$aaa=$a->login($user,$passwd); //$aaa=$a->cmdSelect("user.damian"); $aaa=$a->cmdSelect("inbox"); $str="inbox.peteáá"; //$str="inbox.inbox3aaa &4eE-"; //$str="inbox.&AOEA4QDh-"; echo "Method cmdCreate()\n"; print_r($aaa=$a->cmdCreate($str)); echo "Method cmdList()\n"; print_r($aaa=$a->cmdList("","*")); //Returns the Auth Methods the IMAP server Has //print_r($aaa=$a->getServerAuthMethods()); //print_r($aaa=$a->cmdFetch("4","(BODY[1.1])")); //print_r($aaa=$a->cmdFetch("4","(BODY[1])")); print_r($aaa=$a->cmdFetch("4","(RFC822.TEXT)")); print_r($aaa=$a->cmdFetch("1","(BODY[HEADER] BODY[TEXT])")); print_r($aaa=$a->cmdFetch("1","BODY[HEADER]")); print_r($aaa=$a->cmdFetch("15","FULL")); print_r($aaa=$a->cmdFetch("1:3","(FLAGS RFC822.SIZE UID ENVELOPE INTERNALDATE)")); //print_r($aaa=$a->cmdFetch("1:3","(FLAGS RFC822.SIZE UID INTERNALDATE)")); //$aaa=$a->cmdFetch("1","(FLAGS RFC822.SIZE UID ENVELOPE INTERNALDATE)"); //print_r($aaa=$a->cmdFetch("1","(FLAGS RFC822.SIZE UID INTERNALDATE)")); //$aaa=$a->cmdFetch("1:3","BODY[HEADER.FIELDS (References)]"); //$aaa=$a->cmdFetch("1","(UID RFC822.SIZE)"); //$aaa=$a->cmdFetch("1:10","RFC822.SIZE"); //$aaa=$a->cmdFetch("1:10","INTERNALDATE"); //$aaa=$a->cmdFetch("2:6","BODY[TEXT]"); //$aaa=$a->cmdFetch("1:3","(FLAGS)"); //$aaa=$a->cmdFetch("26:32","BODY"); //$aaa=$a->cmdFetch("26:29","BODY"); //$aaa=$a->cmdFetch("1","RFC822"); $aaa=$a->cmdFetch("28","BODY"); //$aaa=$a->cmdFetch("1","BODYSTRUCTURE"); //$aaa=$a->cmdFetch("27","BODYSTRUCTURE"); //$aaa=$a->cmdFetch("1:100","BODYSTRUCTURE"); $aaa=$a->cmdFetch("2:10","(RFC822.SIZE FLAGS INTERNALDATE)"); //$aaa=$a->cmdFetch("1:10","INTERNALDATE"); $aaa=$a->cmdFetch("1","ENVELOPE"); $aaa=$a->cmdFetch("10,9:16","FLAGS"); //$aaa=$a->cmdFetch("10","BODY[TEXT]"); //$aaa=$a->cmdFetch("10","RFC822.HEADER"); //$aaa=$a->cmdFetch("10","RFC822.TEXT"); //$aaa=$a->cmdFetch("10","BODYSTRUCTURE"); //$aaa=$a->cmdFetch("10","RFC822.HEADER"); $aaa=$a->cmdFetch("1:4","(BODY[HEADER] FLAGS RFC822.SIZE INTERNALDATE)"); //$aaa=$a->cmdFetch("1:4","(FLAGS RFC822.SIZE INTERNALDATE)"); //$aaa=$a->cmdFetch("10","BODY[1]"); //$aaa=$a->cmdFetch("1","RFC822.SIZE"); //$aaa=$a->cmdFetch("10","ENVELOPE"); //$aaa=$a->cmdFetch("10","RFC822"); //$aaa=$a->cmdFetch("10","ENVELOPE"); //$aaa=$a->cmdFetch("1:30","(RFC822.SIZE FLAGS)"); //$aaa=$a->cmdFetch("1:30","FLAGS"); //print_r($aaa=$a->cmdFetch(32,"FLAGS")); //print_r($aaa=$a->cmdFetch("1:3","(FLAGS RFC822.SIZE UID ENVELOPE INTERNALDATE)")); //print_r($aaa=$a->cmdFetch("1","(FLAGS RFC822.SIZE UID ENVELOPE INTERNALDATE)")); //print_r($aaa=$a->cmdFetch("10","ENVELOPE")); //print_r($aaa=$a->cmdFetch("10","FLAGS")); //$aaa=$a->cmdUidFetch("1","FLAGS"); //print_r($aaa=$a->cmdCapability()); //print_r($aaa=$a->cmdStore("1:2","+FLAGS","\Deleted")); echo "Method cmdCheck()\n"; print_r($aaa=$a->cmdCheck()); //print_r($aaa=$a->cmdClose()); echo "Method cmdNoop()\n"; print_r($aaa=$a->cmdNoop()); echo "Method cmdRename()\n"; print_r($aaa=$a->cmdRename("inbox.test2","inbox.test3")); echo "Method cmdSubscribe()\n"; print_r($aaa=$a->cmdSubscribe("inbox.test1")); echo "Method cmdStatus()\n"; print_r($aaa=$a->cmdStatus("inbox","MESSAGES UNSEEN")); echo "Method cmdUnsubscribe()\n"; print_r($aaa=$a->cmdUnsubscribe("inbox.test1")); echo "Method cmdList()\n"; print_r($aaa=$a->cmdList("","*")); echo "Method cmdLsub()\n"; print_r($aaa=$a->cmdLsub("*","*")); echo "Method cmdSearch()\n"; print_r($aaa=$a->cmdSearch("ALL")); echo "Method cmdUidSearch()\n"; print_r($aaa=$a->cmdUidSearch("ALL")); echo "Method cmdCopy()\n"; print_r($aaa=$a->cmdCopy("1","inbox.test1")); echo "Method cmdGetQuota()\n"; print_r($aaa=$a->cmdGetQuota("user.montoto")); echo "Method cmdMyRights()\n"; print_r($aaa=$a->cmdMyRights("inbox")); echo "Method cmdListRights()\n"; print_r($aaa=$a->cmdListRights("inbox","montoto")); echo "Method cmdGetACL()\n"; print_r($aaa=$a->cmdGetACL("user.montoto")); echo "Method cmdSetQuota()\n"; print_r($aaa=$a->cmdSetQuota("user.montoto","500000")); echo "Method cmdCheck()\n"; print_r($aaa=$a->cmdCheck()); echo "Method cmdCreate()\n"; print_r($aaa=$a->cmdCreate("inbox.inbox3")); echo "Method cmdStatus()\n"; print_r($a->cmdStatus("inbox","MESSAGES UNSEEN")); print_r($a->_serverSupportedCapabilities); echo "Method cmdExamine()\n"; print_r($aaa=$a->cmdExamine("inbox")); echo "Method cmdStore()\n"; print_r($aaa=$a->cmdStore("1:2","+FLAGS","\Deleted")); echo "Method cmdExpunge()\n"; print_r($a->cmdExpunge()); echo "Check if the server has ANNOTATEMORE Support\n"; if( $a->hasAnnotateMoreSupport() ){ echo "Yes the server has ANNOTATEMORE Support\n"; //print_r( $a->cmdGetAnnotation("inbox" , array("test"), "algo") ); print_r( $a->cmdSetAnnotation("INBOX" , "/comment",array("value.priv"=>"My comment" ) ) ); print_r( $a->cmdGetAnnotation("INBOX" , "/comment","value.priv" ) ); } else{ echo "The server has NOT ANNOTATEMORE Support\n"; } //print_r($aaa); $aaa=$a->cmdLogout(); //print_r($aaa); ?> php-net-imap-1.1.1/Net_IMAP-1.1.1/tests/000077500000000000000000000000001170170425600171465ustar00rootroot00000000000000php-net-imap-1.1.1/Net_IMAP-1.1.1/tests/IMAPTest.php000066400000000000000000000242541170170425600212540ustar00rootroot00000000000000 * @copyright 2006 Sebastian Ebling * @license http://www.gnu.org/copyleft/gpl.html * @version CVS: $Id$ * @link http://pear.php.net/package/Net_IMAP/ */ /** * We are testing IMAP.php */ require_once 'Net/IMAP.php'; /** * Use PHPUnit3 for testing */ require_once 'PHPUnit/Framework/TestCase.php'; /** * The test class */ class testIMAP extends PHPUnit_Framework_TestCase { // contains the object handle of the Net_IMAP class protected $fixture; private $delimiter; private $reservedFolders; private $mailboxNames; function testIMAP() { $conn = new Net_IMAP(HOST, PORT); // we need to login for getting the delimiter $conn->login(USER, PASS); if (PEAR::isError($this->delimiter = $conn->getHierarchyDelimiter())) { $this->fail('Can not get hierarchy delimiter'); } $conn->disconnect(); $this->reservedFolders = array( 'INBOX', 'INBOX'.$this->delimiter.'Trash'); } protected function setUp() { if (file_exists(dirname(__FILE__) . '/settings.php')) { include_once dirname(__FILE__) . '/settings.php'; } else { $this->markTestSkipped("No settings.php available?"); } $this->fixture = new Net_IMAP(); // some mailboxnames to test with $this->mailboxNames = array(); $this->mailboxNames[] = 'INBOX'.$this->delimiter.'testcase'; $this->mailboxNames[] = 'INBOX'.$this->delimiter.'umlautsöäüßÖÄÜ'; // ToDo: insert some mails // $this->messages['test_mail1'] = file_get_contents('mails1.mbox'); // $this->messages['test_mail2'] = file_get_contents('mails2.mbox'); // $this->messages['test_mail3'] = file_get_contents('mails3.mbox'); } protected function tearDown() { // delete all mailboxes except INBOX $mailboxes = $this->fixture->getMailboxes(); foreach ($mailboxes as $mailbox) { if (in_array($mailbox, $this->reservedFolders)) { continue; } $this->fixture->deleteMailbox($mailbox); } // delete instance unset($this->fixture); } protected function login() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue(!PEAR::isError($result), 'Can not connect'); $result = $this->fixture->login(USER, PASS); $this->assertTrue(!PEAR::isError($result), 'Can not log in'); } protected function logout() { $result = $this->fixture->disconnect(); $this->assertTrue(!PEAR::isError($result), 'Error on disconnect'); } /// /// connection tests /// public function testConnect() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue(!PEAR::isError($result), 'Can not connect'); } public function testLogin() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue(!PEAR::isError($result), 'Can not connect'); $result = $this->fixture->login(USER, PASS); $this->assertTrue(!PEAR::isError($result), 'Can not login'); } public function testDisconnect() { $result = $this->fixture->connect(HOST, PORT); $this->assertTrue(!PEAR::isError($result), 'Can not connect'); $result = $this->fixture->login(USER, PASS); $this->assertTrue($result, 'Can not login'); $result = $this->fixture->disconnect(); $this->assertTrue(!PEAR::isError($result), 'Error on disconnect'); } /// /// mailbox tests /// public function testCreateMailbox() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); foreach ($this->mailboxNames as $mailbox) { if (in_array($mailbox, $this->reservedFolders)) { continue; } $this->fixture->deleteMailbox($mailbox); } foreach ($this->mailboxNames as $mailbox) { if ($mailbox == 'INBOX') { continue; } $result = $this->fixture->createMailbox($mailbox); $this->assertTrue($result, 'Can not create mailbox '.$mailbox); } // print_r($this->fixture->getMailboxes()); $this->logout(); } public function testGetMailboxes() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); // print_r($mailboxes); $this->logout(); $this->assertTrue(!PEAR::isError($mailboxes), 'Can not list mailboxes'); } public function testSelectMailbox() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); foreach ($mailboxes as $mailbox) { $result = $this->fixture->selectMailbox($mailbox); $this->assertTrue(!PEAR::isError($result), 'Can not select mailbox '.$mailbox); } $this->logout(); } // examineMailbox needs some messages for testing public function testRenameMailbox() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); // print_r($mailboxes); foreach ($mailboxes as $mailbox) { if (in_array($mailbox, $this->reservedFolders)) { continue; } $result = $this->fixture->renameMailbox($mailbox, $mailbox.'renamed'); $this->assertTrue(!PEAR::isError($result), 'Can not rename mailbox '.$mailbox); } $mailboxes_new = $this->fixture->getMailboxes(); for ($i=0; $i < sizeof($mailboxes_new); $i++) { if (in_array($mailboxes[$i], $this->reservedFolders)) { continue; } $this->assertTrue(($mailboxes[$i].'renamed' == $mailboxes_new[$i]), 'Mailbox '.$mailboxes[$i].' not renamed'); } // print_r($mailboxes_new); $this->logout(); } public function testMailboxExist() { $this->login(); // this mailbox name must not exist before $mailboxname = 'INBOX'.$this->delimiter.'testMailboxExistöäüß'; $this->fixture->deleteMailbox($mailboxname); $result = $this->fixture->mailboxExist($mailboxname); $this->assertFalse($result, 'Mailbox should NOT exist'); $result = $this->fixture->createMailbox($mailboxname); $this->assertTrue(!PEAR::isError($result), 'Can not create mailbox'); $result = $this->fixture->mailboxExist($mailboxname); $this->assertTrue($result, 'Mailbox should exist'); $result = $this->fixture->deleteMailbox($mailboxname); $this->assertTrue($result, 'Can not delete Mailbox'); $this->logout(); } public function testDeleteMailbox() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); // print_r($mailboxes); foreach ($mailboxes as $mailbox) { if (in_array($mailbox, $this->reservedFolders)) { continue; } $result = $this->fixture->deleteMailbox($mailbox); $this->assertTrue(!PEAR::isError($result), 'Can not delete mailbox '.$mailbox); } // print_r($this->fixture->getMailboxes()); $this->logout(); } public function testGetMailboxSize() { $this->login(); $mailboxes = $this->fixture->getMailboxes(); foreach ($mailboxes as $mailbox) { $result = $this->fixture->getMailboxSize($mailbox); // print_r($result); $this->assertTrue(!PEAR::isError($result), 'Can not get size for mailbox '.$mailbox); } $this->logout(); } /// /// suscribing tests /// public function testSubscribeMailbox() { $this->login(); $this->fixture->createMailbox('INBOX'.$this->delimiter.'testSubscribe'); $result = $this->fixture->subscribeMailbox('INBOX'.$this->delimiter.'testSubscribe'); $this->assertTrue(!PEAR::isError($result), 'Can not subscribe Mailbox'); $this->logout(); } public function testListsubscribedMailboxes() { $this->login(); $this->fixture->createMailbox('INBOX'.$this->delimimter.'testSubscribe'); $this->fixture->subscribeMailbox('INBOX'); $this->fixture->subscribeMailbox('INBOX'.$this->delimiter.'testSubscribe'); $subscribed = $this->fixture->listsubscribedMailboxes(); //print_r($subscribed); $this->logout(); $this->assertTrue(!PEAR::isError($subscribed), 'Can not list subscribed mailboxes'); } public function testUnsubscribeMailbox() { $this->login(); $subscribed = $this->fixture->listsubscribedMailboxes(); // print_r($subscribed); foreach ($subscribed as $mailbox) { if ($mailbox == 'INBOX') { continue; } $result = $this->fixture->unsubscribeMailbox($mailbox); $this->assertTrue(!PEAR::isError($result), 'Can not unsubscribe mailbox '.$mailbox); } // print_r($this->fixture->listsubscribedMailboxes()); $this->logout(); } public function testGetStorageQuotaRoot() { $this->login(); if (!$this->fixture->hasCapability('QUOTA')) { return; } $this->fixture->selectMailbox('INBOX'); $result = $this->fixture->getStorageQuotaRoot(); $this->assertTrue(!PEAR::isError($result), 'Can not get StorageQuotaRoot'); $this->logout(); } public function testGetACL() { $this->login(); if (!$this->fixture->hasCapability('ACL')) { return; } $result = $this->fixture->getACL(); $this->assertTrue(!PEAR::isError($result), 'Can not get ACL'); $this->logout(); } public function testGetHierarchyDelimiter() { $this->login(); $result = $this->fixture->getHierarchyDelimiter(); $this->assertTrue(!PEAR::isError($result), 'Can not get Hierarchy Delimiter'); $this->logout(); } } ?> php-net-imap-1.1.1/Net_IMAP-1.1.1/tests/settings.php.sample000066400000000000000000000010611170170425600227750ustar00rootroot00000000000000 * @copyright 2006 Sebastian Ebling * @license http://www.gnu.org/copyleft/gpl.html * @version CVS: $Id$ * @link http://pear.php.net/package/Net_IMAP/ */ /** * Connection settings */ define('HOST', 'testhost'); define('PORT', '143'); define('USER', 'testuser'); define('PASS', 'testpass'); ?> php-net-imap-1.1.1/package.xml000066400000000000000000000314541170170425600161400ustar00rootroot00000000000000 Net_IMAP pear.php.net Provides an implementation of the IMAP protocol Provides an implementation of the IMAP4Rev1 protocol using PEAR's Net_Socket and the optional Auth_SASL class. Anish Mistry amistry amistry@am-productions.biz yes Sebastian Ebling hudeldudel hudeldudel@php.net yes Damian Alejandro Fernandez Sosa damian damlists@cnba.uba.ar no 2012-01-02 1.1.1 1.1.0 stable stable PHP License QA release Bug #14566 Error in parsing protocol Bug #16288 getMessagesList breaks if mailbox is empty Bug #16819 IMAPProtocol::cmdStatus fails on error Bug #16891 bug in IMAPProtocol.php aka operator precedence error in _getNextToken Bug #18599 Wrong result from getAnnotation() for folder with non-ascii characters Bug #18768 failed to connect to Gmail (start TLS) 4.2 1.4.0b1 Net_Socket pear.php.net 1.0.8 Auth_SASL pear.php.net 1.0.2 0.1 0.1 beta beta 2003-02-22 PHP License - The IMAP Procotol generic parser is now implemented. - Implemmented RFC2195 - Implemmented RFC2060 0.2 0.2 beta beta 2003-02-22 PHP License - Ups I call require_once ./IMAPProtocol.php instead of require_once Net/IMAPProtocol.php sorry - login method can authenticate with the following methods: DIGEST-MD4, CRAM-MD5, LOGIN and the login command - A lot of new mailbox-related functions - 2 Examples of use to the test directory - fixes in protocol parser 0.3 0.3 beta beta 2003-03-05 PHP License - Fixed a lot of warnings and uninitialized variables(hope all of them) - new getSummary method - updated Examples of use - tested with Ipswitch Imail 6.06 IMAP Server - tested with Cyrus Imapd 2.0.17 IMAP Server - tested with uw-imapd IMAP Server - minor fixes in protocol parser - changed appendMessage() to make the mailbox parameter optional - added Subscription related methods: unsubscribeMailbox(),listsubscribedMailboxes(),subscribeMailbox() - workarround about getMailboxes() to allow work with wu-imapd - new search() method - added support for Message quotas (quotas for quantity of messages and not size) - getSummary(), getMessages(),deleteMessages() can accept an array of numbers as msg_id to retrieve/delete msg_id that are in the array (designed to use the search() output as parammeter. For example: to delete all seen messages in current mailbox you can do: $imap->getDeleteMessages($imap->search("SEEN")); 0.4 0.4 beta beta 2003-04-27 PHP License - new search() method - new support for Message quotas (quotas for quantity of messages and not size) - new getNumberOfRecentMessages() method - new getNumberOfUnSeenMessages() method - new getEnvelope() method - new getSummary() method - new Subscription related methods: unsubscribeMailbox(),listsubscribedMailboxes(),subscribeMailbox() - updated Examples of use - tested with Ipswitch Imail 6.06 IMAP Server - tested with Cyrus Imapd 2.0.17 IMAP Server - tested with uw-imapd IMAP Server - minor fixes in protocol parser - fix the parsing of rfc email in _getAddressList() - changed appendMessage() to make the mailbox parameter optional - changed copyMessages() method (the messages list can be now an array) - workarround about getMailboxes() to allow work with wu-imapd - getSummary(), getMessages(),deleteMessages() can accept an array of numbers as msg_id to retrieve/delete msg_id that are in the array (designed to use the search() output as parammeter. For example: to delete all seen messages in current mailbox you can do: $imap->DeleteMessages($imap->search("SEEN")); 0.5 0.5 beta beta 2003-07-12 PHP License - new getHierachyDelimiter() method to find the character used to separate subfolder parts (cyrus uses '.' , wu-imapd uses '/') - added a 3rd parameter to getMailboxes() to return an array with mailboxnames and mailbox attributes instead of an array of names - new method getACLRights() to list the Rights any user has over a mailbox without been administrator (this is relative to the user's INBOX) 0.5.1 0.5.1 beta beta 2003-07-14 PHP License - Fix warning in login() where the imap server does not have any Auth method suported 0.6 0.6 beta beta 2003-07-20 PHP License - Fixed bugs 24706 and 24707 - Fixed method listsubscribedMailboxes() and now works like getMailboxes() - added hasFlag() method to allow th check any flag the IMAP server has - Modified isDeleted,isDraft,isAnswered,isFlagged,isSeen methods to use hasFlag to not duplicate the code - Removed duplicated method getHierarchyDelimiter() i have the same method in IMAP.php and IMAPProtocol.php but in one class it is called getHierachyDelimiter and in the other getHierarchyDelimiter() (missed 'r' ) - Removed $_hierachyDelimiter variable (not needed anymore) - Fixed cmdSetQuotaRoot now it can set both quotas storage and messages - Reduced the class size by 10kbytes (IMAPProtocol.php) - moved all redundant code to _genericCommand. - Removed cmdUid() we don't need it anymore. 0.7 0.7 beta beta 2004-02-02 PHP License - Fixed bug in mailboxExist - Fixed bug #55 0.7.1 0.7.1 beta beta 2004-02-12 PHP License * The parser was modified to parse any BODY[XXXXXX] response (not supported spaces in XXXXX yet) thanks to Richard Heyes for the tip 1.0.0 1.0.0 stable stable 2004-05-22 PHP License * The package is marked as stable * Fixed bug #1280 * Fixed a bug returning " , " when the password is not correct 1.0.1 1.0.1 stable stable 2004-05-22 PHP License * Fixed bug #1568 1.0.2 1.0.2 stable stable 2004-08-04 PHP License * Fixed bug #1772 * Fixed bug #2028 * Changed getStorageQuota, getMessagesQuota,getACL defautting mailbox_name to current selected mailbox 1.0.3 1.0.3 stable stable 2004-09-25 PHP License * Fixed bug #2379 (Yes it was a copy-paste bug!) Thanks to omicron at mighty dot co dot za 1.1.0beta1 1.1.0beta1 beta beta 2007-01-10 PHP License new beta release fixing bugs and introducing new features * bugfixing * add STARTTLS support for PHP 5.1 and above * added methods for manipulating message flags * added support for fetching the mailbox status at once (getStatus) * added support for fetching subparts and the headers of subparts * added support for fetching the namespace * added support for fetching the bodystructure * added support for setting flags when appending messages * added method for parsing image information 1.1.0 1.1.0 stable stable 2012-01-02 PHP License New stable release introducing new features and fixing a lot of bugs 1.1.1 1.1.0 stable stable 2012-01-02 PHP License QA release Bug #14566 Error in parsing protocol Bug #16288 getMessagesList breaks if mailbox is empty Bug #16819 IMAPProtocol::cmdStatus fails on error Bug #16891 bug in IMAPProtocol.php aka operator precedence error in _getNextToken Bug #18599 Wrong result from getAnnotation() for folder with non-ascii characters Bug #18768 failed to connect to Gmail (start TLS)