²é¿´ POP3/SMTP ЭÒéµÄʱºòÏë³¢ÊÔÒ»ÏÂ×Ô¼ºÐ´Ò»¸ö²Ù×÷À࣬ºËÐÄûɶ£¬¾ÍÊÇʹÓà fsockopen £¬È»ºóдÈë/½ÓÊÕÊý¾Ý£¬Ö»ÊµÏÖÁË×îºËÐĵIJ¿·Ö¹¦ÄÜ£¬µ±×÷ÊÇѧϰ Socket ²Ù×÷µÄÁ·ÊÖ¡£ÆäÖвο¼ÁË RFC 2449ºÍÒ»¸ö¹úÍâµÄ¼òµ¥WebÓʼþϵͳ Uebimiau µÄ²¿·Ö´úÂ룬²»¹ý¾ø¶ÔûÓг­ËûµÎ£¬HOHO£¬¾ø¶ÔÔ­´´¡£Èç¹ûÄãϲ»¶£¬ÇëÊղأ¬Ëæ±ãÐ޸ģ¬àÅ£¬µ«ÊǼǵò»ÒªÉ¾³ýżÀàÀïµÄÉùÃû£¬±Ï¾¹Å¼Ò²ÊÇÐÁÐÁ¿à¿àдÁ˺ü¸ÌìÄÅ¡£
ÁíÍ⣬»¶Ó­×ÔÓÉ·¢»Ó£¬¸ÄÉÆ»òÕßÐÞÕýÕâ¸öÀ࣬ϣÍûÄܹ»ÎªÄãËùÓᣴúÂëûÓÐÈÏÕæ×ÐϸµÄµ÷ÊÔ£¬·¢ÏÖbugÇë×Ô¼ºÐÞÕý£¬HOHO£¡

<?php
/**
 * ÀàÃû£ºSocketPOPClient
 * ¹¦ÄÜ£ºPOP3 ЭÒé¿Í»§¶ËµÄ»ù±¾²Ù×÷Àà
 * ×÷Õߣºheiyeluren <http://blog.csdn.net/heiyeshuwu>
 * ʱ¼ä£º2006-7-3
 * ²Î¿¼£ºRFC 2449, Uebimiau
 * ÊÚȨ£ºBSD License
 */

class SocketPOPClient
{
    var $strMessage        = '';
    var $intErrorNum    = 0;
    var $bolDebug        = false;
    
    var $strEmail        = '';
    var $strPasswd        = '';
    var $strHost        = '';
    var $intPort        = 110;
    var $intConnSecond    = 30;
    var $intBuffSize    = 8192;

    var $resHandler        = NULL;
    var $bolIsLogin        = false;
    var $strRequest        = '';
    var $strResponse    = '';
    var $arrRequest        = array();
    var $arrResponse    = array();


    //---------------
    // »ù´¡²Ù×÷
    //---------------

    //¹¹Ô캯Êý
    function SocketPOP3Client($strLoginEmail, $strLoginPasswd, $strPopHost='', $intPort='')
    {
        $this->strEmail        = trim(strtolower($strLoginEmail));
        $this->strPasswd    = trim($strLoginPasswd);
        $this->strHost        = trim(strtolower($strPopHost));

        if ($this->strEmail=='' || $this->strPasswd=='')
        {
            $this->setMessage('Email address or Passwd is empty', 1001);
            return false;
        }
        if (!preg_match("/^[/w-]+(/.[/w-]+)*@[/w-]+(/.[/w-]+)+$/i", $this->strEmail))
        {
            $this->setMessage('Email address invalid', 1002);
            return false;
        }
        if ($this->strHost=='')
        {
            $this->strHost = substr(strrchr($this->strEmail, "@"), 1);
        }
        if ($intPort!='')
        {
            $this->intPort = $intPort;
        }
        $this->connectHost();
    }
    
    //Á¬½Ó·þÎñÆ÷
    function connectHost()
    {
        if ($this->bolDebug)
        {
            echo "Connection ".$this->strHost." .../r/n";
        }
        if (!$this->getIsConnect())
        {
            if ($this->strHost=='' || $this->intPort=='')
            {
                $this->setMessage('POP3 host or Port is empty', 1003);
                return false;            
            }
            $this->resHandler = @fsockopen($this->strHost, $this->intPort, &$this->intErrorNum, &$this->strMessage, $this->intConnSecond);
            if (!$this->resHandler)
            {
                $strErrMsg = 'Connection POP3 host: '.$this->strHost.' failed';
                $intErrNum = 2001;
                $this->setMessage($strErrMsg, $intErrNum);
                return false;
            }
            $this->getLineResponse();
            if (!$this->getRestIsSucceed())
            {
                return false;
            }
        }
        return true;
    }

    //¹Ø±ÕÁ¬½Ó
    function closeHost()
    {
        if ($this->resHandler)
        {
            fclose($this->resHandler);
        }
        return true;
    }

