POP3
Classes that implement MIME decoding
(Author: Chen Junqing October 24, 2000 15:11)
A class that implements MIME decoding
This class implements decoding method is decode ($head =null, $body =null, $content _num=-1), in order to handle the convenience, the input is two character array, in our previous article, the Pop class used to receive is two such an array, One is the message header content, one is the body content of the message. Confined to the space, not to do a detailed explanation, the realization of the idea is similar to the Pop class described in the previous article. Please refer to the comments.
A large number of regular expressions are used in this class, and for unfamiliar readers, refer to the relevant data of the regular expressions.
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;
Message in the message header section after decoding:
var $body;
After decoding, the resulting body data is an array.
var $body _type; Body type
var $tem _num=0;
var $get _content_num=0;
var $body _temp=array ();
var $body _code_type;
var $boundary;
These are some of the methods used in some of the global temporary variables, because PHP can not do a good encapsulation, so can only be placed here to define
var $err _str; Error message
var $debug = 0; Debug tags
var $month _num=array ("Jan" =>1, "Feb" =>2, "Mar" =>3, "APR" =>4, "may" =>5, "June" =>6, "Jul" =>7,
"=>8", "Sep" =>9, "Oct" =>10, "Nov" =>11, "Dec" =>12); Convert the English month into a numeric month
function decode ($head =null, $body =null, $content _num=-1)//The Main method of the call, $head and $body are two arrays, $content _num represents when the body has multiple parts, Only the content of the specified part is removed to improve efficiency, the default is-1, which means decoding the entire content, if the decoding succeeds, the method returns True
{
if (! $head and! $body)
{
$this->err_str= "No header and content for the specified message!";
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= "passed the wrong argument, usage: New Decode_mail (head,body) two parameters are arrays";
return false;
}
}
function Decode_head ($head)//message header content decoding, take out the message header meaningful content
{
$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]); If there is encoded content, then decoding, decoding function is described above decode_mime ()
$pos =strpos ($head [$i], ":");
$summ =substr ($head [$i],0, $pos);
$content =substr ($head [$i], $pos + 1); Separate the message header information from the content
if ($this->debug) echo $summ. ":----:". $content. "
";
Switch (Strtoupper ($SUMM))
{
Case ' from '://Sender's address and name (may not have a name, only address information)
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;
No e-mail address from Sender
}
Break
Case ' to '://Recipient's address and name (may not have a name)
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;
No separate recipient's email address
}
Break
Case "Date"://Send date, for ease of handling, this returns a Unix timestamp, can be used date ("y-m-d", $this->mail_time) to get the general format of the day
$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"://Email subject
$this->subject= $content;
Break
Case "reply_to"://Reply to address (may not be)
if (Ereg ("< ([^>]+) >", $content, $reg))
$this->reply_to= $reg [1];
else $this->reply_to= $content;
Break
Case "Content-type"://CONTENT type for the entire message, eregi ("([^;] *); ", $content, $reg);
$this->body_type=trim ($reg [1]);
if (eregi ("multipart", $content))//If it is a multipart type, get the delimiter
{
while (!eregi (' boundary=\ ' (. *) \ "', $head [$i], $reg) and $head [$i])
$i + +;
$this->boundary= $reg [1];
}
else//For general body type, direct access to its encoding method
{
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"://CC to ...
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) = = "")//If no reply address is specified, the reply-to address is the sender's address
$this->reply_to= $this->from_mail;
}//End Function Define
function decode_body ()//body decoding, which uses a lot of message header decoding information obtained
{
$i = 0;
if (!eregi ("multipart", $this->body_type))//If it is not a composite type, it can be decoded directly
{
$tem _body=implode ($this->body_temp, "\ r \ n");
Switch (Strtolower ($this->body_code_type))//Body_code_type, the body encoding method, obtained by the message header information
{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]= "Hypertext text";
Break
Case "Text/plain":
$this->body[$this->tem_num][name]= "text body";
Break
Default
$this->body[$this->tem_num][name]= "Unknown Body";
}
$this->body[$this->tem_num][size]=strlen ($tem _body);
$this->body[$this->tem_num][content]= $tem _body;
unset ($tem _body);
}
else//If it is a composite type
{
$this->body=array ();
$this->tem_num=0;
$this->decode_mult ($this->body_type, $this->boundary,0); Calling the decoding method of a composite type
}
}
function Decode_mult ($type, $boundary, $begin _row)//This method implements the decoding of compound type message body by recursive method, the message source file is taken from the body_temp array, and the type, delimiter and The start pointer in the BODY_TEMP array
{
$i = $begin _row;
$lines =count ($this->body_temp);
while ($i < $lines)//This is a part of the end of the logo;
{
while (!eregi ($boundary, $this->body_temp[$i])//Find a start identity
$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]); The type that gets this part is milt or text ....
if (eregi ("multipart", $sub _type))//The sub-part is also a plurality of parts;
{
while (!eregi (' boundary=\ ' ([^\]*) \ "', $this->body_temp[$i], $reg) and $this->body_temp[$i])
$i + +;
$sub _boundary= $reg [The delimiter of the 1];//sub-section;
$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]); Encoding method
$comm. = $this->body_temp[$i]. " \ r \ n ";
$i + +;
}//Comm is the description part of the encoding
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))//image identifier.
$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]= "Hypertext text";
Break
Case "Text/plain":
$this->body[$this->tem_num][name]= "text body";
Break
Default
$this->body[$this->tem_num][name]= "Unknown Body";
}
The next line starts retrieving the body
if ($this->get_content_num==-1 or $this->get_content_num== $this->tem_num)//Determine if this part is needed. -1 means all
{
$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 has been given in the above, skipped here.
}
}//End Class define
A special note here is the decoding of the images used in the HTML body. When you send an HTML-formatted body, you will encounter problems with how the image is routed. A picture is a label in an HTML document, and the key is where the source file comes from. Many messages are handled using an absolute URL identifier, which is a tag in the HTML body of the message, so that when you read the message, the message reader (usually an embedded browser) automatically downloads the image from the web, but if the message is received, the connection to the Internet is broken, The picture will not display properly.
So the better way is to put the picture in the mail and send it together. In MIME encoding, the relationship between the picture and the body is described, in addition to the multipart/related MIME header information mentioned above, a Content-id: property is used to establish a relationship between the picture and the HTML body. A picture in an HTML document is encoded with a content-id:122223443556dsdf@ntsever-like attribute in its MIME header, and 122223443556dsdf@ntsever is a unique identifier, in an HTML document, tags are modified to, in fact, in the decoding of the HTML body of these tags to be modified to point to the decoded image of the specific path. However, given the specific decoding process for the image will be different processing, so in this decoding class, the HMTL body of the label is not modified. So in the actual use of this class, for the image of the HTML text, but also need some processing. The picture in the body can be saved with temporary files, or it can be saved with a database.
We have now introduced the principle of POP3 receiving mail and MIME decoding. Here is a small program that uses these two classes:
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 "Shared". $rec->messages. " Letter, Total ". $rec->size." BYTE size
";
if ($rec->messages>0)
{
if (! $rec->listmail ()) Die ($rec->err_str);
echo "The following are the contents of the letter:
";
for ($i =1; $i <=count ($rec->mail_list); $i + +)
{
echo "letter". $rec->mail_list[$i][num]. ", Size:". $rec->mail_list[$i][size]. "
";
$rec->getmail ($rec->mail_list[$i][num]);
$decoder->decode ($rec->head, $rec->body);
echo "
Contents of the message header:
";
echo $decoder->from_name. " (". $decoder->from_mail.") To ". Date" ("Y-m-d h:i:s", $decoder->mail_time). "Send". $decoder->to_name. " (". $decoder->to_mail.");
echo "\ n
CC: ";
if ($decoder->cc_to) echo $decoder->cc_to;else echo "None";
echo "\ n
Subject: ". $decoder->subject;
echo "\ n
Reply to: ". $decoder->reply_to;
echo "
Message body:
";
echo "Body type:". $decoder->body_type;
echo "
The contents of the text: ";
for ($j =0; $j body); $j + +)
{
echo "\ n
Type: ". $decoder->body[$j][type];
echo "\ n
Name: ". $decoder->body[$j][name];
echo "\ n
Size: ". $decoder->body[$j][size];
echo "\ n
content_id: ". $decoder->body[$j][content_id];
echo "\ n
Body character set ". $decoder->body[$j][char_set];
echo "
echo "
";
}
$rec->dele ($i);
}
}
$rec->close ();
?>
If you want to get complete source code of friends, please contact me: boss_ch@netease.com
<全文完>