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

メールの解析は、おそらく単純に見える問題の典型的な例ですが、実際には単純なパーサーを壊す奇妙なエッジケースで満たされています。ただし、これはまったく新しい問題ではないため、正常に機能する既存のソリューションはたくさんあります。いくつかのオプション:

おそらく、完璧にするためにこの1つの小さな変更が必要なだけの優れたパーサーを既に作成しているかもしれませんが、既存のツールを使用して作業を行うことで、多くの時間と労力を節約できる可能性があります。

于 2012-04-09T18:44:55.917 に答える
0

これはかなりうまく仕事をする関数です:

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

プレーンテキストの電子メールからの行の配列を想定しているため、少し難解です。使用法は次のとおりです。

$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 は必要なものです。これは、サーバーが追加した面倒な改行を削除し、元のスペースに置き換えて、必要なテキストを取得するかなり正確な方法です。

于 2012-10-18T15:24:39.510 に答える
0

次のようなハックはどうでしょうか: 78 の倍数の任意の位置にある CLRF 文字を削除します (+ この事実を説明するために 5 文字と言います: the mail server won't just cut a line mid-word)。

したがって、次の位置で CLRF 文字を探します。

  • 78 または79または80または81または82または83 AND
  • 156 または157または158または159または160または161 AND
  • すぐ。

もちろん、これは最長の単語の長さが 5 文字であることを前提としています。解析する必要がある電子メールに基づいて、これを微調整する必要があります。

于 2012-04-11T19:49:12.083 に答える
0

次の行に単語が含まれ、空白文字で始まらない行 (リストのインデントなど) については、行の長さが 65 ~ 80 文字であるかどうかを確認してください。その場合は、末尾の CR を削除します (行末にスペースや句読点が含まれていない場合はスペースを追加します)。これにより、ワード ラップ ケースのほとんどが取得され、ほとんどのリストはそのままになります。

于 2012-04-06T22:04:55.380 に答える
0

TinyMCEエディターを使用して電子メール メッセージを表示してみてください。正しくフォーマットされます。私は TinyMCE を数回使用してデータを入力し、それをデータベースに保存しましたが、フォーマットがどれほど奇妙であっても、データを取得した後は毎回正しく表示されました。

于 2012-04-07T18:43:28.693 に答える