imapprotocol.php

来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 2,423 行 · 第 1/5 页

PHP
2,423
字号
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license,      |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | license@php.net so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Author: Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>       |
// +----------------------------------------------------------------------+
require_once 'Net/Socket.php';



/**
 * Provides an implementation of the IMAP protocol using PEAR's
 * Net_Socket:: class.
 *
 * @package Net_IMAP/Protocol
 * @author  Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>
 */
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
     */
    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
     */
    var $_socket = null;

     /**
     * To allow class debuging
     * @var boolean
     */
    var $_debug = false;

    var $dbgDialog = '';

     /**
     * Command Number
     * @var int
     */
    var $_cmd_counter = 1;


     /**
     * Command Number for IMAP commands
     * @var int
     */
    var $_lastCmdID = 1;

     /**
     * Command Number
     * @var boolean
     */
    var $_unParsedReturn = false;



     /**
     * _connected: checks if there is a connection made to a imap server or not
     * @var boolean
     */
    var $_connected = false;
     /**
     * Capabilities
     * @var boolean
     */
    var $_serverSupportedCapabilities = null;



     /**
     * Use UTF-7 funcionallity
     * @var boolean
     */
    //var $_useUTF_7 = false;
    var $_useUTF_7 = true;



    /**
     * 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.
     *
     * @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( $this->_socket->connect( $host , $port ) ) ) {
            return new PEAR_Error( 'unable to open socket' );
        }
        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 True or false
     *
     * @return nothing
     * @access public
     * @since  1.0
     */
    function setDebug($debug = true)
    {
        $this->_debug = $debug;
    }


    function getDebugDialog()
    {
        return $this->dbgDialog;
    }



    /**
     * 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 "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 The userid to authenticate as.
     * @param string 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 The userid to authenticate as.
     * @param string The password to authenticate with.
     * @param string 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->_authDigest_MD5( $uid , $pwd , $cmdid );
                break;
            case 'CRAM-MD5':
                $result = $this->_authCRAM_MD5( $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 The userid to authenticate as.
     * @param string The password to authenticate with.
     * @param string The cmdID.
     *
     * @return array Returns an array containing the response
     *
     * @access private
     * @since  1.0
     */
    function _authDigest_MD5($uid , $pwd , $cmdid)
    {

        if ( PEAR::isError($error = $this->_putCMD( $cmdid ,"AUTHENTICATE" , "DIGEST-MD5") ) ) {
            return $error;
        }

        if (PEAR::isError( $args = $this->_recvLn() ) ) {
            return $args;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?