函數 imap_fetchbody() 似乎無法取得 message/rfc822 部分的子部分。我曾遇到取得以該部分轉寄的附件的問題,因為 imap_fetchstructure() 提供的物件會假設該部分由字串 "2.1.2.1.2" 表示。
所以我寫了這組函數,它會剖析原始訊息內文,並建立一個陣列,其結構與 imap_fetchstructure() 提供的結構對應。函數 mail_fetchpart()(請見下方)將會在陣列上運作,並傳回我無法使用 imap_fetchbody() 取得的那些部分。
此函數的用法範例:mail_fetchpart($mbox, 2, "2.1.2.1.2");
注意:如果訊息不包含多個部分,則可以使用部分字串 "1" 存取訊息的內文。
我還有更多用於剖析和解碼訊息的函數,請寄電子郵件給我。
// 根據 $part 中的字串取得訊息某部分的內文
// $part 中的字串
function mail_fetchpart($mbox, $msgNo, $part) {
$parts = mail_fetchparts($mbox, $msgNo);
$partNos = explode(".", $part);
$currentPart = $parts;
while(list ($key, $val) = each($partNos)) {
$currentPart = $currentPart[$val];
}
if ($currentPart != "") return $currentPart;
else return false;
}
// 如果訊息是以
// multipart mime 訊息的形式在內文中給出,則將其分割並傳回各部分,
// 如果找不到任何部分,則傳回 false
function mail_mimesplit($header, $body) {
$parts = array();
$PN_EREG_BOUNDARY = "Content-Type:(.*)boundary=\"([^\"]+)\"";
if (eregi ($PN_EREG_BOUNDARY, $header, $regs)) {
$boundary = $regs[2];
$delimiterReg = "([^\r\n]*)$boundary([^\r\n]*)";
if (eregi ($delimiterReg, $body, $results)) {
$delimiter = $results[0];
$parts = explode($delimiter, $body);
$parts = array_slice ($parts, 1, -1);
}
return $parts;
} else {
return false;
}
}
// 傳回包含給定部分所有子部分的陣列
// 如果找不到子部分,則傳回目前部分的內文
// 如果找不到子部分,則傳回目前部分的內文
// 目前部分的內文
function mail_mimesub($part) {
$i = 1;
$headDelimiter = "\r\n\r\n";
$delLength = strlen($headDelimiter);
// 取得目前部分的標頭和內文
$endOfHead = strpos( $part, $headDelimiter);
$head = substr($part, 0, $endOfHead);
$body = substr($part, $endOfHead + $delLength, strlen($part));
// 根據 rfc822 檢查是否為訊息
if (stristr($head, "Content-Type: message/rfc822")) {
$part = substr($part, $endOfHead + $delLength, strlen($part));
$returnParts[1] = mail_mimesub($part);
return $returnParts;
// 如果不是訊息,則取得子部分並遞迴呼叫函式
} elseif ($subParts = mail_mimesplit($head, $body)) {
// 取得更多子部分
while (list ($key, $val) = each($subParts)) {
$returnParts[$i] = mail_mimesub($val);
$i++;
}
return $returnParts;
} else {
return $body;
}
}
// 取得一個包含電子郵件所有部分的內容的陣列
// 陣列的結構對應於
// imap_fetchstructure 可用的結構
function mail_fetchparts($mbox, $msgNo) {
$parts = array();
$header = imap_fetchheader($mbox,$msgNo);
$body = imap_body($mbox,$msgNo, FT_INTERNAL);
$i = 1;
if ($newParts = mail_mimesplit($header, $body)) {
while (list ($key, $val) = each($newParts)) {
$parts[$i] = mail_mimesub($val);
$i++;
}
} else {
$parts[$i] = $body;
}
return $parts;
}