    //·¢ËÍÖ¸Áî
    function sendCommand($strCommand)
    {
        if ($this->bolDebug)
        {
            if (!preg_match("/PASS/", $strCommand))
            {
                echo "Send Command: ".$strCommand."/r/n";
            }
            else
            {
                echo "Send Command: PASS ******/r/n";
            }

        }
        if (!$this->getIsConnect())
        {
            return false;
        }
        if (trim($strCommand)=='')
        {
            $this->setMessage('Request command is empty', 1004);
            return false;
        }
        $this->strRequest = $strCommand."/r/n";
        $this->arrRequest[] = $strCommand;
        fputs($this->resHandler, $this->strRequest);
        return true;
    }

    //ÌáÈ¡ÏìÓ¦ÐÅÏ¢µÚÒ»ÐÐ
    function getLineResponse()
    {
        if (!$this->getIsConnect())
        {
            return false;
        }
        $this->strResponse = fgets($this->resHandler, $this->intBuffSize);
        $this->arrResponse[] = $this->strResponse;

        return $this->strResponse;        
    }

    //ÌáÈ¡Èô¸ÉÏìÓ¦ÐÅÏ¢,$intReturnTypeÊÇ·µ»ØÖµÀàÐÍ, 1Ϊ×Ö·û´®, 2ΪÊý×é
    function getRespMessage($intReturnType)
    {
        if (!$this->getIsConnect())
        {
            return false;
        }
        if ($intReturnType == 1)
        {
            $strAllResponse = '';
            while(!feof($this->resHandler))
            {
                $strLineResponse = $this->getLineResponse();
                if (preg_match("/^/+OK/", $strLineResponse))
                {
                    continue;
                }
                if (trim($strLineResponse)=='.')
                {
                    break;
                }
                $strAllResponse .= $strLineResponse;
            }
            return $strAllResponse;
        }
        else
        {
            $arrAllResponse = array();
            while(!feof($this->resHandler))
            {
                $strLineResponse = $this->getLineResponse();
                if (preg_match("/^/+OK/", $strLineResponse))
                {
                    continue;
                }
                if (trim($strLineResponse)=='.')
                {
                    break;
                }
                $arrAllResponse[] = $strLineResponse;
            }
            return $arrAllResponse;            
        }
    }

    //ÌáÈ¡ÇëÇóÊÇ·ñ³É¹¦
    function getRestIsSucceed($strRespMessage='')
    {
        if (trim($responseMessage)=='')
        {
            if ($this->strResponse=='')
            {
                $this->getLineResponse();
            }
            $strRespMessage = $this->strResponse;
        }
        if (trim($strRespMessage)=='')
        {
            $this->setMessage('Response message is empty', 2003);
            return false;
        }
        if (!preg_match("/^/+OK/", $strRespMessage))
        {
            $this->setMessage($strRespMessage, 2000);
            return false;
        }
        return true;
    }

    //»ñÈ¡ÊÇ·ñÒÑÁ¬½Ó
    function getIsConnect()
    {
        if (!$this->resHandler)
        {
            $this->setMessage("Nonexistent availability connection handler", 2002);
            return false;
        }
        return true;
    }


    //ÉèÖÃÏûÏ¢
    function setMessage($strMessage, $intErrorNum)
    {
        if (trim($strMessage)=='' || $intErrorNum=='')
        {
            return false;
        }
        $this->strMessage    = $strMessage;
        $this->intErrorNum    = $intErrorNum;
        return true;
    }

    //»ñÈ¡ÏûÏ¢
    function getMessage()
    {
        return $this->strMessage;
    }

    //»ñÈ¡´íÎóºÅ
    function getErrorNum()
    {
        return $this->intErrorNum;
    }

    //»ñÈ¡ÇëÇóÐÅÏ¢
    function getRequest()
    {
        return $this->strRequest;        
    }

    //»ñÈ¡ÏìÓ¦ÐÅÏ¢
    function getResponse()
    {
        return $this->strResponse;
    }


    //---------------
    // ÓʼþÔ­×Ó²Ù×÷
    //---------------

    //µÇ¼ÓÊÏä
    function popLogin()
    {
        if (!$this->getIsConnect())
        {
            return false;
        }
        $this->sendCommand("USER ".$this->strEmail);
        $this->getLineResponse();
        $bolUserRight = $this->getRestIsSucceed();

        $this->sendCommand("PASS ".$this->strPasswd);
        $this->getLineResponse();
        $bolPassRight = $this->getRestIsSucceed();

        if (!$bolUserRight || !$bolPassRight)
        {
            $this->setMessage($this->strResponse, 2004);
            return false;
        }        
        $this->bolIsLogin = true;
        return true;
    }

