PHP郵件專題PHP SMTP類 <? /*********************************** PHP MIMESMTP ver 1.0 Powered by Boss_ch, Unigenius soft ware co. Ltd All rights reserved, Copyright 2000 ; 本類用PHP通過smtp sock 操作發(fā)送MIME 類型的郵件,可以發(fā)送 HTML 格式的正文、附件,采用base64 編碼 本版本是針對個人的發(fā)送,與多人群發(fā)版本不同的是,每發(fā)送到一個人,就重新進行一次編碼,在接收端的用戶看來,只是發(fā)送給他一個人的。 針對多人群發(fā)的情況,只發(fā)送一次,通過多個RCPTTO命令發(fā)送到不同的人信箱中, 說明: 請把$hostname 設為你有權限的默認smtp 服務器或是在new 時指定 把$charset 改成你的默認字符集 Html 正文中如有圖片,請用絕對路徑的引用"httP://host/path/image.gif"; 并連上網(wǎng),以保證程序能讀取到圖片的數(shù)據(jù)信息 如果是通過表單提交過來的Html 正文,請先用StripSlashes($html_body)把正文內(nèi)容進行預處理 Html 中用到的樣式表文件,請不要用<link >之類的引用,直接把樣式表定義放在 <style></style>標簽中
轉(zhuǎn)載請保留此版權信息,Bugs Report : boss_ch@china.com *************************************/ if(!isset($__smtp_class__)){ $__smtp_class__=1;
class smtp { var $hostname=""; var $port=25; var $connection=0; var $debug=1;
var $timeout=30; var $err_str; var $err_no;
var $autocode=true; var $charset="??????"; var $subject=""; var $body=""; var $attach=""; var $temp_text_body; var $temp_html_body; var $temp_body_images;
var $bound_begin="=====powered_by_boss_chen_"; var $bound_end="_046484063883_=====";
Function smtp($server="smtp.china.com",$port=25,$time_out=20) {$this->hostname=$server; $this->port=$port; $this->timeout=$time_out; return true; }
Function outdebug($message) { echo htmlspecialchars($message)."<br>\n"; }
function command($command,$return_lenth=1,$return_code='2') { if ($this->connection==0) { $this->err_str="沒有連接到任何服務器,請檢查網(wǎng)絡連接"; return false; } if ($this->debug) $this->outdebug(">>> $command"); if (!fputs($this->connection,"$command \r\n")) { $this->err_str="無法發(fā)送命令".$command; return false; } else { $resp=fgets($this->connection,256); if($this->debug) $this->outdebug("$resp"); if (substr($resp,0,$return_lenth)!=$return_code) { $this->err_str=$command." 命令服務器返回無效:".$resp; return false; } else return true; } }
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="連接到SMTP 服務器失敗,錯誤信息:".$err_str."錯誤號:".$err_no; return false; } else { $resp=fgets($this->connection,256); if($this->debug) $this->outdebug("$resp"); if (substr($resp,0,1)!="2") {$this->err_str="服務器返回無效的信息:".$resp."請檢查SMTP服務器是否正確"; return false; } return true; } }
Function Close() { if($this->connection!=0) { fclose($this->connection); $this->connection=0; } }
Function Buildhead($from_name,$to_name,$from_mail,$to_mail,$subject) { if (empty($from_name)) $from_name=$from_mail; if (empty($to_name)) $to_name=$to_mail; $this->subject="From: =?$this->charset?B?".base64_encode($from_name)."?=<$from_mail>\r\n"; $this->subject.="To: =?$this->charset?B?".base64_encode($to_name)."?=<$to_mail>\r\n"; $subject=ereg_replace("\n","",$subject); $this->subject.="Subject: =?$this->charset?B?".base64_encode($subject)."?=\r\n"; if ($this->debug) echo nl2br(htmlspecialchars($this->subject)); return true; }
Function parse_html_body($html_body=null) { $passed=""; $image_count=0; $this->temp_body_images=array(); while (eregi("\<*img([^\>]+)src[[:space:]]*=[[:space:]]*([^ ]+)",$html_body,$reg)) {
$pos=@strpos($html_body,$reg[0]); $passed.=substr($html_body,0,$pos); $html_body=substr($html_body,$pos+strlen($reg[0])); $image_tag=$reg[2]; $image_att=$reg[1]; $tag_len=strlen($image_tag); if ($image_tag[0]=="'" or $image_tag[0]=='"') $image_tag=substr($image_tag,1); if (substr($image_tag,strlen($imgage_tag)-1,1)=="'" or substr($image_tag,strlen($imgage_tag)-1,1)=='"') $image_tag=substr($image_tag,0,strlen($imgage_tag)-1); //echo $image_tag."<br>"; $cid=md5(uniqid(rand())); $cid=substr($cid,0,15)."@unigenius.com"; $passed.="<img ".$image_att."src=\"cid:".$cid."\""; $end_pos=@strpos($html_body,'>'); $passed.=substr($html_body,0,$end_pos); $html_body=substr($html_body,$end_pos); // 把圖片數(shù)據(jù)讀出來保存到一個數(shù)據(jù);
$img_file_con=fopen($image_tag,"r"); unset($image_data); while ($tem_buffer=AddSlashes(fread($img_file_con,16777216))) $image_data.=$tem_buffer; fclose($img_file_con); $image_exe_name=substr($image_tag,strrpos($image_tag,'.')+1,3); switch (strtolower($image_exe_name)) { case "jpg": case "jpeg": $content_type="image/jpeg"; break; case "gif": $content_type="image/gif"; break; case "png": $content_type="image/x-png"; break; case "tif": $content_type="image/tif"; break; default: $content_type="image/"; break; }
$this->temp_body_images[$image_count][name]=basename($image_tag); $this->temp_body_images[$image_count][type]=$content_type; $this->temp_body_images[$image_count][cid]=$cid; $this->temp_body_images[$image_count][data]=$image_data; $image_count++; } $this->temp_html_body=$passed.$html_body; return true;
}
function build_content($bound_level=0,$text_body,$html_body,$hava_att=false) { if ($html_body) { if (eregi("\<*img[[:space:]]+src[[:space:]]*=[[:space:]]*([^ ]+)",$html_body,$reg)) { $bound_level++; if ($text_body) { $this->body.="Content-Type: multipart/related; type=\"multipart/alternative\"; \tboundary=\""; $this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n"; } else { $this->body.="Content-Type: multipart/related; \tboundary=\""; $this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
}// 對于是否 text 正文 、 html正文 有沒有,須有不同的 MIME 頭 if (!$hava_att) $this->body.="This is a multi-part message in MIME format.\r\n\r\n"; // 正文標識,如果是已經(jīng)有附件的編碼,則在正文 中不需要這一句 $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->parse_html_body($html_body); if ($text_body) { $this->body.="Content-Type: multipart/alternative; \tboundary=\""; $bound_level++; $this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: text/plain;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: text/html;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n"; $bound_level--; } else { $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: text/html;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n"; }//正文編碼,有或沒有text 部分,編成不同的格式。 for ($i=0;$i<count($this->temp_body_images);$i++) { $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type:".$this->temp_body_images[$i][type]."; name=\""; $this->body.=$this->temp_body_images[$i][name]."\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="Content-ID: <".$this->temp_body_images[$i][cid].">\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_body_images[$i][data])))."\r\n"; } $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n"; $bound_level--; } else // 有或沒有圖片,以上是有圖片的處理,下面是沒有圖片的處理 { $this->temp_html_body=$html_body; if ($text_body) { $bound_level++; $this->body.="Content-Type: multipart/alternative; \tboundary=\""; $this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n";
if (!$hava_att) $this->body.="\r\nThis is a multi-part message in MIME format.\r\n\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: text/plain;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: text/html;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n"; $bound_level--; } else { $this->body.="Content-Type: text/html;\r\n"; $this->body.="\tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($this->temp_html_body)))."\r\n"; }//正文編碼,有或沒有text 部分,編成不同的格式。
}// end else } else // 如果沒有html 正文,只有text 正文 { $this->body.="Content-Type: text/plain; \tcharset=\"$this->charset\"\r\n"; $this->body.="Content-Transfer-Encoding: base64\r\n"; $this->body.="\r\n".chunk_split(base64_encode(StripSlashes($text_body)))."\r\n"; } }// end function default
Function Buildbody($text_body=null,$html_body=null,$att=null) { $this->body="MIME-Version: 1.0\r\n"; if (null==$att or (@count($att)==0)) //如果沒有附件,查看正文的類型; { $encode_level=0; $this->build_content($encode_level,$text_body,$html_body); }// 如果沒有附件, // ******************************************************** else //如果有附件, { $bound_level=0; $this->body.="Content-Type: multipart/mixed; \tboundary=\""; $bound_level++;
$this->body.=$this->bound_begin.$bound_level.$this->bound_end."\"\r\n\r\n"; $this->body.="This is a multi-part message in MIME format.\r\n\r\n"; $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->build_content($bound_level,$text_body,$html_body,true);// 編入正文部分
$num=count($att); for ($i=0;$i<$num;$i++) { $file_name=$att[$i][name]; $file_source=$att[$i][source]; $file_type=$att[$i][type]; $file_size=$att[$i][size];
if (file_exists($file_source)) { $file_data=addslashes(fread($fp=fopen($file_source,"r"), filesize($file_source))); $file_data=chunk_split(base64_encode(StripSlashes($file_data))); $this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."\r\n"; $this->body.="Content-Type: $file_type;\r\n\tname=\"$file_name\"\r\nContent-Transfer-Encoding: base64\r\n"; $this->body.="Content-Disposition: attachment;\r\n\tfilename=\"$file_name\"\r\n\r\n"; $this->body.=$file_data."\r\n"; } }//end for
$this->body.="--".$this->bound_begin.$bound_level.$this->bound_end."--\r\n\r\n"; }// end else
if ($this->debug) echo nl2br(htmlspecialchars($this->body));
return true; }
function send($from_name,$to_name,$from_mail,$to_mail,$subject,$text_body=false,$html_body=false,$att=false) {
if (empty($from_mail) or empty($to_mail)) { $this->err_str="沒有指定正確的郵件地址:發(fā)送人:".$from_mail."接收人:".$to_mail; return false; }
if (gettype($to_mail)!="array") $to_mail=split(",",$to_mail);//如果不是數(shù)組,轉(zhuǎn)換成數(shù)組,哪怕只有一個發(fā)送對象; if (gettype($to_name)!="array") $to_name=split(",",$to_name);//如果不是數(shù)組,轉(zhuǎn)換成數(shù)組,哪怕只有一個發(fā)送對象;
$this->Buildbody($text_body,$html_body,$att); // 所有信件的內(nèi)容是一樣的,可以只編一次,而對于不同的收信人,需要不同的Head
if (!$this->open()) return false; if (!$this->command("HELO $this->hostname",3,"250")) return false; // 與服務器建立鏈接 if (!$this->open()) return false; if (!$this->command("HELO $this->hostname",3,"250")) return false;
for ($i=0;$i<count($to_mail);$i++) { $this->Buildhead($from_name,$to_name[$i],$from_mail,$to_mail[$i],$subject); if (!$this->command("RSET",3,"250")) return false; if (!$this->command("MAIL FROM:".$from_mail,3,"250")) return false; if (!$this->command("RCPT TO:".$to_mail[$i],3,"250")) return false; if (!$this->command("DATA",3,"354")) return false; // 準備發(fā)送郵件 if ($this->debug) $this->outdebug("sending subject;"); if (!fputs($this->connection,$this->subject)) {$this->err_str="發(fā)送郵件頭時出錯!";return false;} if ($this->debug) $this->outdebug("sending body;"); if (!fputs($this->connection,$this->body)) {$this->err_str="發(fā)送正文時出錯!";return false;} if (!fputs($this->connection,".\r\n")) {$this->err_str="發(fā)送正文時出錯!";return false;}//正文發(fā)送完畢,退出; $resp=fgets($this->connection,256); if($this->debug) $this->outdebug("$resp"); if (substr($resp,0,1)!="2") { $this->err_str="發(fā)送完后,服務器沒有響應!!"; return false; } // 發(fā)送郵件 } if (!$this->command("QUIT",3,"221")) return false; $this->close(); return true; }
}//end class define }//end if(!isset($__smtp_class__)) ?>
PHP SMTP類使用方法 <? include("smtp.php");
$mail = new smtp("localhost");
$mail->debug = 0;
$sender_name = "root"; $sender_mail = "root@localhost"; $to_name = "mm"; $to_mail = "mm@your.com"; $subject = "i miss u"; $content = "i miss u much."; $att[0]["name"] = "miss.jpg"; $att[0]["source"] = "/path/to/your/miss.jpg"; $att[0]["type"] = "image/jpeg"; $att[0]["size"] = "10kb"; $extra_subject = "To:".$to_mail." 主題:".$subject;
if (!$mail->send($sender_name,$to_name,$sender_mail,$to_mail,$extra_subject,$content,false,$att)) $err = 1; ?>
返回文件的MIME類型的函數(shù)guessMIMEType() function guessMIMEType($filename) { //GUESS MIME TYPE $filename = basename($filename); if(strrchr($filename,".") == false) { return("application/octet-stream"); }
$ext = strrchr($filename,"."); switch($ext) { case ".gif": return "image/gif"; break; case ".gz": return "application/x-gzip"; case ".htm": case ".html": return "text/html"; break; case ".jpg": return "image/jpeg"; break; case ".tar": return "application/x-tar"; break; case ".txt": return "text/plain"; break; case ".zip": return "application/zip"; break; default: return "application/octet-stream"; break; } }
檢測Email地址的函數(shù)IsValidEmail() function IsValidEmail($Email) { if(!ereg("^[[:alnum:]\_\.]+@([[:alnum:]\_]+\.)+[[:alnum:]][[:alnum:]][[:alnum:]]?$",$Email, $regs)){ $IsValidEmail = false; } else { $IsValidEmail = true; } return $IsValidEmail; }
一個MIME MAIL類,請大家注意如何構造一個郵件體 <? class mime_mail { var $parts; var $to; var $from; var $headers; var $subject; var $body;
/* * void mime_mail() * class constructor */ function mime_mail() { $this->parts = array(); $this->to = ""; $this->from = ""; $this->subject = ""; $this->body = ""; $this->headers = ""; }
/* * void add_attachment(string message, [string name], [string ctype]) * Add an attachment to the mail object */ function add_attachment($message, $name = "", $ctype = "application/octet-stream") { $this->parts[] = array ( "ctype" => $ctype, "message" => $message, "encode" => $encode, "name" => $name ); }
/* * void build_message(array part= * Build message parts of an multipart mail */ function build_message($part) { $message = $part["message"]; $message = chunk_split(base64_encode($message)); $encoding = "base64"; return "Content-Type: ".$part["ctype"]. ($part["name"]?";\n\tname=\"".$part["name"]."\"" : ""). "\nContent-Transfer-Encoding: $encoding". "\nContent-Disposition: attachment". ($part["name"]?";\n\tfilename=\"".$part["name"]."\"" : ""). "\n\n$message\n"; }
/* * void build_multipart() * Build a multipart mail */ function build_multipart() { $boundary = "b".md5(uniqid(time())); $multipart = "Content-Type: multipart/mixed;\n\tboundary=\"$boundary\"\n\nThis is a MIME encoded message.\n\n--$boundary";
for($i = sizeof($this->parts)-1; $i >= 0; $i--) { $multipart .= "\n".$this->build_message($this->parts[$i])."--$boundary"; } return $multipart.= "--\n"; }
/* * void send() * Send the mail (last class-function to be called) */ function send() { $addtionheaders = ""; if (!empty($this->from)) $addtionheaders .= "From: ".$this->from."\n"; if (!empty($this->headers)) $addtionheaders .= $this->headers."\n";
if (!empty($this->body)) $this->add_attachment($this->body, "", "text/plain");
$addtionheaders .= "MIME-Version: 1.0\n".$this->build_multipart();
$fp = fopen("mail.txt","w"); fputs($fp,$addtionheaders); fclose($fp); mail($this->to, $this->subject, "", $addtionheaders); } }; // end of class
/* * Example usage *
$attachment = fread(fopen("test.jpg", "r"), filesize("test.jpg"));
$mail = new mime_mail(); $mail->from = "foo@bar.com"; $mail->headers = "Errors-To: foo@bar.com"; $mail->to = "bar@foo.com"; $mail->subject = "Testing..."; $mail->body = "This is just a test."; $mail->add_attachment("$attachment", "test.jpg", "image/jpeg"); $mail->send();
*/ ?>
myimap類,讀取郵件 <?php ////////////////////////////////////////////// //Origin by Alpha.Z (5/21/2000) //Modified By Belltree <belltree@163.com> (11/01/2000) /////////////////////////////////////////////// class myimap { var $username=""; var $userpwd=""; var $hostname=""; var $port=0; var $connection=0; //是否連接 var $state="DISCONNECTED"; //連接狀態(tài) var $greeting=""; var $must_update=0; var $inStream=0; var $num_msg_parts = 0; var $attach; var $num_of_attach = 0;
function open() { if ($this->port==110) $this->inStream=imap_open("{".$this->hostname."/pop3:110}inbox",$this->username,$this->userpwd); else $this->inStream=imap_open("{".$this->hostname.":143}INBOX",$this->username,$this->userpwd);
if ($this->inStream) { //echo "用戶:$this->username 的信箱連接成功。<br>"; return $inStream; } else { echo "用戶:$this->username 的信箱連接失敗。<br>"; return 0; } }
Function close() { if(imap_close($this->inStream)) { //echo "<hr>已經(jīng)與服務器 $this->hostname 斷開連接。"; return 1; } else { //echo "<hr>與服務器 $this->hostname 斷開連接失敗。"; return 0; } }
function DeleteMail($msg_no){ if (@imap_delete($this->inStream,$msg_no)) return true; else return false; }
function ExpungeMail(){ if (@imap_expunge($this->inStream)) return true; else return false; }
function CheckMailbox($page_size,$page) { $mboxinfo=@imap_mailboxmsginfo($this->inStream); //$mboxinfo=imap_check($this->inStream); if ($mboxinfo) if ($mboxinfo->Nmsgs>0) { //echo "您郵箱:".$mboxinfo->Mailbox."<br>"; echo $this->username."@wells.com的收件箱里共有郵件數(shù):".$mboxinfo->Nmsgs."<br>\n"; echo "未讀郵件數(shù):".$mboxinfo->Unread.""; echo "新郵件數(shù):".$mboxinfo->Recent." "; echo "總共占用空間:".$mboxinfo->Size."字節(jié)<br>\n"; $last_page = ceil($mboxinfo->Nmsgs/$page_size); $cur_page = $page +1; $num_page = $last_page; echo "第".$cur_page."頁,共".$last_page."頁。\n"; } else { echo "您的信箱里沒有郵件。<br><hr>\n"; } else { echo '<font color="#ff0000">錯誤:無法獲取收件箱的信息。</font>'; return 0; } echo "<table border=1 width=100% cellpadding=2 cellspacing=0 bordercolorlight=#000080 bordercolordark=#ffffff style=\"font:9pt Tahoma,宋體\">\n"; echo "<tr bgcolor=#ffffd8><td width=24>狀態(tài)</td><td width=24> </td><td>發(fā)件人</td><td>主題</td><td>時間</td><td>大小</td></tr>\n"; $sortby="SORTDATE"; $sort_reverse=1; $sorted = imap_sort($this->inStream, $sortby, $sort_reverse, SE_UID);
for ($i=0;$i<$mboxinfo->Nmsgs;$i++) { if (($i>=$page*$page_size) and ($i<$page*$page_size+$page_size)){ $msg_no = @imap_msgno($this->inStream, $sorted[$i]); $msgHeader = @imap_header($this->inStream, $msg_no); //日期
if (isset($msgHeader->date)) { $date = $msgHeader->date;
if (ord($date) > 64) $date = substr($date, 5);
$datepart = split(" ",$date); $date = $datepart[0]." ".$datepart[1]." ".$datepart[2]." ".$datepart[3]; /* while (strstr(' ', $date)) { $date = str_replace(' ', ' ', $date); } */ }
if (isset($msgHeader->from[0])) { $from = $msgHeader->from[0]; if (isset($from->personal)) { $frm = trim($this->decode_mime_string($from->personal)); if (isset($from->mailbox) && isset($from->host)) { $frm_add = $from->mailbox . '@' . $from->host; } } else if (isset($from->mailbox) && isset($from->host)) { $frm = $from->mailbox . '@' . $from->host; } else if (isset($msgHeader->fromaddress)) $frm = trim($h->fromaddress); } else if (isset($msgHeader->fromaddress)) $frm = trim($msgHeader->fromaddress);
if (isset($msgHeader->toaddress)) $to = trim($msgHeader->toaddress); else $to = "未知";
if (isset($msgHeader->subject)) $sub = trim($this->decode_mime_string($msgHeader->subject)); if ($sub == "") $sub = "無主題"; if (isset($msgHeader->Size)) $msg_size = ($msgHeader->Size > 1024) ? sprintf("%.0f kb", $msgHeader->Size / 1024) : $msgHeader->Size; //if (strlen($frm) > 50) // $frm = substr($frm, 0, 50) . '...'; if (strlen($sub) > 50) $sub = substr($sub, 0, 50) . '...'; if ($msgHeader->Unseen == "U") $newmail = "未讀"; else $newmail = "已讀"; echo "<tr>\n"; echo "<td align=center>$newmail</td><td align=\"center\"></td>\n"; echo '<td>'.$frm.'</td><td><a href="mail_read.php?msg='.$msg_no.'">'.$sub.'</a></td><td width=125>'.$date.'</td><td width=50>'.$msg_size.'</td>'; echo "</tr>\n"; }} echo "</table>\n"; echo "<table border=0 width=100% cellspacing=4 cellpadding=4><tr>\n"; if ($page == 0) echo "<td>第一頁</td>\n"; else echo "<td><a href=\"mail_list.php?page=0\">第一頁</a></td>\n"; if (($prev_page = $page-1) < 0) echo "<td>前一頁</td>\n"; else echo "<td><a href=\"mail_list.php?page=$prev_page\">前一頁</a></td>\n";
if (($next_page = $page + 1) >= $last_page) echo "<td>后一頁</td>\n"; else echo "<td><a href=\"mail_list.php?page=$next_page\">后一頁</a></td>\n"; $last_page --; if ( $last_page < $next_page) echo "<td>最末頁</td>\n"; else echo "<td><a href=\"mail_list.php?page=$last_page\">最末頁</a></td>\n"; echo "</tr></table>\n"; }
function decode_mime_string ($string) { $pos = strpos($string, '=?'); if (!is_int($pos)) { return $string; }
$preceding = substr($string, 0, $pos); // save any preceding text
$search = substr($string, $pos+2, 75); // 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);
$d2 = strpos($search, '?'); if (!is_int($d2)) { return $string; }
$encoding = substr($search, 0, $d2); $search = substr($search, $d2+1);
$end = strpos($search, '?='); if (!is_int($end)) { return $string; }
$encoded_text = substr($search, 0, $end); $rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text)+6));
switch ($encoding) { case 'Q': case 'q': $encoded_text = str_replace('_', '%20', $encoded_text); $encoded_text = str_replace('=', '%', $encoded_text); $decoded = urldecode($encoded_text); break;
case 'B': case 'b': $decoded = urldecode(base64_decode($encoded_text)); break;
default: $decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?='; break; }
return $preceding . $decoded . $this->decode_mime_string($rest); }
Function display_toaddress ($user, $server, $from) { return is_int(strpos($from, $this->get_barefrom($user, $server))); }
Function get_barefrom($user, $server) { $barefrom = "$user@$real_server";
return $barefrom; }
Function get_structure($msg_num) { $structure=imap_fetchstructure($this->inStream,$msg_num); //echo gettype($structure); return $structure; }
Function proc_structure($msg_part, $part_no, $msg_num) { if ($msg_part->ifdisposition) { // See if it has a disposition, The only thing I know of that this, would be used for would be an attachment // Lets check anyway if ($msg_part->disposition == "attachment") { $att_name = "unknown"; for ($lcv = 0; $lcv < count($msg_part->parameters); $lcv++) { $param = $msg_part->parameters[$lcv];
if ($param->attribute == "name") { $att_name = $param->value; break; } }
$att_name = $this->decode_mime_string($att_name);
$att_path = $this->username."\\".$att_name;
$this->attach[$this->num_of_attach]=$att_name; //登記附件列表 $this->num_of_attach ++; //登記附件數(shù)量 /* $att_path = $this->username."\\".$this->decode_mime_string($att_name); if ($this->attach=="") $this->attach = $att_name; else $this->attach .= ";".$att_name; */ if (!is_dir($this->username)) mkdir($this->username,0700); $fp=fopen($att_path,"w"); switch ($msg_part->encoding) { case 3: // base64 fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no))); break; case 4: // QP fputs($fp,imap_qprint(imap_fetchbody($this->inStream,$msg_num,$part_no))); break; default: fputs($fp,imap_fetchbody($this->inStream,$msg_num,$part_no)); break; } fclose($fp);
//if ($msg_part->type=="5"){ // echo "<p align=center><hr align=center>\n"; // echo "<img src=\"$att_path\" align=center></p>\n"; //} } // END IF ATTACHMENT else //NOT ifdisposition { // I guess it is used for something besides attachments???? } } else { // Not an attachment, lets see what this part is... switch ($msg_part->type) { case 0: $mime_type = "text"; break; case 1: $mime_type = "multipart"; // Hey, why not use this function to deal with all the parts // of this multipart part $this->num_msg_parts = count($msg_part->parts); for ($i = 0; $i < $this->num_msg_parts; $i++) { if ($part_no != "") { $part_no = $part_no."."; } for ($i = 0; $i < count($msg_part->parts); $i++) { $this->proc_structure($msg_part->parts[$i], $part_no.($i + 1), $msg_num); } } break; case 2: $mime_type = "message"; break; case 3: $mime_type = "application"; break; case 4: $mime_type = "audio"; break; case 5: $mime_type = "image"; break; case 6: $mime_type = "video"; break; case 7: $mime_type = "model"; break; default: $mime_type = "unknown"; // hmmm.... }
$full_mime_type = $mime_type."/".$msg_part->subtype; $full_mime_type = strtolower($full_mime_type);
// Decide what you what to do with this part // If you want to show it, figure out the encoding and echo away
switch ($msg_part->encoding) {
case 0: case 1: if ($this->num_msg_parts == 0){ echo ereg_replace("\r\n","<br>\r\n",imap_body($this->inStream,$msg_num));
} else{ if ($part_no!=""){ echo ereg_replace("\r\n","<br>\r\n",imap_fetchbody($this->inStream,$msg_num,$part_no));
} } break; case 3: //BASE64
if ($full_mime_type=="text/plain"){
if ($this->num_msg_parts == 0){ $content=imap_base64(imap_body($this->inStream,$msg_num)); } else{ $content = imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no)); $att_path = $this->username . "\\文本內(nèi)容.txt"; $fp = fopen($att_path,"w"); fputs($fp,$content); fclose($fp); $this->attach[$this->num_of_attach]="文本內(nèi)容.txt"; $this->num_of_attach++; }
echo $content;
}
if ($full_mime_type=="text/html"){ $att_path = $this->username . "\\超文本內(nèi)容.htm"; $fp = fopen($att_path,"w"); fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no))); fclose($fp); $this->attach[$this->num_of_attach]="超文本內(nèi)容.htm"; $this->num_of_attach++; } break; case 4: //QPRINT // use imap_qprint to decode if ($this->num_msg_parts == 0){ echo ereg_replace("\n","<br>",imap_qprint(imap_body($this->inStream,$msg_num)));
} else{ echo ereg_replace("\n","<br>",imap_qprint(imap_fetchbody($this->inStream,$msg_num,$part_no)));
} if ($full_mime_type=="text/html"){ $att_path = $this->username . "\\qp超文本內(nèi)容.htm"; $fp = fopen($att_path,"w"); fputs($fp,imap_base64(imap_fetchbody($this->inStream,$msg_num,$part_no))); fclose($fp); $this->attach[$this->num_of_attach]="qp超文本內(nèi)容.htm"; $this->num_of_attach++; } break; case 5: // not sure if this needs decoding at all echo ereg_replace("\n","<br>",imap_fetchbody($this->inStream,$msg_num)); break; default: //echo ereg_replace("\n","<br>",imap_fetchbody($this->inStream,$msg_num,$part_no)); break; }
} }
};
?>
myimap的擴展類,及讀取一封郵件的例子(mail_read.php) <? require("myimap.php");
class myimap_ext extends myimap {
function get_mail_subject($msg_no){ $msgHeader = @imap_header($this->inStream, $msg_no); if (isset($msgHeader->subject)) $sub = trim($this->decode_mime_string($msgHeader->subject)); if ($sub == "") $sub = "無主題"; return "Fw:".$sub; } function print_attaches(){ for ($i=0;$i<count($this->attach);$i++){ echo "<a target=_blank href=\"".$this->username."\\".$this->attach[$i]."\">".$this->attach[$i]."<br/>"; } } function list_attaches(){ for ($i=0;$i<count($this->attach);$i++){ if ($i==0) $attaches = $this->attach[$i]; else $attaches .= ";".$this->attach[$i]; } return $attaches; } }
$imap=new myimap_ext; $imap->hostname="localhost"; $imap->port=143; $imap->username="name"; $imap->userpwd="password";
$imap->open();
$mail_structure=$imap->get_structure($msg); $imap->proc_structure($mail_structure,"",$msg); if ($imap->num_of_attach > 0){ $imap->print_attaches(); } @$imap->close(); ?>
myimap的例子(mail_list.php) <? require("myimap.php");
$imap=new myimap; $imap->hostname="localhost"; $imap->port=143; $imap->username="name"; $imap->userpwd="password";
$imap->open(); if ($page=="") $page=0; $imap->CheckMailBox(10,$page); @$imap->close(); ?>
如何發(fā)送附件(轉(zhuǎn)) 我經(jīng)常聽到這樣一個問題:"我有一個從網(wǎng)站發(fā)來的合同。我如何給通過表單發(fā)送的電子郵件增加一個附件呢?" 首先我要說的是要做到這個沒有什么簡單的辦法。你要很好的理解PHP或 其它的服務器端的腳本語言。當然你還要一個真正支持PHP的網(wǎng)站的賬號。如果滿足了這個前提,在你讀完了本章后就可以用PHP發(fā)送帶附件的電子郵件了。
1. 附件是如何工作的
如果你曾經(jīng)在PHP的手冊中搜索過"附件"函數(shù),那么結果可能是什么都沒有(至少在我寫本文的時間還沒有)。后來你就要花很多時間來了解這方面的知識。
你也許會想當你給某個人發(fā)送一封帶附件的電子郵件時,附件是和郵件一起放到收件人的信箱里的(比如,如果你給他/她發(fā)了一個PNG的圖片文件,他/她的信箱里會包含一個txt文件(電子郵件)和一個.png文件(附件))。但這不是它的工作原理。當你加入一個附件時,你的郵件程序把附件轉(zhuǎn)換成純文本文件,并在你寫的內(nèi)容(實際的電子郵件)后面插入這個文本塊。這個,當你把所有的東西發(fā)出來后,收件人的信箱里只有一個純文本文件--一個同時包含附件和實際電子郵件內(nèi)容的文件。
下面是一個帶附件(一個HTML文件)電子郵件的例子。我已經(jīng)標注了其中重要的幾行:
Return-Path: <someone@example.com> Date: Mon, 22 May 2000 19:17:29 +0000 From: Someone <someone@example.com> To: Person <person@eksempel.dk> Message-id: <83729KI93LI9214@example.com> Content-type: multipart/mixed; boundary="396d983d6b89a" Subject: Here's the subject
--396d983d6b89a Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 8bit
This is the body of the email.
--396d983d6b89a Content-type: text/html; name=attachment.html Content-disposition: inline; filename=attachment.html Content-transfer-encoding: 8bit
<html> <head> <title>The attachment</title> </head> <body> <h2>This is the attached HTML file</h2> </body> </html>
--396d983d6b89a--
前面的7行是郵件的頭,其中值得注意的是Content-type頭部分。這個頭告訴郵件程序電子郵件是由一個以上的部分組成的。不含附件的郵件只有一個部分:消息本身。帶附件的電子通常至少由兩部分組成:消息和附件。這樣,帶兩個附件的郵件由三部分組成:消息,第一個附件和第二個附件。
帶附件的電子郵件的不同部分之間用分界線來分隔。分界線在Content-type頭中定義。郵件的每個新部分以兩個連字號(--)和分界線開始。最后一個分界線后也有兩個連字號,表示這個郵件中沒有其它的部分了。
在每個分界線后有一些行,用來告訴郵件程序這個部分的內(nèi)容的類型。比如,看看上面例子中第一個分界線后面的兩行--以Content-type: text/plain開頭的行。這些行說明后面的部分是ISO-8859-1字符集的純文本。跟在第二個分界線后的行告訴郵件程序現(xiàn)在的部分是一個HTML文件,它的名字是"attachment.html"。
Content-disposition這持告訴郵件程序如果可能就以內(nèi)嵌的方式顯示附件。現(xiàn)在新的郵件程序會在消息后顯示HTML的內(nèi)容。如果Content-disposition被設為attachment,那么郵件程序就不會顯示HTML文件的內(nèi)容,而是顯示一個連接到文件的圖標(或其它的類似的東西)。收件人要看附件的內(nèi)容,必須點擊這個圖標。一般情況下,如果附件是一些文本(包含HTML),Content-disposition會被設為inline,這是因為現(xiàn)在大部分郵件程序能夠不借助其它瀏覽器而直接顯示附件(文本)的內(nèi)容。如果附件不是文本(比如圖片或其它類似的內(nèi)容),Content-disposition就設為attachment。
2. 用PHP生成帶附件的電子郵件
這里一個例子,告訴你如果把一個定義好的HTML文件加為郵件的附件:
<?php # 我們首先寫實際的消息內(nèi)容 $emailBody = "This is text that goes into the body of the email.";
# 然后我們要作為附件的HTML文件 $attachment = "<html> <head> <title>The attached file</title> </head> <body> <h2>This is the attached HTML file</h2> </body> </html>";
# 建立在郵件中分隔不同部分的分界線。 # 基本上,分界線可以是任意的字符串。 # 但是重要的一點是確定一個寫郵件的人 # 這會隨意寫出的字符串,所以我們用 # uniqid函數(shù)來產(chǎn)生一個隨機的字符串。 $boundary = uniqid( "");
# 現(xiàn)在我們要建立郵件頭。不要忘了插入 # Content-type頭來說明這個郵件包含一個或更多的附件。 $headers = "From: someone@example.com Content-type: multipart/mixed; boundary=\"$boundary\"";
# 好,現(xiàn)在我們已經(jīng)有了郵件的所有內(nèi)容。 # 下一件事是修改郵件的主體。 $emailBody = "--$boundary Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 8bit
$emailBody
--$boundary Content-type: text/html; name=attachment.html Content-disposition: inline; filename=attachment.html Content-transfer-encoding: 8bit
$attachment
--$boundary--";
# 現(xiàn)在可以把郵件發(fā)出去了 mail( "person@eksempel.dk", "The subject", $emailBody, $headers); ?>
3. 把用戶上傳的文件作為附件
你也許會覺得上面的例子難以理解,但下面...。在下面的例子中事情更難了,因為我們要用一個表單讓用戶上傳他們的文件,并把這個文件作為我們要發(fā)的郵件的附件。麻煩的是我們不能預先知道文件的MIME類型。在前面的例子中,我們已經(jīng)知道該它是一個HTML文件,所以給這個附件設置Content-type頭是很簡單的。在下面的例子中,MIME類型可能是任意的,因為用戶可能會上傳一個HTML文件,一個PNG文件,一個vCard文件,或者其它的東西。讓我們來看看例子:
<?php # 現(xiàn)在我們來生成表單。在產(chǎn)生可以上傳文件的表單時, # 不要忘了把<form>標簽的"enctype"屬性設為"multipart/form-data". echo "<form action='$PHP_SELF' enctype='multipart/form-data' method='post'>\n"; echo "<input type='text' name='from'><br>\n"; echo "<input type='text' name='to'><br>\n"; echo "<input type='text' name='subject'><br>\n"; echo "<input type='file' name='attachment'><br>\n"; echo "<textarea name='body'></textarea><br>\n"; echo "<input type='submit' name='send' value='Send'>\n"; echo "</form>\n";
# 如果用戶已經(jīng)按了"Send"按鈕" if ($send) { # 定義分界線 $boundary = uniqid( "");
# 生成郵件頭 $headers = "From: $from Content-type: multipart/mixed; boundary=\"$boundary\"";
# 確定上傳文件的MIME類型 if ($attachment_type) $mimeType = $attachment_type; # 如果瀏覽器沒有指定文件的MIME類型, # 我們可以把它設為"application/unknown". else $mimeType = "application/unknown";
# 確定文件的名字 $fileName = $attachment_name;
# 打開文件 $fp = fopen($attachment, "r"); # 把整個文件讀入一個變量 $read = fread($fp, filesize($attachment));
# 好,現(xiàn)在變量$read中保存的是包含整個文件內(nèi)容的文本塊。 # 現(xiàn)在我們要把這個文本塊轉(zhuǎn)換成郵件程序可以讀懂的格式 # 我們用base64方法把它編碼 $read = base64_encode($read);
# 現(xiàn)在我們有一個用base64方法編碼的長字符串。 # 下一件事是要把這個長字符串切成由每行76個字符組成的小塊 $read = chunk_split($read);
# 現(xiàn)在我們可以建立郵件的主體 $body = "--$boundary Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 8bit
$body
--$boundary Content-type: $mimeType; name=$fileName Content-disposition: attachment; filename=$fileName Content-transfer-encoding: base64
$read
--$boundary--";
# 發(fā)送郵件 mail($to, $subject, $body, $headers); } ?>
這就是全部內(nèi)容。如果你不能很好地理解上面的例子,我的建議是給你自己發(fā)送幾個帶附件的郵件,然后仔細研究郵件的源代碼。
|