通行证: 用户 密码 域名空间  下载中心 社区论坛 信息公告 MY小屋
联系我们
设为首页
加入收藏

 

QQ,ASP,PHP,JSP,XML,SQL,.Net,编程 程序 网页图象 建站经验 私服
首页 | 新闻资讯 | 编程开发 | 网页设计 | 图形图象 | 网络媒体 | 网站模板 | 数 据 库 | 投稿
论坛 | 操作系统 | 系统优化 | 网络安全 | 黑客技术 | 硬件学堂 | 硬件报价 | 服 务 器 | 地图
专题 | 应用软件 | 聊天通讯 | Q Q 专栏 | 建站经验 | 在线工具 | 站长Club | 注 册 表 | 旧版
社会 | 游戏娱乐 | 设计欣赏 | 疑难解答 | 社区论坛 | 韩国素材 | 素材图库 | 广告服务 | 服务
当前位置:首页>>编程开发>>PHP专区>>正文 新版上线![旧版]
注:打开慢时请稍等

用PHP实现POP3邮件的收取

http://www.iyit.net  日期:2006-5-25 10:32:03  来源:本站整理转载   点击:
参加讨论


POP协议简介

  本文简要说明了通过POP3协议收取邮件、MIME邮件的解码的原理;针对收取和MIME解码,提供了两个实用的PHP类,并提供了使用的样例。分为邮件收取、MIME解码两个部分。这里我们先向您介绍邮件的收取,解码部分会在以后的文章中为各位详细的介绍,敬请关注。

  

  现在Internet上最大的应用应该是非Email莫属了,我们每天都习惯于每天通过Email进行交流,各大网站也几乎都推出了自己的基于WEB的免费邮件系统。在本文里,笔者将介绍一些Email实现的一些原理。同时我们假设你对于PHP的编程有一定的基础,对于TCP/IP协议也有一定的了解。

