使用PHP Socket写的POP3类


Posted in PHP onOctober 30, 2013

查看 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(); 
*/ 
?>
PHP 相关文章推荐
PHP三层结构(上) 简单三层结构
Jul 04 PHP
检查php文件中是否含有bom的函数
May 31 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
Jun 24 PHP
php实现最简单的MVC框架实例教程
Sep 08 PHP
php+xml实现在线英文词典之添加词条的方法
Jan 23 PHP
CodeIgniter针对lighttpd服务器URL重写的方法
Jun 10 PHP
浅谈php的优缺点
Jul 14 PHP
WordPress中使主题支持小工具以及添加插件启用函数
Dec 22 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
Sep 11 PHP
PHP单例模式简单用法示例
Jun 23 PHP
PHP并发查询MySQL的实例代码
Aug 09 PHP
基于laravel Request的所有方法详解
Sep 29 PHP
腾讯QQ微博API接口获取微博内容
Oct 30 #PHP
FireFox浏览器使用Javascript上传大文件
Oct 30 #PHP
php使用ICQ网关发送手机短信
Oct 30 #PHP
PHP分页详细讲解(有实例)
Oct 30 #PHP
php预定义变量使用帮助(带实例)
Oct 30 #PHP
调整PHP的性能
Oct 30 #PHP
PHP数据过滤的方法
Oct 30 #PHP
You might like
在PHP中实现Javascript的escape()函数代码
2010/08/08 PHP
使用ThinkPHP自带的Http类下载远程图片到本地的实现代码
2011/08/02 PHP
PHP数据类型之布尔型的介绍
2013/04/28 PHP
php用正则表达式匹配URL的简单方法
2013/11/12 PHP
PHP循环结构实例讲解
2014/02/10 PHP
linux平台编译安装PHP7并安装Redis扩展与Swoole扩展实例教程
2016/09/30 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
javascript 页面划词搜索JS
2009/09/28 Javascript
jquery ui dialog实现弹窗特效的思路及代码
2013/08/03 Javascript
提取字符串中年月日的函数代码
2013/11/05 Javascript
jquery、js调用iframe父窗口与子窗口元素的方法整理
2014/07/31 Javascript
JS实现获取键盘按下的按键并显示在页面上的方法
2015/11/04 Javascript
微信小程序实现添加手机联系人功能示例
2017/11/30 Javascript
微信小程序实现导航栏选项卡效果
2020/06/19 Javascript
React学习笔记之高阶组件应用
2018/06/02 Javascript
vue.js 中使用(...)运算符报错的解决方法
2018/08/09 Javascript
vue elementUI tree树形控件获取父节点ID的实例
2018/09/12 Javascript
three.js实现圆柱体
2018/12/30 Javascript
Jquery实现无缝向上循环滚动列表的特效
2019/02/13 jQuery
vscode中eslint插件的配置(prettier配置无效)
2019/09/10 Javascript
详解Vue数据驱动原理
2020/11/17 Javascript
JavaScript实现缓动动画
2020/11/25 Javascript
[52:27]2018DOTA2亚洲邀请赛 3.31 小组赛B组 paiN vs Secret
2018/04/01 DOTA
Python实现抓取百度搜索结果页的网站标题信息
2015/01/22 Python
Python利用socket模块开发简单的端口扫描工具的实现
2021/01/27 Python
英国鞋类及配饰零售商:Kurt Geiger
2017/02/04 全球购物
网络通讯中,端口有什么含义,端口的取值范围
2012/11/23 面试题
旅游市场营销方案
2014/03/09 职场文书
《长征》教学反思
2014/04/27 职场文书
公务员培的训心得体会
2014/09/01 职场文书
晋江市人民政府党组群众路线教育实践活动整改方案
2014/10/25 职场文书
幼儿园大班个人总结
2015/02/28 职场文书
房地产销售助理岗位职责
2015/04/14 职场文书
2015年销售部工作总结范文
2015/04/27 职场文书
2015秋季幼儿园开学通知
2015/07/16 职场文书
AudioContext 实现音频可视化(web技术分享)
2022/02/24 Javascript