    //Í˳öµÇ¼
    function popLogout()
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("QUIT");
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return true;
    }

    //»ñÈ¡ÊÇ·ñÔÚÏß
    function getIsOnline()
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("NOOP");
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return true;        
    }

    //»ñÈ¡ÓʼþÊýÁ¿ºÍ×Ö½ÚÊý(·µ»ØÊý×é)
    function getMailSum($intReturnType=2)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("STAT");
        $strLineResponse = $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        if ($intReturnType==1)
        {
            return     $this->strResponse;
        }
        else
        {
            $arrResponse = explode(" ", $this->strResponse);
            if (!is_array($arrResponse) || count($arrResponse)<=0)
            {
                $this->setMessage('STAT command response message is error', 2006);
                return false;
            }
            return array($arrResponse[1], $arrResponse[2]);
        }
    }

    //»ñȡָ¶¨ÓʼþµÃSession Id
    function getMailSessId($intMailId, $intReturnType=2)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        if (!$intMailId = intval($intMailId))
        {
            $this->setMessage('Mail message id invalid', 1005);
            return false;
        }
        $this->sendCommand("UIDL ". $intMailId);
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        if ($intReturnType == 1)
        {
            return     $this->strResponse;
        }
        else
        {
            $arrResponse = explode(" ", $this->strResponse);
            if (!is_array($arrResponse) || count($arrResponse)<=0)
            {
                $this->setMessage('UIDL command response message is error', 2006);
                return false;
            }
            return array($arrResponse[1], $arrResponse[2]);
        }
    }

    //È¡µÃij¸öÓʼþµÄ´óС
    function getMailSize($intMailId, $intReturnType=2)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("LIST ".$intMailId);
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        if ($intReturnType == 1)
        {
            return $this->strResponse;
        }
        else
        {
            $arrMessage = explode(' ', $this->strResponse);
            return array($arrMessage[1], $arrMessage[2]);
        }
    }

    //»ñÈ¡Óʼþ»ù±¾ÁбíÊý×é
    function getMailBaseList($intReturnType=2)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("LIST");
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return $this->getRespMessage($intReturnType);
    }

    //»ñȡָ¶¨ÓʼþËùÓÐÐÅÏ¢£¬intReturnTypeÊÇ·µ»ØÖµÀàÐÍ£¬1ÊÇ×Ö·û´®,2ÊÇÊý×é
    function getMailMessage($intMailId, $intReturnType=1)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        if (!$intMailId = intval($intMailId))
        {
            $this->setMessage('Mail message id invalid', 1005);
            return false;
        }
        $this->sendCommand("RETR ". $intMailId);
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return $this->getRespMessage($intReturnType);
    }

    //»ñȡijÓʼþǰָ¶¨ÐÐ, $intReturnType ·µ»ØÖµÀàÐÍ£¬1ÊÇ×Ö·û´®£¬2ÊÇÊý×é
    function getMailTopMessage($intMailId, $intTopLines=10, $intReturnType=1)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        if (!$intMailId=intval($intMailId) || !$intTopLines=int($intTopLines))
        {
            $this->setMessage('Mail message id or Top lines number invalid', 1005);
            return false;
        }
        $this->sendCommand("TOP ". $intMailId ." ". $intTopLines);
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return $this->getRespMessage($intReturnType);
    }

    //ɾ³ýÓʼþ
    function delMail($intMailId)
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        if (!$intMailId=intval($intMailId))
        {
            $this->setMessage('Mail message id invalid', 1005);
            return false;
        }
        $this->sendCommand("DELE ".$intMailId);
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return true;
    }

    //ÖØÖñ»É¾³ýµÃÓʼþ±ê¼ÇΪδɾ³ý
    function resetDeleMail()
    {
        if (!$this->getIsConnect() && $this->bolIsLogin)
        {
            return false;
        }
        $this->sendCommand("RSET");
        $this->getLineResponse();
        if (!$this->getRestIsSucceed())
        {
            return false;
        }
        return true;        
    }

 

    //---------------
    // µ÷ÊÔ²Ù×÷
    //---------------

    //Êä³ö¶ÔÏóÐÅÏ¢
    function printObject()
    {
        print_r($this);
        exit;
    }

    //Êä³ö´íÎóÐÅÏ¢
    function printError()
    {
        echo "[Error Msg] : $strMessage     <br>/n";
        echo "[Error Num] : $intErrorNum <br>/n";
        exit;
    }

    //Êä³öÖ÷»úÐÅÏ¢
    function printHost()
    {
        echo "[Host]  : $this->strHost <br>/n";
        echo "[Port]  : $this->intPort <br>/n";
        echo "[Email] : $this->strEmail <br>/n";
        echo "[Passwd] : ******** <br>/n";
        exit;
    }

    //Êä³öÁ¬½ÓÐÅÏ¢
    function printConnect()
    {
        echo "[Connect] : $this->resHandler <br>/n";
        echo "[Request] : $this->strRequest <br>/n";
        echo "[Response] : $this->strResponse <br>/n";
        exit;
    }
}

?>


<?
//²âÊÔ´úÂë
//ÀýÈ磺$o = SocketPOP3Client('ÓÊÏ䵨ַ', 'ÃÜÂë', 'POP3·þÎñÆ÷', 'POP3¶Ë¿Ú')

/*
set_time_limit(0);
$o = new SocketPOPClient('abc@126.com', '123456', 'pop.126.com', '110');
$o->popLogin();
print_r($o->getMailBaseList());
print_r($o->getMailSum(1));
print_r($o->getMailTopMessage(2, 2, 2));
$o->popLogout();
$o->closeHost();
$o->printObject();
*/
?>