[英]Processing e-mails that are word wrapped (Content-Type: text/plain)
我正在嘗試將電子郵件處理到我的應用程序中,並且一切似乎都正常工作,直到我收到一封來自用戶的電子郵件,該用戶的郵件服務器正在強制對郵件文本進行自動換行。 我知道自動換行是 RFC 規范的一部分,所以我只是在尋找處理它的最佳方法以獲得顯示良好的消息。
原始電子郵件:
這是我的主要問題。 當我 email 一條消息時,文本被分解得相當奇怪。 它幾乎看起來好像消息本身被破壞了。 我不確定為什么會這樣,因為我原來的 email 看起來一點也不像。
這是收到的電子郵件的樣子(標有 CRLF 以顯示郵件服務器插入它們的位置):
這是我的主要問題。 當我email發消息時,文字被打散而CRLF
奇怪。 它幾乎看起來好像消息本身被破壞了。 我不確定 CRLF
為什么會這樣,因為我原來的 email 看起來一點也不像 CRLF
那。
我的處理代碼通過以下運行,然后將結果插入數據庫。
$dirty_string = nl2br($dirty_string);
$config = HTMLPurifier_Config::createDefault();
$config->set('AutoFormat.RemoveEmpty', 'true');
$config->set('AutoFormat.RemoveEmpty.RemoveNbsp', 'true');
$config->set('HTML.Allowed', 'a[href],br,p');
$purifier = new HTMLPurifier($config);
$clean_string = $purifier->purify($dirty_string);
以下是顯示的結果。 如果我頁面上的 div 不夠寬,瀏覽器會自動將其自動換行,但 nl2br() 的換行符會導致下一行變短。
這是我的主要問題。 當我email留言時,正文是
寧願分手
奇怪。 它幾乎看起來好像消息本身是
破碎的。 我不確定
為什么會這樣,因為我原來的 email 看起來
什么都不像
那。
我想也許我可以將雙 CRLF 更改為新段落並去除所有單個 CRLF 以將這些行連接成一個自動換行可以正確顯示的單行。 但是,如果有人在電子郵件中發布了以下項目符號列表,則會破壞列表。
這是我的清單 CRLF
- 第 1 項 CRLF
- 第 2 項 CRLF
ETC...
任何幫助將不勝感激。
郵件解析可能是一個典型的問題示例,它看起來很簡單,但實際上充滿了破壞簡單解析器的古怪邊緣情況。 然而,這也不完全是一個新問題,所以有很多現有的解決方案都可以正常工作。 一些選項:
也許您已經編寫了一個很棒的解析器,只需要這個小改動就可以完美,但更有可能的是,通過使用現有的工具來完成這項工作,您會節省很多時間和心痛。
這個怎么樣:對於下一行包含單詞並且不以空白字符開頭的任何行(例如列表中的縮進),檢查該行的長度是否在 65 到 80 個字符之間。 如果是,請刪除尾隨的 CR(如果行尾不包含空格或標點符號,則添加一個空格)。 這將得到你的大部分自動換行情況,而不會影響你的大部分列表。
您可以嘗試使用TinyMCE編輯器查看電子郵件信息。 它將正確格式化。 我已經使用 TinyMCE 幾次輸入數據並將其保存到數據庫中,無論格式多么奇怪,每次我檢索數據后它都會正確顯示。
像這樣的 hack 怎么樣:刪除 78 的倍數的任何位置的 CLRF 字符(+ 說 5 個字符來說明這個事實: the mail server won't just cut a line mid-word
)。
所以你會在這些位置尋找 CLRF 字符:
78
或79或80或81或82或83和156
或157或158或159或160或161和這當然是假設最長的單詞長度為 5 個字符。 您應該根據需要解析的電子郵件進行調整。
這是一個 function 可以很好地完成這項工作:
function PlaintextEmailBrokenLineCombine($lineSet, $startIndex = 0) {
$result = '';
$lineCount = count($lineSet);
for($i=$startIndex; $i < $lineCount; $i++) {
$thisLine = $lineSet[$i];
$nextLine = ($i < $lineCount-1 ? $lineSet[$i+1] : '');
$nextLineFirstWord = substr($nextLine, 0, strpos($nextLine, ' '));
$lineSeparator = "\n"; // we assume until we detect invocation of the 78char rule
if(strlen($thisLine) + strlen($nextLineFirstWord) + 1 > 75) {
// A line break was PROBABLY put in here where a space once was, so switch back:
$lineSeparator = ' ';
}
$result .= $thisLine . ($i == $lineCount-1 ? '' : $lineSeparator); // no separator for the last line
}
return $result;
}
它有點深奧,因為它需要來自純文本 email 的行數組。這是用法:
$Parser = new MimeMailParser();
$Parser->setText($rawEmailText);
$plaintext = $Parser->getMessageBody('text'); // or however you get it, many ways
$lineSet = explode("\n", $plaintext);
$niceText = PlaintextEmailBrokenLineCombine($lineSet);
$niceText 是你想要的:這是一種非常准確的方式來獲取你想要的文本,而那些討厭的服務器添加的換行符消失了,並被原來的空格所取代。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.