2010-09-03 24 views
3

我正在研究一個PHP腳本,它讀取電子郵件的內容,並提取某些信息以存儲在數據庫中。preg_match模式找到<html>和</html>之間的字符串的內容標籤

使用imap_fetchbody($ imap_stream,$ msg_number,1),我可以得到電子郵件的正文。在某些情況下(尤其是電子郵件發送,通過手機短信),電子郵件的正文是這樣的:

===------=_Part_110734_170079945.9852 
Content-Type: text/html;charset=UTF-8; 
Content-Transfer-Encoding: 7bit 
Content-Disposition: inline 

<html> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     <title>Multimedia Message</title> 
    </head> 
    <body leftmargin="0" topmargin="0"> 


       <tr height="15" style="border-top: 1px solid #0F7BBC;"> 
        <td> 
         SMS to email test 
        </td> 
       </tr> 


    </body> 
</html> 


------=_Part_110734_170079945.9852--=== 

我想拔出電子郵件的「內容」。所以,我的計劃是這樣的:

檢查身體是否包含「html」標記。如果沒有,我可以正常閱讀(不是HTML電子郵件)。

如果是這樣,請提取「html」標籤之間的內容。然後,消除所有其他的HTML標籤,剩下的就是「內容」。

但是,當涉及到正則表達式模式時,我非常無能。

我嘗試這樣做:

$pattern = '/<html[^>]*>(.*?)<\/html>/i'; 
preg_match($pattern, $body, $matches); 
// my 'content' should be in $matches[1] 

但沒有工作(可能是因爲$體內含有換行符和其他空白)。所以然後我試過這個:

$pattern = '/<html[^>]*>([.\s]*?)<\/html>/i'; 
preg_match($pattern, $body, $matches); 

但那也沒有效果。

那麼,我可以用什麼$模式來提取「html」標籤之間的所有文本?

更新:我偶然到一個解決方法 - 去除所有的空白第一:

$body = preg_replace('/\s\s+/', ' ', $body); 
$pattern = '/<body[^>]*>(.*?)<\/body>/'; 

我懷疑這是不是最快,最有效的方法,但它的作品,並且是最好的我到目前爲止。儘管如此,我還是會喜歡更好的解決方案。

更新2:由於Gumbo的建議,我試着更深入地挖掘電子郵件的結構以找到我正在尋找的部分,而不是嘗試正則表達式HTML。我終於找到了這個:http://docstore.mik.ua/orelly/webprog/pcook/ch17_04.htm,它解釋瞭如何完成我所需要的。

+3

爲什麼不使用其他[IMAP函數](http://php.net/ref.imap)來獲取多部分主體? – Gumbo 2010-09-03 19:14:54

+0

Gumbo - 實際上,我是(雖然也許不正確)。我使用imap_fetchbody($ imap,$ msg_number,1.1)。如果返回一個空字符串,我使用imap_fetchbody($ imap,$ msg_number,1)。對於正常的郵件,這正是我想要的,而不是所有的HTML。我遇到的問題特定於從手機發送的短信作爲電子郵件。在這種情況下,無論如何,我都會收到我上面發佈的文字。有一個更好的方法嗎? – mattstuehler 2010-09-03 19:26:33

+0

@mattstuehler:'imap_fetchbody'期望第三個參數是一個字符串。你試過'imap_fetchbody($ imap,$ msg_number,'1.1')'? – Gumbo 2010-09-03 19:35:56

回答

2

[.\s]意味着要麼文字.或空白字符。您需要的是(.|\s)[\s\S],或者您只需將s modifier設置爲.也匹配換行符。

但是除此之外,you should not use regular expressions to match HTML。部分HTML不是常規的,因此您不能使用正則表達式來描述它。

但除此之外,當您有不同的分隔符時,您不應該嘗試猜測多部分內容的範圍。但這些不是<html>…</html>。因爲如果他們失蹤了怎麼辦?那麼你的嘗試將失敗。使用消息本身定義的分隔符:boundary值。因此,使用邊界來獲取零件,並在第一個CRLF + CRLF序列中拆分它們以將標題與正文分開。

但除此之外,你爲什麼不使用IMAP functions來獲得身體?我不熟悉PHP的IMAP API,但可能有一個功能完全符合您的需求。

3
$pattern = '/<html[^>]*>([^\00]*?)<\/html>/i'; 

這隻會打破,如果有在內容0x00字節,這不應該是。

+0

完美!感謝這個代碼! – 2013-05-13 04:45:17

1

你只需要添加s modifier允許.匹配換行符:

$pattern = '/<html[^>]*>(.*?)<\/html>/si'; 
preg_match($pattern, $body, $matches); 
相關問題