用PHP实现POP3邮件的解码

白泽语
2023-12-01

原文内容没有变化,在公司快消化了两个系统了,所以打算自己写一个功能还可以的个人系统,我知道网上很多,我也收集了好几个,但是想看看自己能不能做出来,好好加油吧,在筹备的过程中遇到了邮件这样的问题,所以花了点时间研究了一番,网上找到的好内容,拿出来分享一下

引用网址:http://www.china-askpro.com/msg36/qa99.shtml

 

编号:QA003599
建立日期: 2000年11月28日 最后修改日期:2000年11月28日
所属类别:
其他语言 - Internet编程

文章:

    标题:用PHP实现POP3邮件的解码
    (作者:陈俊清 2000年10月24日 15:08)
   
初步认识邮件的源文件

    本文简要说明了通过POP3协议收取邮件、MIME邮件的解码的原理;针对收取和MIME解码,提供了两个实用的PHP类,并提供了使用的样例。分为邮件收取、MIME解码两个部分。我们已经向您介绍过了邮件的收取,现在让我们来为您介绍本文的解码部。
    在上一篇里,我们已经完成了一个用PHP通过POP3收取邮件的实例,可是在使用这个类的时候,相信你已经看到了,很多的邮件收下来是一堆乱码,自己根本看不懂!是的。现在的邮件大部分都已经经过了编码,需要一个解码的过程才能变成我们习惯的文字、图片、或是其它的附件。
    邮件的源文件
    首先,我们来看一段简单的邮件的源文件:(在Foxmail中,选中邮件,点选“查看源文件”就会看到这样的些内容了)
      From: <boss_ch@netease.com >
      To: <boss_ch@china.com >
      Subject: =?gb2312?B?xOO6w6Oh?=
      Date: Sun, 8 Oct 2000 20:28:45 +0800
      MIME-Version: 1.0
      Content-Type: multipart/alternative;
       boundary="----=_NextPart_000_0007_01C03166.5B1E9510"
      X-Priority: 3
      X-MSMail-Priority: Normal
      X-Mailer: Microsoft Outlook Express 5.00.2919.6700
      X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700
      This is a multi-part message in MIME format.
      ------=_NextPart_000_0007_01C03166.5B1E9510
      Content-Type: text/plain;
       charset="gb2312"
      Content-Transfer-Encoding: base64
      w7vT0MLSwuuwyaO/DQo=
      ------=_NextPart_000_0007_01C03166.5B1E9510
      Content-Type: text/html;
       charset="gb2312"
      Content-Transfer-Encoding: base64
      PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv
      L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PWdi
      MjMxMiIgaHR0cC1lcXVpdj1Db250ZW50LVR5cGU+DQo8TUVUQSBjb250ZW50PSJNU0hUTUwgNS4w
      MC4yOTIwLjAiIG5hbWU9R0VORVJBVE9SPg0KPFNUWUxFPjwvU1RZTEU+DQo8L0hFQUQ+DQo8Qk9E
      WSBiZ0NvbG9yPSNmZmZmZmY+DQo8RElWPjxGT05UIHNpemU9Mj7Du9PQwtLC67DJo788L0ZPTlQ+
      PC9ESVY+PC9CT0RZPjwvSFRNTD4NCg==
      ------=_NextPart_000_0007_01C03166.5B1E9510-
    这样的一段邮件,我想没有人能看得懂的。不要急,我们来仔细看看这些内容。
      From: <boy@netease.com >
      To: <boss_ch@china.com >
    这个是好理解的,邮件由boy@netease.com 发送,收件人是boss_ch@china.com ,这些标签的含义我们基本可从字面上理解到,像Date:Sun, 8 Oct 2000 20:28:45 +0800表示的是时间,X-Priority: 3表示的是邮件的优先级,X-Mailer: Microsoft Outlook Express 5.00.2919.6700表示的是邮件发送器的名字,这里用的是Outllook 5,不过,这些东西跟邮件的内容是没有很大关系的。我们不需要深究。
   
