6

我正在尝试将电子邮件处理到我的应用程序中,并且一切似乎都工作正常,直到我收到来自其邮件服务器正在强制邮件文本自动换行的用户的电子邮件。我知道自动换行是 RFC 规范的一部分,所以我只是在寻找处理它的最佳方法,以得到一个显示良好的消息。

原始电子邮件:

这是我的主要问题。当我通过电子邮件发送消息时,文本被分解得相当奇怪。它几乎看起来好像消息本身已损坏。我不确定为什么会这样,因为我的原始电子邮件看起来不像那样。

这是收到的电子邮件的样子(标有 CRLF 以显示邮件服务器将它们插入的位置):

这是我的主要问题。
当我通过电子邮件发送消息时,文本被奇怪地分解为 CRLF 。它几乎看起来好像消息本身已损坏。我不确定 CRLF
为什么会这样,因为我的原始电子邮件看起来不像 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() 的换行会导致下一行变短。

这是我的主要问题。当我通过电子邮件发送消息时,文本被
分解得相当
奇怪。它几乎看起来好像消息本身已
损坏。我不确定
为什么会这样,因为我的原始电子邮件看起来
不像
那样。

我想也许我可以将双 CRLF 更改为新段落并剥离所有单个 CRLF 以将这些行连接到一个可以正确显示自动换行的单行。但是,如果有人在电子邮件中发布以下项目符号列表,那将破坏该列表。

这是我的清单 CRLF
- 第 1 项 CRLF
- 第 2 项 CRLF
等...

任何帮助将不胜感激。

4

5 回答 5

1

邮件解析可能是一个看似简单的问题的典型示例,但实际上充满了破坏简单解析器的奇怪边缘情况。然而,这也不完全是一个新问题,因此有很多现有的解决方案可以正常工作。一些选项:

也许您已经编写了一个出色的解析器,只需要这一点小改动即可完美,但更有可能通过使用现有工具来完成这项工作,您将节省大量时间和心痛。

于 2012-04-09T18:44:55.917 回答
0

Here's a function that does the job pretty well:

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;
}

It's a little esoteric because it expect an array of lines from the plain text email. Here's the usage:

$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 is what you want: it's a pretty accurate way of getting the text you want with those pesky server-added line breaks gone, and replaced with the original spaces.

于 2012-10-18T15:24:39.510 回答
0

像这样的 hack 怎么样:删除 78 倍数的任何位置的 CLRF 字符(+ 说 5 个字符来解释这个事实:)the mail server won't just cut a line mid-word

所以你会在这些位置寻找 CLRF 字符:

  • 78 7980818283
  • 156 157158159160161
  • 很快。

这当然是假设最长的单词长度为 5 个字符。您应该根据需要解析的电子邮件进行调整。

于 2012-04-11T19:49:12.083 回答
0

您可以尝试使用TinyMCE编辑器查看电子邮件。它将正确格式化。我已经使用 TinyMCE 输入数据并将其保存到数据库中几次,并且每次在我检索数据后正确显示它,无论格式多么奇怪。

于 2012-04-07T18:43:28.693 回答
0

怎么样:对于下一行包含单词且不以空格字符开头的任何行(例如列表中的缩进),检查该行的长度是否在 65 到 80 个字符之间。如果是,请删除尾随 CR(如果行尾不包含空格或标点符号,则添加空格)。这将获得您的大部分自动换行案例,并保留您的大部分列表。

于 2012-04-06T22:04:55.380 回答