欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用PHP Socket写的POP3类

程序员文章站 2023-11-10 22:58:40
查看 pop3/smtp 协议的时候想尝试一下自己写一个操作类,核心没啥,就是使用 fsockopen ,然后写入/接收数据,只实现了最核心的部分功能,当作是学习 sock...

查看 pop3/smtp 协议的时候想尝试一下自己写一个操作类,核心没啥,就是使用 fsockopen ,然后写入/接收数据,只实现了最核心的部分功能,当作是学习 socket 操作的练手。其中参考了 rfc 2449和一个国外的简单web邮件系统 uebimiau 的部分代码,不过绝对没有抄他滴,hoho,绝对原创。

复制代码 代码如下:

<?php
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]);
        }
    }

    //取得某个邮件的大小
    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);
    }

    //获取某邮件前指定行, $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();
*/
?>