热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用PHP实现POP3邮件的收取(二)

用php实现POP3收取邮件的类现在让我们来用PHP实现一个通过POP3协议收取信件的类吧,这个类中所用到的一些sock操作的函数,不另做特殊说明,请参考php的有关资料。通过这个实例,相信你也会和我一样,感觉到PHP中对于sock操作的灵活、方便和功能的强大。首先,我们来说明一下这个类中需要用到的一些内部成员变量:(这些变量应该都是对外封闭的,可
用php实现POP3收取邮件的类

现在让我们来用PHP实现一个通过POP3协议收取信件的类吧,这个类中所用到的一些sock操作的函数,不另做特殊说明,请参考php的有关资料。通过这个实例,相信你也会和我一样,感觉到PHP中对于sock操作的灵活、方便和功能的强大。

首先,我们来说明一下这个类中需要用到的一些内部成员变量:(这些变量应该都是对外封闭的,可是由于php对类的成员变量没有PRivate与publice之类的分别,只好就这么直接定义了。这是PHP的一个令人遗憾的地方。)

1.成员变量说明

class pop3
  {

    var $hostname=""; // POP主机名

    var $port=110; // 主机的POP3端口,一般是110号端口

var $timeout=5;  // 连接主机的最大超时时间 

    var $cOnnection=0; // 保存与主机的连接

    var $state="DISCONNECTED"; // 保存当前的状态 

    var $debug=0;  // 做为标识,是否在调试状态,是的话,输出调试信息

var $err_str='';  // 如果出错,这里保存错误信息

var $err_no;   //如果出错,这里保存错误号码

var $resp; // 临时保存服务器的响应信息

var $apop; // 指示需要使用加密方式进行密码验证,一般服务器不需要

var $messages; // 邮件数

var $size; //各邮件的总大小

var $mail_list; // 一个数组,保存各个邮件的大小及其在邮件服务器上序号  

var $head=array(); // 邮件头的内容,数组

var $body=array(); // 邮件体的内容,数组;

2.当然,这其中的有些变量,仅通过这样一个简单的说明并不能完全了解如何使用,下面我就逐个来说明这个类实现中的一些主要方法:
  Function pop3($server="192.100.100.1",$port=110,$time_out=5)

{$this->hostname=$server;

$this->port=$port;

$this->timeout=$time_out;

return true;
  }

熟悉面向对象编程的朋友一看就会知道,这是这个类的构造函数,在初始化这个类时,可以给出这几个最基本的参数:pop3服务器的地址,端口号,及连接服务器时的最大超时时间。一般来说,只需要给出POP3服务器的地址就行了。

Function open()
  {
  if($this->hostname=="")

  {$this->err_str="无效的主机名!!";

return false;
   }  

if ($this->debug) echo "正在打开 $this->hostname,$this->port,&$err_no, &$err_str, $this->timeout
";

if (!$this->cOnnection=fsockopen($this->hostname,$this->port,&$err_no, &$err_str, $this->timeout))
   {

$this->err_str="连接到POP服务器失败,错误信息:".$err_str."错误号:".$err_no;

return false;

}
   else
   {
   $this->getresp();

if($this->debug)        

   $this->outdebug($this->resp);

if (substr($this->resp,0,3)!="+OK")

{$this->err_str="服务器返回无效的信息:".$this->resp."请检查POP服务器是否正确";

return false;
   }

$this->state="AUTHORIZATION";

return true;

}

}

该方法不需要任何参数就可建立与POP3服务器的sock连接。该方法又用到了另一个类中的方法$this->getresp();下面是这个方法的声明:

Function getresp()

{

for($this->resp="";;)

   {

       if(feof($this->connection))

             return false;

         $this->resp.=fgets($this->connection,100);

         $length=strlen($this->resp);

         if($length>=2 && substr($this->resp,$length-2,2)=="\r\n")

         {

          $this->resp=strtok($this->resp,"\r\n");

return true;

         }
          }
      }

这个方法取得服务器端的返回信息并进行简单的处理:去掉最后的回车换行符,将返回信息保存在resp这个内部变量中。这个方法在后面的多个操作中都将用到。另外,还有个小方法也在后面的多个操作中用到:

Function outdebug($message)
  {
   echo htmlspecialchars($message)."
\n";
  }

它的作用就是把调试信息$message显示出来,并把一些特殊字符进行转换以及在行尾加上
标签,这样是为了使其输出的调试信息便于阅读和分析。

建立起与服务器的sock连接之后,就要给服务器发送相关的命令了(请参见上面的与服务器对话的过程)从上面对 POP对话的分析可以看到,每次都是发送一条命令,然后服务器给予一定的回应,如果命令的执行是对的,回应一般是以+OK开头,后面是一些描述信息,所以,我们可以做一个通过发送命令的方法:

Function command($command,$return_lenth=1,$return_code='+')
  {
   if ($this->cOnnection==0)
   {
   $this->err_str="没有连接到任何服务器,请检查网络连接";

return false;
   }

if ($this->debug)
   $this->outdebug(">>> $command");

if (!fputs($this->connection,"$command\r\n"))

{

$this->err_str="无法发送命令".$command;

return false;
   }
   else
   {

$this->getresp();

if($this->debug)

   $this->outdebug($this->resp);

if (substr($this->resp,0,$return_lenth)!=$return_code)

{

$this->err_str=$command." 命令服务器返回无效:".$this->resp;

return false;

}

  else

return true;

  }
  }

这个方法可以接受三个参数: $command--> 发送给服务器的命令; $return_lenth,$return_code ,指定从服务器的返回中取多长的值做为命令返回的标识以及这个标识的正确值是什么。对于一般的pop操作来说,如果服务器的返回第一个字符为"+",则可以认为命令是正确执行了。也可以用前面提到过的三个字符"+OK"做为判断的标识。

下面介绍的几个方法则可以按照前述收取信件的对话去理解,因为有关的内容已经在前面做了说明,因此下面的方法不做详细的说明,请参考其中的注释:

Function Login($user,$passWord) //发送用户名及密码,登录到服务器
  {

if($this->state!="AUTHORIZATION")
   {

$this->err_str="还没有连接到服务器或状态不对";

return false;
   }

if (!$this->apop) //服务器是否采用APOP用户认证
   {

if (!$this->command("USER $user",3,"+OK")) return false;

if (!$this->command("PASS $password",3,"+OK")) return false;

}

else

{

//echo $this->resp=strtok($this->resp,"\r\n");

if (!$this->command("APOP $user ".md5($this->greeting.$password),3,"+OK")) return false;

}

$this->state="TRANSACTION"; // 用户认证通过,进入传送模式

return true;
  }

Function stat() // 对应着stat命令,取得总的邮件数与总的大小
  {
  if($this->state!="TRANSACTION")
   {

$this->err_str="还没有连接到服务器或没有成功登录";

return false;
   }

if (!$this->command("STAT",3,"+OK"))
   return false;

else

{

$this->resp=strtok($this->resp," ");

$this->messages=strtok(" "); // 取得邮件总数

$this->size=strtok(" "); //取得总的字节大小

return true;
   }
  }

Function listmail($mess=null,$uni_id=null) //对应的是LIST命令,取得每个邮件的大小及序号。一般来说用到的是List命令,如果指定了$uni_id ,则使用UIDL命令,返回的是每个邮件的标识符,事实上,这个标识符一般是没有什么用的。取得的各个邮件的大小返回到类的内部变量mail_list这个二维数组里。

{
  if($this->state!="TRANSACTION")
   {

$this->err_str="还没有连接到服务器或没有成功登录";

return false;
   }

if ($uni_id)

$command="UIDL ";

else

$command="LIST ";

if ($mess)

$command.=$mess;
 

if (!$this->command($command,3,"+OK"))
   {

//echo $this->err_str;

return false;

}
   else
   {

$i=0;

$this->mail_list=array();

$this->getresp();

while ($this->resp!=".")

{ $i++;

if ($this->debug)
   {

$this->outdebug($this->resp);
   }

if ($uni_id)
   {
   $this->mail_list[$i][num]=strtok($this->resp," ");

$this->mail_list[$i][size]=strtok(" ");
   }
   else
   {
   $this->mail_list[$i]["num"]=intval(strtok($this->resp," "));

$this->mail_list[$i]["size"]=intval(strtok(" "));

}

$this->getresp();

}

return true;
   }
  }

function getmail($num=1,$line=-1) // 取得邮件的内容,$num是邮件的序号,$line是指定共取得正文的多少行。有些时候,如邮件比较大而我们只想先查看邮件的主题时是必须指定行数的。默认值$line=-1,即取回所有的邮件内容,取得的内容存放到内部变量$head,$body两个数组里,数组里的每一个元素对应的是邮件源代码的一行。

{

if($this->state!="TRANSACTION")
   {
   $this->err_str="不能收取信件,还没有连接到服务器或没有成功登录";

return false;
   }

if ($line<0)

$command="RETR $num";

else

$command="TOP $num $line";

if (!$this->command("$command",3,"+OK"))

return false;

else
   {

$this->getresp();

$is_head=true;

while ($this->resp!=".") // . 号是邮件结束的标识
   {

if ($this->debug)

$this->outdebug($this->resp);

if (substr($this->resp,0,1)==".")

$this->resp=substr($this->resp,1,strlen($this->resp)-1);

if (trim($this->resp)=="") // 邮件头与正文部分的是一个空行

$is_head=false;

if ($is_head)

$this->head[]=$this->resp;

else

$this->body[]=$this->resp;

$this->getresp();

}

return true;
   }
  } // end function

function dele($num) // 删除指定序号的邮件,$num 是服务器上的邮件序号

{

if($this->state!="TRANSACTION")
   {

$this->err_str="不能删除远程信件,还没有连接到服务器或没有成功登录";

return false;
   }

if (!$num)
   {

$this->err_str="删除的参数不对";

return false;
   }

if ($this->command("DELE $num ",3,"+OK"))
   return true;

else

return false;
  }

通过以上几个方法,我们已经可以实现邮件的查看、收取、删除的操作,不过别忘了最后要退出,并关闭与服务器的连接,调用下面的这个方法:

Function Close()
  {

if($this->connection!=0)
   {

if($this->state=="TRANSACTION")

$this->command("QUIT",3,"+OK");

fclose($this->connection);

   $this->cOnnection=0;

$this->state="DISCONNECTED";
   }

}


推荐阅读
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
author-avatar
贾章鱼_977
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有