POP 协议简介
  POP的全称是 Post Office Protoco ,即邮局协议,用于电子邮件的接收,现在常 用的是第三版 ,简称为 POP3。通过POP协议,客户机登录到服务器上后,可以对自己的邮件进行删除,或是下载到本地,下载后,电子邮件客户软件就可以在本地对邮件进行修改、删除等。另外一种用于接收信件的邮件是 IMAP 协议,现在发展很快,在本文中,我们暂不讨论。

  POP服务器一般使用的是TCP的110号端口,如果你用的是Foxmail的话,在其收邮件的时候,你可以看到其信息提示窗口有这么一些命令:

  “正在连接到 62.123.23.123:110";

  "USER BOSS_CH";

  "PASS..............";

  下面让我们来看一段 与 POP3 服务器对话的实录:

  telenet pop.china.com 110

  +OK AIMC POP service (mail2.china.com) is ready.

  USER boss_ch

  +OK Please enter password for user <boss_ch>.

  PASS ******

  +OK boss_ch has 1 messages (750 octets)

  STAT

  +OK 1 750

  LIST

  +OK 1 messages (750 octets)

  1 750

  RETR 1

  +OK 750 octets

  Received: from smtp2.ptt.js.cn([202.102.24.37]) by china.com(JetMail 2.5.3.0)

  with SMTP id jm4839cc4227; Sat, 23 Sep 2000 05:31:21 -0000

  Received: from chenjunqing ([61.155.120.6]) by smtp2.ptt.js.cn

  (Netscape Messaging Server 4.15) with SMTP id G1BRHJ03.V07 for

  <boss_ch@china.com>; Sat, 23 Sep 2000 13:34:31 +0800

  Date: Sat, 23 Sep 2000 13:34:18 +0800

  From: =?ISO-8859-1?Q?=B3=C2=BF=A1=C7=E5?= <Boss_ch@netease.com>

  To: boss_ch@china.com <boss_ch@china.com>

  Subject: =?ISO-8859-1?Q?=D3=CA=BC=FE=CA=BE=C0=FD?=

  X-mailer: FoxMail 3.1 [cn]

  Mime-Version: 1.0

  Content-Type: text/plain; charset="GB2312"

  Content-Transfer-Encoding: 8bit

  Message-ID: <G1BRHJ03.V07@smtp2.ptt.js.cn>

  您好!

    这是一个邮件的小示例

  QUIT

  +OK Pop server at <mail2.china.com> signing off.

  以下对几个常用的POP3命令作一个简单的介绍 :

  命令    参数    状态    描述

  ------------------------------------------

  USER    username  认可    此命令与下面的pass命令若成功,将导致状态转换

  PASS    password  认可

  APOP    Name,Digest 认可    Digest是MD5消息摘要

  ------------------------------------------

  STAT    None    处理    请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数

  UIDL    [Msg#]   处理    返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的

  LIST    [Msg#]   处理    返回邮件数量和每个邮件的大小

  RETR    [Msg#]   处理    返回由参数标识的邮件的全部文本

  DELE    [Msg#]   处理    服务器将由参数标识的邮件标记为删除,由quit命令执行

  RSET    None    处理    服务器将重置所有标记为删除的邮件,用于撤消DELE命令

  TOP    [Msg#]    处理    服务器将返回由参数标识的邮件前n行内容,n必须是正整数

  NOOP    None    处理    服务器返回一个肯定的响应,不做任何操作。

  ------------------------------------------

  QUIT    None    更新 退出
用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<BR>";

  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)."<br>\n";

  }

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

  建立起与服务器的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";

   }

  }
应用实例

  POP3收取邮件的类在前面的文章中已经给大家做了详细的介绍,下面我们来看看如何应用这个类:

  <?

  include("pop3.inc.php");

  $host="pop.china.com";

  $user="boss_ch";

  $pass="026007";

  $rec=new pop3($host,110,2);

  if (!$rec->open()) die($rec->err_str);

  echo "open ";

  if (!$rec->login($user,$pass)) die($rec->err_str);

  echo "login";

  if (!$rec->stat()) die($rec->err_str);

  echo "共有".$rec->messages."封信件,共".$rec->size."字节大小<br>";

  

  if ($rec->messages>0)

   {

   if (!$rec->listmail()) die($rec->err_str);

   echo "有以下信件:<br>";

   for ($i=1;$i<=count($rec->mail_list);$i++)

   {

   echo "信件".$rec->mail_list[$i][num]."大小:".$rec->mail_list[$i][size]."<BR>";

   }

   $rec->getmail(1);

   echo "邮件头的内容:<br>";

   for ($i=0;$i<count($rec->head);$i++)

   echo htmlspecialchars($rec->head[$i])."<br>\n";

   echo "邮件正文 :<BR>";

   for ($i=0;$i<count($rec->body);$i++)

   echo htmlspecialchars($rec->body[$i])."<br>\n";

   }

  $rec->close();

  ?>

  如果你把pop3类中的debug设为true的话,你还可以看到程序与pop3服务器是如何对话的,用于正在调试的程序来说,这样显得更为直观。



  小结

  从以上的这个实例我们可以看到PHP真的是网站开发的一个功能非常强大的工具,但是也可以感觉到,PHP做为一种混合形的语言,其面对对象的开发与其它的工具java相比还存在不少让人遗憾的地方。这个pop类的实现也还有不少需要改进之处,欢迎各位同仁们指导。


编辑:黑鹰 [发送给好友] [打印本页] [关闭窗口] [返回顶部]
上一篇:用PHP实现POP3邮件的解码
下一篇:仿OfficeXP风格的左边版面列表
转载请注明来源:www.iyit.net
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。

 相关文章
初学者必读 PHP常用开发工具分析 最令PHP初学者头痛的十四个问题  Win2003下APACHE+PHP5+MYSQL4+PHPMYADM
Win2000下PHP服务器安装攻略 在Windows中安装Apache2和PHP4的权威指 在WIN平台上让你 Apache 2.0.45支持PHP
PHP 在Windows 2003 Enterprise Server 虚拟主机中对PHP的特殊设置 透析PHP的配置文件
apache2.0.39 php4.2.3在windowsXP下模 PHP安装攻略:常见问题解答 在Windows下面从源代码编译PHP的步骤
Apache 2.0.35和PHP 4.3-Dev的集成 RedHat上安装apache+gd1.8.3+php4+tomc 把PHP安装为Apache DSO
phpMyAdmin 2.x.x - 文档(安装及配置) PHP的编译选项说明 php3.ini及php.ini配置文件各选项的说明
超级服务器apache+mysql+php+ssl之完全 PHP4.04在英文win2000下的安装 PHP4.03在linux下的安装
PHP4.04在win98下的安装 PHP设计聊天室步步通 十天学会php之第十天
最新更新 热点排行 推荐新闻
初学者必读 PHP常用开发工具分析
最令PHP初学者头痛的十四个问题 
Win2003下APACHE+PHP5+MYSQL4+PHPMYAD
Win2000下PHP服务器安装攻略
在Windows中安装Apache2和PHP4的权威指
更新了本站链接,请各位站长注意!
初学者必读 PHP常用开发工具分析
最令PHP初学者头痛的十四个问题 
Win2003下APACHE+PHP5+MYSQL4+PHPMYAD
Win2000下PHP服务器安装攻略
在Windows中安装Apache2和PHP4的权威指
在WIN平台上让你 Apache 2.0.45支持PH
PHP 在Windows 2003 Enterprise Serve
Zend Optimizer 配置指南
虚拟主机中对PHP的特殊设置
判断字符串emailAddr是否为合法的emai
PHP控制语句 
如何正确理解 PHP 的错误信息
PHP的十个高级技巧 
PHP新手上路(一) 
优秀公益广告作品欣赏(8)
java数据类型转换
Windows XP专业版IIS连接数的更改
新开放QQ免费挂级网站
优秀公益广告作品欣赏(7)
免费在QQ上看在线电影电视听音乐
WEB服务器配置全攻略(三)
QQ珊瑚虫外挂4.0版本发布!
免费把QQ炫铃设为本机QQ的系统提示音
Office2007简体中文版浮出水面 美图抢
如何在Win20003中更好的玩游戏
QQ收费头像免费使用的方法 
微软将在华推分期付款,充值卡PC 可低价
 AMD处理器AM2测试 风扇竟运行7分钟
exeplorer.exe错误的问题的总结、解决
ASP.NET 2.0 中的异步页功能应用
硬盘坏道修复及数据恢复宝典
免费登录搜索引擎入口大全
搜索引擎注册九大秘法
小心摄像头成为黑客偷窥你的眼睛
 友情链接
设置首 页 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接
Copyrights © 2004-2006 iYiT.Net All Rights Reserved.
网站合作、广告联系QQ:147007642、466949678
易特网络技术 点击这里给我发消息