MIME 编码方式简介

    MIME 编码方式简介
    Subject: =?gb2312?B?xOO6w6Oh?=
    这里是邮件的主题,可是因为编码了,我们看不出是什么内容,其原来的文本是: “你好!”我们先看看 MIME 编码的两种方法。
    对邮件进行编码最初的原因是因为 Internet 上的很多网关不能正确传输8 bit 内码的字符,比如汉字等。编码的原理就是把 8 bit 的内容转换成 7 bit 的形式以能正确传输,在接收方收到之后,再将其还原成 8 bit 的内容。
    MIME 是“多用途网际邮件扩充协议”的缩写,在 MIME 协议之前,邮件的编码曾经有过 UUENCODE 等编码方式 ,但是由于 MIME 协议算法简单,并且易于扩展,现在已经成为邮件编码方式的主流,不仅是用来传输 8 bit 的字符,也可以用来传送二进制的文件 ,如邮件附件中的图像、音频等信息,而且扩展了很多基于MIME 的应用。从编码方式来说,MIME 定义了两种编码方法Base64与QP(Quote-Printable) :
    Base 64 是一种通用的方法,其原理很简单,就是把三个Byte的数据用 4 个Byte表示,这样,这四个Byte 中,实际用到的都只有前面6 bit,这样就不存在只能传输 7bit 的字符的问题了。Base 64的缩写一般是“B”,像这封信中的Subject 就是用的 Base64 编码。
    另一种方法是QP(Quote-Printable) 方法,通常缩写为“Q”方法,其原理是把一个 8 bit 的字符用两个16进制数值表示,然后在前面加“=”。所以我们看到经过QP编码后的文件通常是这个样子:=B3=C2=BF=A1=C7=E5=A3=AC=C4=FA=BA=C3=A3=A1。
    在 PHP 里,系统有两个函数可以很方便地实现解码:base64_decode()与quoted_printable_decode(),前者可用于base64 编码的解码,后者是用于 QP 编码方法的解码。
    现在我们再来看看Subject: =?gb2312?B?xOO6w6Oh?= 这一主题的内容,这不是一段完整的编码,只有部分是编码了的,这个部分用 =? ?= 两个标记括起来,=? 后面说明的是这段文字的字符集是 GB2312 ,然后一个 ? 后面的一个 B 表示的是用的 Base64编码。通过这段分析,我们来看一下这个 MIME 解码的函数:(该函数由 PHPX.COM 站长 Sadly 提供,本人将其放入一个类中,并做了少量的修改,在此致谢)
      function decode_mime($string) {
       $pos = strpos($string, '=?');
       if (!is_int($pos)) {
         return $string;
       }
       $preceding = substr($string, 0, $pos); // save any preceding text
       $search = substr($string, $pos+2); /* the mime header spec says this is
     the longest a single encoded word can be */
       $d1 = strpos($search, '?');
       if (!is_int($d1)) {
         return $string;
       }
       $charset = substr($string, $pos+2, $d1); //取出字符集的定义部分
       $search = substr($search, $d1+1); //字符集定义以后的部分=>$search;
       $d2 = strpos($search, '?');
       if (!is_int($d2)) {
         return $string;
       }
       $encoding = substr($search, 0, $d2); 两个? 之间的部分编码方式 :q
     或 b 
       $search = substr($search, $d2+1);
       $end = strpos($search, '?='); //$d2+1 与 $end 之间是编码了 的内容:=>
    $endcoded_text;
       if (!is_int($end)) {
         return $string;
       }
       $encoded_text = substr($search, 0, $end);
       $rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text)+6)); //+6 是前面去掉的 =????= 六个字符
       switch ($encoding) {
       case 'Q':
       case 'q':
         //$encoded_text = str_replace('_', '%20', $encoded_text);
         //$encoded_text = str_replace('=', '%', $encoded_text);
         //$decoded = urldecode($encoded_text);
       $decoded=quoted_printable_decode($encoded_text);
         if (strtolower($charset) == 'windows-1251') {
         $decoded = convert_cyr_string($decoded, 'w', 'k');
         }
         break;
       case 'B':
       case 'b':
         $decoded = base64_decode($encoded_text);
         if (strtolower($charset) == 'windows-1251') {
         $decoded = convert_cyr_string($decoded, 'w', 'k');
         }
         break;
       default:
         $decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text. '?=';
         break;
       }
       return $preceding . $decoded . $this->decode_mime($rest);
      }
    这个函数用了递归的方法来实现一段包含有如上的 Subject 段的字符的解码。程序中已经加上了注释。相信有点PHP 编程基础的人都能够看得明白。该函数也是调用的base64_decode()与quoted_printable_decode()两个系统函数实现的解码,但是需要对邮件源文件进行大量的字符串的分析。不过,PHP 的字符串操作可以算是所有语言里最为方便自由的。函数的最后return $preceding . $decoded . $this->decode_mime($rest); 实现递归解码,因为这个函数实际上是放在后面要介绍的一个 MIME解码的类中的,所以用了 $this->decode_mime($rest)这种形式的调用方法。
    下面我们来看正文。这里关系到 MIME 的一些头信息,我们先做一个简单的介绍( 如果读者有兴趣了解更多的内容,请参考 MIME 的官方文档)。
      MIME-Version: 1.0
      表示使用的 MIME 的版本号,一般是1.0;
      Content-Type: 定义了正文的类型,我们实际上是通过这个标识来知道正文内是什么类型的文件,比如:text/plain 表示的是无格式的文本正文,text/html 表示的 Html 文档,image/gif 表示的是 gif 格式的图片等等。在本文中特别要说明一下的是邮件中常用到的复合类型。multipart 类型表示正文是由多个部分组成的,后面的子类型
    说明的是这些部分之间的关系,邮件中用到的三个类型有,multipart/alternative:表示正文由两个部分组成,可以选择其中的任意一个。主要作用是在征文同时有 text 格式和 html 格式时,可以在两个正文中选择一个来显示,支持 html 格式的邮件客户端软件一般会显示其 HTML 正文,而不支持的则会显示其 Text 正文;multipart/mixed
    :表示文档的多个部分是混合的,指正文与附件的关系。如果邮件的 MIME 类型是multipart/mixed,即表示邮件带有附件;multipart/related :表示文档的多个部分是相关的,一般用来描述 Html 正文与其相关的图片。
    这些复合类型又是可以嵌套使用的,比如说一个带有附件的邮件,同时有 html 与text 两种格式的正文,则邮件的结构是:
      Content-Type: multipart/mixed
       部分一:
       Content Type : multipart/alternative:
       Text 正文;
       Html 格式的正文 
      部分二:
       附件
      邮件结束符;
    由于复合类型由多个部分组成,因此,需要一个分隔符来分隔这多个部分,这就是上面的邮件源文件中的boundary="----=_NextPart_000_0007_01C03166.5B1E9510"所描述的,对于每一个Contect type :multipart/* 的内容,都会有这么一个说明,表示多个部分之间的分隔,这个分隔符是正文中不可能出现的一串古字符的组合,在文档中,以 "--" 加上这个boundary 来表示一个部分的开始,在文档的结束,以"--"加boundary再在最后加上 "--" 来表示文档的结束。由于复合类型是可以嵌套使用的,因此,邮件中可能会多个 boundary 。
    还有一个最重要的 MIME 头标签:
      Content-Transfer-Encoding: base64 它表示了这个部分文档的编码方式,也就是我们上面所介绍的Base64或QP(Quote-Printable)。我们只有识别了这个说明,才能用正确的解码方式实现对其解码。
    限于篇幅,对于 MIME 的介绍就只说到这里。下面我将给出一个解码MIME邮件的类,并对其做简要说明。
   
实现 MIME 解码的类

    一个实现 MIME 解码的类
    该类实现解码的方法是 decode($head=null,$body=null,$content_num=-1),为了处理上的方便,要求输入的是两个字符数组,在我们的上篇中,所用到的POP类所收取得到的就是两个这样的数组,一个是邮件头内容,一个是邮件的正文内容。限于篇幅,不对其做详细的说明,其实现思想跟本文上篇中所介绍的POP类类似。请参考其中的注释。
    该类中用到了大量的正则表达式的操作,对此不熟悉的读者,请参考正则表达式的有关资料。
      class decode_mail
      {
      var $from_name;var $to_name;var $mail_time;var $from_mail;var $to_mail;
      var $reply_to;var $cc_to;var $subject;
      // 解码后的邮件头部分的信息:
      var $body;
      // 解码后得到的正文数据,为一个数组。
      var $body_type; // 正文类型
      var $tem_num=0;
      var $get_content_num=0;
      var $body_temp=array();
      var $body_code_type;
      var $boundary;
      // 以上是一些方法中用到的一些全局性的临时变量,由于PHP不能做到良好的封装,所以只能放在这里定义
      var $err_str; // 错误信息
      var $debug=0; // 调试标记
      var $month_num=array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,
      "Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12); // 把英文月份转换成数字表示的月份
      function decode($head=null,$body=null,$content_num=-1) // 调用的主方法,
    $head 与 $body 是两个数组,$content_num 表示的是当正文有多个部分的时候,只取出指定部分的内容以提高效率,默认为 -1 ,表示解码全部内容,如果解码成功,该方法返回 true
      {
       if (!$head and !$body)
       {
       $this->err_str="没有指定邮件的头与内容!!";
       return false;
       }
      if (gettype($head)=="array")
       {
       $have_decode=true;
       $this->decode_head($head);
       }
      if (gettype($body)=="array")
       {
       $this->get_content_num=$content_num;
       $this->body_temp=$body;
       $have_decode=true;
       $this->decode_body();
       unset($this->body_temp);
       }
      if (!$have_decode)
       {
       $this->err_str="传递的参数不对,用法:new decode_mail(head,body) 两个参数都是数组";
       return false;
       }
      }
      function decode_head($head) // 邮件头内容 的解码,取出邮件头中有意义的内容
      {
       $i=0;
       $this->from_name=$this->to_name=$this->mail_time=$this->from_mail=$this->
       to_mail=$this->reply_to=$this->cc_to=$this->subject="";
       $this->body_type=$Sthis->boundary=$this->body_code_type="";
       while ($head[$i])
       {
       if (strpos($head[$i],"=?"))
       $head[$i]=$this->decode_mime($head[$i]);  //如果有编码的内容,则进行解码,解码函数是上文所介绍的 decode_mime()
       $pos=strpos($head[$i],":");
       $summ=substr($head[$i],0,$pos);
       $content=substr($head[$i],$pos+1);  //将邮件头信息的标识与内容分开
       if ($this->debug) echo $summ.":----:".$content."<BR>";
       switch (strtoupper($summ))
       {
       case "FROM": // 发件人地址及姓名(可能没有姓名,只有地址信息)
       if ($left_tag_pos=strpos($content,"<"))
       {
       $mail_lenth=strrpos($content,">")-$left_tag_pos-1;
       $this->from_name=substr($content,0,$left_tag_pos);
       $this->from_mail=substr($content,$left_tag_pos+1,$mail_lenth);
       if (trim($this->from_name)=="") $this->from_name=$this->from_mail;
       else
       if (ereg("[/"|/']([^/'/"]+)[/'|/"]",$this->from_name,$reg))
       $this->from_name=$reg[1];
       }
       else
       {
       $this->from_name=$content;
       $this->from_mail=$content;
       //没有发件人的邮件地址
       }
       break;
       case "TO": //收件人地址及姓名(可能 没有姓名)
       if ($left_tag_pos=strpos($content,"<"))
       {
       $mail_lenth=strrpos($content,">")-$left_tag_pos-1;
       $this->to_name=substr($content,0,$left_tag_pos);
       $this->to_mail=substr($content,$left_tag_pos+1,$mail_lenth);
       if (trim($this->to_name)=="") $this->to_name=$this->to_mail;
       else
       if (ereg("[/"|/']([^/'/"]+)[/'|/"]",$this->to_name,$reg))
       $this->to_name=$reg[1];
       }
       else
       {
       $this->to_name=$content;
       $this->to_mail=$content;
       //没有分开收件人的邮件地址
       }
       break;
       case "DATE" : //发送日期,为了处理方便,这里返回的是一个 Unix 时间戳,可以用date("Y-m-d",$this->mail_time) 来得到一般格式的日期
       $content=trim($content);
       $day=strtok($content," ");
       $day=substr($day,0,strlen($day)-1);
       $date=strtok(" ");
       $month=$this->month_num[strtok(" ")];
       $year=strtok(" ");
       $time=strtok(" ");
       $time=split(":",$time);
       $this->mail_time=mktime($time[0],$time[1],$time[2],$month,$date,$year);
    
       break;
       case "SUBJECT":  //邮件主题
       $this->subject=$content;
       break;
       case "REPLY_TO": // 回复地址(可能没有)
       if (ereg("<([^>]+)>",$content,$reg))
       $this->reply_to=$reg[1];
       else $this->reply_to=$content;
       break;
       case "CONTENT-TYPE": // 整个邮件的 Content类型, eregi("([^;]*);",$content,$reg);
       $this->body_type=trim($reg[1]);
       if (eregi("multipart",$content)) // 如果是 multipart 类型,取得 分隔符
    
       {
       while (!eregi('boundary=/"(.*)/"',$head[$i],$reg) and $head[$i])
       $i++;
       $this->boundary=$reg[1];
       }
       else //对于一般的正文类型,直接取得其编码方法
       {
       while (!eregi("charset=[/"|/'](.*)[/'|/"]",$head[$i],$reg))
       $i++;
       $this->body_char_set=$reg[1];
       while (!eregi("Content-Transfer-Encoding:(.*)",$head[$i],$reg))
       $i++;
       $this->body_code_type=trim($reg[1]);
       }
       break;
       case "CC": //抄送到。。
       if (ereg("<([^>]+)>",$content,$reg))
       $this->cc_to=$reg[1];
       else
       $this->cc_to=$content;
       default:
       break;
       } // end switch
      
       $i++;
       } // end while
      
       if (trim($this->reply_to)=="")  //如果没有指定回复地址,则回复地址为发送人地址
       $this->reply_to=$this->from_mail;
      }// end function define
      function decode_body() //正文的解码,其中用到了不少邮件头解码所得来的信息
      {
      $i=0;
      if (!eregi("multipart",$this->body_type)) // 如果不是复合类型,可以直接解码
       {
       $tem_body=implode($this->body_temp,"/r/n");
       switch (strtolower($this->body_code_type)) // body_code_type ,正文的编
    码方式,由邮件头信息中取得
       {case "base64":
       $tem_body=base64_decode($tem_body);
       break;
       case "quoted-printable":
       $tem_body=quoted_printable_decode($tem_body);
       break;
       }
       $this->tem_num=0;
       $this->body=array();
       $this->body[$this->tem_num][content_id]="";
       $this->body[$this->tem_num][type]=$this->body_type;
       switch (strtolower($this->body_type))
       {
       case "text/html":
       $this->body[$this->tem_num][name]="超文本正文";
       break;
       case "text/plain":
       $this->body[$this->tem_num][name]="文本正文";
       break;
       default:
       $this->body[$this->tem_num][name]="未知正文";
       }
      
       $this->body[$this->tem_num][size]=strlen($tem_body);
       $this->body[$this->tem_num][content]=$tem_body;
       unset($tem_body);
       }
       else // 如果是复合类型的
       {
       $this->body=array();
       $this->tem_num=0;
       $this->decode_mult($this->body_type,$this->boundary,0);  //调用复合类型的解码方法
       }
      }
      function decode_mult($type,$boundary,$begin_row) // 该方法用递归的方法实现复合类型邮件正文的解码,邮件源文件取自于 body_temp 数组,调用时给出该复合类型的类型、分隔符及在body_temp 数组中的开始指针
      {
      $i=$begin_row;
      $lines=count($this->body_temp);
      while ($i<$lines) // 这是一个部分的结束标识;
       {
       while (!eregi($boundary,$this->body_temp[$i]))//找到一个开始标识
       $i++;
       if (eregi($boundary."--",$this->body_temp[$i]))
       {
       return $i;
       }
       while (!eregi("Content-Type:([^;]*);",$this->body_temp[$i],$reg ) and $
    this->body_temp[$i])
       $i++;
       $sub_type=trim($reg[1]); // 取得这一个部分的 类型是milt or text ....
       if (eregi("multipart",$sub_type))// 该子部分又是有多个部分的;
       {
       while (!eregi('boundary=/"([^/"]*)/"',$this->body_temp[$i],$reg) and $t
    his->body_temp[$i])
       $i++;
       $sub_boundary=$reg[1];// 子部分的分隔符;
       $i++;
       $last_row=$this->decode_mult($sub_type,$sub_boundary,$i);
       $i=$last_row;
       }
       else
       {
       $comm="";
       while (trim($this->body_temp[$i])!="")
       {
       if (strpos($this->body_temp[$i],"=?"))
       $this->body_temp[$i]=$this->decode_mime($this->body_temp[$i]);
       if (eregi("Content-Transfer-Encoding:(.*)",$this->body_temp[$i],$reg))
       $code_type=strtolower(trim($reg[1])); // 编码方式
       $comm.=$this->body_temp[$i]."/r/n";
       $i++;
       } // comm 是编码的说明部分
       if (eregi('name=[/"]([^/"]*)[/"]',$comm,$reg))
       $name=$reg[1];
       if (eregi("Content-Disposition:(.*);",$comm,$reg))
       $disp=$reg[1];
       if (eregi("charset=[/"|/'](.*)[/'|/"]",$comm,$reg))
       $char_set=$reg[1];
       if (eregi("Content-ID:[ ]*/<(.*)/>",$comm,$reg)) // 图片的标识符。
       $content_id=$reg[1];
      
       $this->body[$this->tem_num][type]=$sub_type;
       $this->body[$this->tem_num][content_id]=$content_id;
       $this->body[$this->tem_num][char_set]=$char_set;
       if ($name)
       $this->body[$this->tem_num][name]=$name;
       else
       switch (strtolower($sub_type))
       {
       case "text/html":
       $this->body[$this->tem_num][name]="超文本正文";
       break;
       case "text/plain":
       $this->body[$this->tem_num][name]="文本正文";
       break;
       default:
       $this->body[$this->tem_num][name]="未知正文";
       }
      
      
       // 下一行开始取回正文
       if ($this->get_content_num==-1 or $this->get_content_num==$this->tem_nu
    m) // 判断这个部分是否是需要的。-1 表示全部
       {
       $content="";
       while (!ereg($boundary,$this->body_temp[$i]))
       {
       //$content[]=$this->body_temp[$i];
       $content.=$this->body_temp[$i]."/r/n";
       $i++;
       }
       //$content=implode("/r/n",$content);
       switch ($code_type)
       {
       case "base64":
       $content=base64_decode($content);
       break;
       case "quoted-printable":
       $content=str_replace("/n","/r/n",quoted_printable_decode($content));
       break;
       }
       $this->body[$this->tem_num][size]=strlen($content);
       $this->body[$this->tem_num][content]=$content;
       }
       else
       {
       while (!ereg($boundary,$this->body_temp[$i]))
       $i++;
       }
       $this->tem_num++;
       }
       // end else
      } // end while;
      } // end function define
      
      function decode_mime($string) {
      //decode_mime 已在上文中给出,这里略过。
      }
      } // end class define
    在这里要特别说明一点的是html正文里所用图片的解码。发送html格式的正文时,都会碰到图片如何传送的问题。图片在 html 文档里是一个<img src="" >的标签,关键是这个源文件从何来的。很多邮件的处理方法是用一个绝对的 url 标识,就是在邮件的html正文里用<img src= http://www.ccidnet.com/image/22.gif >之类的标签,这样,
    在阅读邮件时,邮件阅读器(通常是用内嵌的浏览器)会自动从网上下载图片,但是如果邮件收下来之后,与 Internet 的连接断了,图片也就不能正常显示。
    所以更好的方法是把图片放在邮件中一起发送出去。在 MIME 编码里,描述图片与正文的关系,除了上面所提到的multipart/related MIME头信息之外,还用到了一个Content-ID: 的属性来使图片与 html 正文之间建立关系。html 文档中的图片在编码时,其MIME头中加入一个 Content-ID:122223443556dsdf@ntsever 之类的属性,1222234
    43556dsdf@ntsever 是一个唯一的标识,在 html 文档里,<img>标签被修改成<img src ="cid: 122223443556dsdf@ntsever ">,在解码的时候,实际上,还需要把 html 正文中的这些<img src>标签进行修改,使之指向解码后的图片的具体路径。但是考虑到具体的解码程序中对图片会有不同的处理,所以在这个解码的类中,没有对 hmtl 正文中的<img>标签进行修改。所以在实际使用这个类时,对于有图片的 html 正文,还需要一定的
    处理。正文中的图片,可以用临时文件来保存,也可以用数据库来保存。
    现在我们已经介绍了POP3 收取邮件并进行 MIME 解码的原理。下面给出一个使用这两个类的一段小程序:
      <?
      include("pop3.inc.php");
      include("mime.inc.php");
      $host="pop.china.com";
      $user="boss_ch";
      $pass="mypassword";
      $rec=new pop3($host,110,2);
      $decoder=new decode_mail();
      if (!$rec->open()) die($rec->err_str);
      if (!$rec->login($user,$pass)) die($rec->err_str);
      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 "以下是信件内容:
";
       for ($i=1;$i<=count($rec->mail_list);$i++)
       {
       echo "信件".$rec->mail_list[$i][num].",大小:".$rec->mail_list[$i][size
    ]."<BR>";
       $rec->getmail($rec->mail_list[$i][num]);
       $decoder->decode($rec->head,$rec->body);
       echo "<h3>邮件头的内容:</h3><br>";
       echo $decoder->from_name."(".$decoder->from_mail.") 于".date("Y-m-d H:i:s",$decoder->mail_time)." 发给".$decoder->to_name."(".$decoder->to_mail.")";
       echo "/n<br>抄送:";
       if ($decoder->cc_to) echo $decoder->cc_to;else echo "无";
       echo "/n<br>主题:".$decoder->subject;
       echo "/n<br>回复到:".$decoder->reply_to;
      
       echo "<h3>邮件正文 :</h3><BR>";
       echo "正文类型:".$decoder->body_type;
       echo "<br>正文各内容:";
       for ($j=0;$jbody);$j++)
       {
       echo "/n<br>类型:".$decoder->body[$j][type];
       echo "/n<br>名称:".$decoder->body[$j][name];
       echo "/n<br>大小:".$decoder->body[$j][size];
       echo "/n<br>content_id:".$decoder->body[$j][content_id];
       echo "/n<br>正文字符集".$decoder->body[$j][char_set];
       echo "<pre>";
       echo "正文内容:".$decoder->body[$j][content];
       echo "</pre>";
       }
      $rec->dele($i);
       }
      }
      $rec->close();
      ?>
    如有想要取得完整源代码的朋友,请与本人联系: boss_ch@netease.com
    
    相关问题:
    QA003598 "用PHP实现POP3邮件的收取"

 类似资料: