| 導購 | 订阅 | 在线投稿
分享
 
 
當前位置: 王朝網路 >> php >> 用PHP實現POP3郵件的解碼(三)
 

用PHP實現POP3郵件的解碼(三)

2008-12-23 08:12:51  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
 
  實現 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 $this->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_num) // 判斷這個部分是否是需要的。-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/relatedMIME頭信息之外,還用到了一個 Content-ID: 的屬性來使圖片與 html 正文之間建立關系。html 文檔中的圖片在編碼時,其MIME頭中加入一個 Content-ID:122223443556dsdf@ntsever 之類的屬性,122223443556dsdf@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 "以下是信件內容:<br>";

  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;$j<count($decoder->body);$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

  <全文完>
 
 
 
上一篇《php6介紹和php6安裝手冊-PHP6下載》
下一篇《用PHP實現POP3郵件的解碼(二)》
 
 
 
 
 
 
日版寵物情人插曲《Winding Road》歌詞

日版寵物情人2017的插曲,很帶節奏感,日語的,女生唱的。 最後聽見是在第8集的時候女主手割傷了,然後男主用嘴幫她吸了一下,插曲就出來了。 歌手:Def...

兄弟共妻,我成了他們夜裏的美食

老鍾家的兩個兒子很特別,就是跟其他的人不太一樣,魔一般的執著。兄弟倆都到了要結婚的年齡了,不管自家老爹怎麽磨破嘴皮子,兄弟倆說不娶就不娶,老父母爲兄弟兩操碎了心...

如何磨出破洞牛仔褲?牛仔褲怎麽剪破洞?

把牛仔褲磨出有線的破洞 1、具體工具就是磨腳石,下面墊一個硬物,然後用磨腳石一直磨一直磨,到把那塊磨薄了,用手撕開就好了。出來的洞啊很自然的。需要貓須的話調幾...

我就是掃描下圖得到了敬業福和愛國福

先來看下敬業福和愛國福 今年春節,支付寶再次推出了“五福紅包”活動,表示要“把欠大家的敬業福都還給大家”。 今天該活動正式啓動,和去年一樣,需要收集“五福”...

冰箱異味産生的原因和臭味去除的方法

有時候我們打開冰箱就會聞到一股異味,冰箱裏的這種異味是因爲一些物質發出的氣味的混合體,聞起來讓人惡心。 産生這些異味的主要原因有以下幾點。 1、很多人有這種習...

《極品家丁》1-31集大結局分集劇情介紹

簡介 《極品家丁》講述了現代白領林晚榮無意回到古代金陵,並追隨蕭二小姐化名“林三”進入蕭府,不料卻陰差陽錯上演了一出低級家丁拼搏上位的“林三升職記”。...

李溪芮《極品家丁》片尾曲《你就是我最愛的寶寶》歌詞

你就是我最愛的寶寶 - 李溪芮 (電視劇《極品家丁》片尾曲) 作詞:常馨內 作曲:常馨內 你的眉 又鬼馬的挑 你的嘴 又壞壞的笑 上一秒吵鬧 下...

烏梅的功效與作用以及烏梅的食用禁忌有哪些?

烏梅,又稱春梅,中醫認爲,烏梅味酸,性溫,無毒,具有安心、除熱、下氣、祛痰、止渴調中、殺蟲的功效,治肢體痛、肺痨病。烏梅泡水喝能治傷寒煩熱、止吐瀉,與幹姜一起制...

什麽是脂肪粒?如何消除臉部脂肪粒?

什麽是脂肪粒 在我們的臉上總會長一個個像脂肪的小顆粒,弄也弄不掉,而且顔色還是白白的。它既不是粉刺也不是其他的任何痘痘,它就是脂肪粒。 脂肪粒雖然也是由油脂...

網絡安全治理:國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰受害者

來源:中國青年報 新的攻擊方法不斷湧現,黑客幾乎永遠占據網絡攻擊的上風,我們不可能通過技術手段杜絕網絡攻擊。國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰...

河南夫妻在溫嶺網絡直播“造人”內容涉黃被刑事拘留

夫妻網絡直播“造人”爆紅   1月9日,溫嶺城北派出所接到南京警方的協查通告,他們近期打掉了一個涉黃直播APP平台。而根據掌握的線索,其中有一對涉案的夫妻主播...

