引用された返信テキストからメールのテキストを解析する方法を見つけようとしています。私は通常、電子メールクライアントが「そのような日付にそう書かれた」を付けるか、行の前に山かっこを付けることに気づきました。残念ながら、誰もがこれを行うわけではありません。プログラムで返信テキストを検出する方法について誰かが何か考えを持っていますか?このパーサーの作成にはC#を使用しています。
引用された返信テキストからメールのテキストを解析する方法を見つけようとしています。私は通常、電子メールクライアントが「そのような日付にそう書かれた」を付けるか、行の前に山かっこを付けることに気づきました。残念ながら、誰もがこれを行うわけではありません。プログラムで返信テキストを検出する方法について誰かが何か考えを持っていますか?このパーサーの作成にはC#を使用しています。
回答:
私はこれについてもっと多くの検索をしました、そしてこれが私が見つけたものです。これを行うには、基本的に2つの状況があります。スレッド全体がある場合とない場合です。私はそれをそれらの2つのカテゴリーに分けます:
スレッドがある場合:
一連の電子メール全体がある場合は、削除するものが実際に引用されたテキストであるという非常に高いレベルの保証を実現できます。これを行うには2つの方法があります。1つは、メッセージのMessage-ID、In-Reply-To ID、およびThread-Indexを使用して、個々のメッセージ、その親、およびメッセージが属するスレッドを判別できます。詳細については、RFC822、RFC2822、スレッドに関するこの興味深い記事、またはスレッドに関するこの記事を参照してください。。スレッドを再構築したら、外部テキスト(To、From、CCなどの行など)を削除して完了です。
使用しているメッセージにヘッダーがない場合は、類似性マッチングを使用して、電子メールのどの部分が返信テキストであるかを判別することもできます。この場合、繰り返されるテキストを決定するために類似性マッチングを行うことに固執しています。この場合、あなたはに見たいと思うかもしれませんレーベンシュタイン距離アルゴリズムのようなコードプロジェクトで、この1またはこのいずれか。
いずれにせよ、スレッド化プロセスに興味がある場合は、電子メールスレッドの再構築に関するこのすばらしいPDFを確認してください。
スレッドがない場合:
スレッドからのメッセージが1つしかない場合は、見積もりが何であるかを推測する必要があります。その場合、私が見たさまざまな見積もり方法は次のとおりです。
そこからテキストを削除すれば完了です。これらのいずれかの欠点は、送信者が引用されたテキストの上に返信を置き、それをインターリーブしなかったと想定していることです(インターネットの古いスタイルのように)。それが起こったら、頑張ってください。これが皆さんのお役に立てば幸いです。
まず第一に、これはトリッキーな作業です。
さまざまな電子メールクライアントから一般的な応答を収集し、それらを解析するために正しい正規表現(またはその他)を準備する必要があります。Outlook、Thunderbird、Gmail、Apple Mail、mail.ruからの回答を集めました。
正規表現を使用して、次の方法で応答を解析しています。式が一致しなかった場合は、次の式を使用しようとします。
new Regex("From:\\s*" + Regex.Escape(_mail), RegexOptions.IgnoreCase);
new Regex("<" + Regex.Escape(_mail) + ">", RegexOptions.IgnoreCase);
new Regex(Regex.Escape(_mail) + "\\s+wrote:", RegexOptions.IgnoreCase);
new Regex("\\n.*On.*(\\r\\n)?wrote:\\r\\n", RegexOptions.IgnoreCase | RegexOptions.Multiline);
new Regex("-+original\\s+message-+\\s*$", RegexOptions.IgnoreCase);
new Regex("from:\\s*$", RegexOptions.IgnoreCase);
最後に引用を削除するには:
new Regex("^>.*$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
これが私の小さなテスト応答のコレクションです(サンプルを---で割ったもの):
From: test@test.com [mailto:test@test.com]
Sent: Tuesday, January 13, 2009 1:27 PM
----
2008/12/26 <test@test.com>
> text
----
test@test.com wrote:
> text
----
test@test.com wrote: text
text
----
2009/1/13 <test@test.com>
> text
----
test@test.com wrote: text
text
----
2009/1/13 <test@test.com>
> text
> text
----
2009/1/13 <test@test.com>
> text
> text
----
test@test.com wrote:
> text
> text
<response here>
----
--- On Fri, 23/1/09, test@test.com <test@test.com> wrote:
> text
> text
よろしく、Oleg Yaroshevych
正規表現をありがとう、ゴレグ!本当に助かりました。これはC#ではありませんが、そこにいるグーグルのために、これが私のRuby解析スクリプトです:
def extract_reply(text, address)
regex_arr = [
Regexp.new("From:\s*" + Regexp.escape(address), Regexp::IGNORECASE),
Regexp.new("<" + Regexp.escape(address) + ">", Regexp::IGNORECASE),
Regexp.new(Regexp.escape(address) + "\s+wrote:", Regexp::IGNORECASE),
Regexp.new("^.*On.*(\n)?wrote:$", Regexp::IGNORECASE),
Regexp.new("-+original\s+message-+\s*$", Regexp::IGNORECASE),
Regexp.new("from:\s*$", Regexp::IGNORECASE)
]
text_length = text.length
#calculates the matching regex closest to top of page
index = regex_arr.inject(text_length) do |min, regex|
[(text.index(regex) || text_length), min].min
end
text[0, index].strip
end
これまでのところ、かなりうまく機能しています。
これを行う最も簡単な方法は、次のようなマーカーをコンテンツに配置することです。
---この行の上に返信してください---
お気づきのことと思いますが、引用されたテキストを解析することは簡単な作業ではありません。さまざまな電子メールクライアントがさまざまな方法でテキストを引用するからです。この問題を適切に解決するには、すべての電子メールクライアントを考慮してテストする必要があります。
Facebookはこれを行うことができますが、プロジェクトに大きな予算がない限り、おそらくできません。
Olegは、正規表現を使用して問題を解決し、「2012年7月13日、13:09にxxxが書き込みました:」というテキストを見つけました。ただし、多くの人が行うように、ユーザーがこのテキストを削除したり、電子メールの下部に返信したりすると、このソリューションは機能しません。
同様に、電子メールクライアントが別の日付文字列を使用している場合、または日付文字列が含まれていない場合、正規表現は失敗します。
-- Please reply above this line. DO NOT REMOVE IT! --
。また、私が経験したことは、一部の電子メールクライアントはxxx wrote on <datetime>:
引用全体の前に、したがってその行の前に行を追加するため、常に機能するとは限らないということです。この行は正規表現で解析できますが、電子メールクライアントが異なるため、言語や形式が異なる場合があります。
電子メールには返信の普遍的な指標はありません。あなたができる最善のことは、最も一般的なパターンを見つけて、それらに出くわしたときに新しいパターンを解析することです。
引用されたテキスト内に返信を挿入する人もいることを覚えておいてください(たとえば、私の上司は私が尋ねたのと同じ行で質問に答えます)。そのため、何をしても、保持したい情報が失われる可能性があります。
これが@hurshagrawalのRubyコードのC#バージョンです。Rubyのことはよくわからないので、うまくいかないかもしれませんが、正解だと思います。
public string ExtractReply(string text, string address)
{
var regexes = new List<Regex>() { new Regex("From:\\s*" + Regex.Escape(address), RegexOptions.IgnoreCase),
new Regex("<" + Regex.Escape(address) + ">", RegexOptions.IgnoreCase),
new Regex(Regex.Escape(address) + "\\s+wrote:", RegexOptions.IgnoreCase),
new Regex("\\n.*On.*(\\r\\n)?wrote:\\r\\n", RegexOptions.IgnoreCase | RegexOptions.Multiline),
new Regex("-+original\\s+message-+\\s*$", RegexOptions.IgnoreCase),
new Regex("from:\\s*$", RegexOptions.IgnoreCase),
new Regex("^>.*$", RegexOptions.IgnoreCase | RegexOptions.Multiline)
};
var index = text.Length;
foreach(var regex in regexes){
var match = regex.Match(text);
if(match.Success && match.Index < index)
index = match.Index;
}
return text.Substring(0, index).Trim();
}
これは良い解決策です。長い間検索して見つけました。
1つ追加すると、前述のように、これはケースワイズであるため、上記の式ではGmailとOutlook(2010)の応答が正しく解析されなかったため、次の2つの正規表現を追加しました。問題があれば教えてください。
//Works for Gmail
new Regex("\\n.*On.*<(\\r\\n)?" + Regex.Escape(address) + "(\\r\\n)?>", RegexOptions.IgnoreCase),
//Works for Outlook 2010
new Regex("From:.*" + Regex.Escape(address), RegexOptions.IgnoreCase),
乾杯
これは古い投稿ですが、githubに応答を抽出するRubylibがあることを知っているかどうかはわかりません。.NETを使用している場合は、https://github.com/EricJWHuang/EmailReplyParserに.NETがあります。
SigParser.comのAPIを使用すると、単一の電子メールテキスト文字列からの返信チェーン内のすべての分割された電子メールの配列が提供されます。したがって、10通のメールがある場合は、10通すべてのメールのテキストが表示されます。
詳細なAPI仕様はこちらでご覧いただけます。