如何防止牆紙老化?牆紙變舊變黃怎麽辦?

如何防止牆紙老化? (1)選擇透氣性好的牆紙 市場上牆紙的材質分無紡布的、木纖維的、PVC的、玻璃纖維基材的、布面的等,相對而言,PVC材質的牆紙最不透氣...

鮮肌之謎非日本生産VS鮮肌之謎假日貨是謠言

觀點一:破日本銷售量的“鮮肌之謎” 非日本生産 近一段時間,淘寶上架了一款名爲“鮮肌之謎的” 鲑魚卵巢美容液,號稱是最近日本的一款推出的全新護膚品,産品本身所...

中國最美古詩詞精選摘抄

系腰裙(北宋詞人 張先) 惜霜蟾照夜雲天,朦胧影、畫勾闌。人情縱似長情月,算一年年。又能得、幾番圓。 欲寄西江題葉字,流不到、五亭前。東池始有荷新綠,尚小如...

關于女人的經典語句

關于女人的經典語句1、【做一個獨立的女人】 思想獨立:有主見、有自己的人生觀、價值觀。有上進心,永遠不放棄自己的理想,做一份自己喜愛的事業,擁有快樂和成就...

未來我們可以和性愛機器人結婚嗎?

你想體驗機器人性愛嗎?你想和性愛機器人結婚嗎?如果你想,機器人有拒絕你的權利嗎? 近日,第二屆“國際人類-機器人性愛研討會”大會在倫敦金史密斯大學落下帷幕。而...

全球最變態的十個地方

10.土耳其地下洞穴城市 變態指數:★★☆☆☆ 這是土耳其卡帕多西亞的一個著名景點,傳說是當年基督教徒們爲了躲避戰爭而在此修建。裏面曾住著20000人,...

科學家稱,人類死亡後意識將在另外一個宇宙中繼續存活

據英國《每日快報》報道,一位科學家兼理論家Robert Lanza博士宣稱,世界上並不存在人類死亡,死亡的只是身體。他認爲我們的意識借助我們體內的能量生存,而且...

《屏裏狐》片頭曲《我愛狐狸精》歌詞是什麽?

《我愛狐狸精》 - 劉馨棋   (電視劇《屏裏狐》主題曲)   作詞:金十三&李旦   作曲:劉嘉   狐狸精 狐狸仙   千年修...

 
 
 
實現 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 $this->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_num) // 判斷這個部分是否是需要的。-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= [url=http://www.ccidnet.com/image/22.gif]http://www.ccidnet.com/image/22.gif[/url] >之類的標簽,這樣,在閱讀郵件時,郵件閱讀器(通常是用內嵌的浏覽器)會自動從網上下載圖片,但是如果郵件收下來之後,與 Internet 的連接斷了,圖片也就不能正常顯示。   所以更好的方法是把圖片放在郵件中一起發送出去。在 MIME 編碼裏,描述圖片與正文的關系,除了上面所提到的multipart/related MIME頭信息之外,還用到了一個 Content-ID: 的屬性來使圖片與 html 正文之間建立關系。html 文檔中的圖片在編碼時,其MIME頭中加入一個 Content-ID:122223443556dsdf@ntsever 之類的屬性,[url=mailto:122223443556dsdf@ntsever]122223443556dsdf@ntsever[/url]是一個唯一的標識,在 html 文檔裏,<img>標簽被修改成<img src="cid: [url=mailto:122223443556dsdf@ntsever]122223443556dsdf@ntsever[/url]">,在解碼的時候,實際上,還需要把 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 "以下是信件內容:<br>";    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;$j<count($decoder->body);$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();   ?>   如有想要取得完整源代碼的朋友,請與本人聯系: [url=mailto:boss_ch@netease.com]boss_ch@netease.com[/url] <全文完>
󰈣󰈤
 
 
 
  免責聲明:本文僅代表作者個人觀點,與王朝網路無關。王朝網路登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
 
美得讓人陶醉
杭州美女模特米萊
清純迷人唐小妹
氣質一流的上海女生
夢醉克孜加爾湖畔
珠江公園(二)
魔域桃源
南嶺森林公園親水谷
 
>>返回首頁<<
 
 
 
 熱帖排行
 
 
 
 
© 2005- 王朝網路 版權所有