Analizar el contenido del correo electrónico de la respuesta citada

Estoy intentando descubrir cómo analizar el texto de un correo electrónico desde cualquier texto de respuesta entre comillas que pueda incluir. Me he dado cuenta de que, por lo general, los clientes de correo electrónico escriben “En tal o cual fecha escriben tal o cual cosa” o anteponen las líneas con un corchete angular. Lamentablemente, no todos hacen esto. ¿Alguien tiene alguna idea sobre cómo detectar mediante progtwigción el texto de respuesta? Estoy usando C # para escribir este analizador.

Hice mucho más buscando en esto y esto es lo que encontré. Básicamente hay dos situaciones en las que haces esto: cuando tienes todo el hilo y cuando no lo haces. Lo dividiré en esas dos categorías:

Cuando tienes el hilo:

Si tiene toda la serie de correos electrónicos, puede lograr un nivel muy alto de seguridad de que lo que está eliminando es en realidad texto citado. Hay dos maneras de hacer esto. En primer lugar, podría usar el ID de mensaje, ID de respuesta e Índice de subprocesos del mensaje para determinar el mensaje individual, su padre y el subproceso al que pertenece. Para obtener más información al respecto, consulte RFC822 , RFC2822 , este interesante artículo sobre enhebrar , o este artículo sobre enhebrado . Una vez que haya vuelto a ensamblar el hilo, puede eliminar el texto externo (como las líneas A, De, CC, etc.) y listo.

Si los mensajes con los que está trabajando no tienen los encabezados, también puede usar la coincidencia de similitudes para determinar qué partes de un correo electrónico son el texto de respuesta. En este caso, tiene que hacer coincidir coincidencias para determinar el texto que se repite. En este caso, es posible que desee buscar en un algoritmo de distancia de Levenshtein como este en Code Project o este .

No importa qué, si está interesado en el proceso de subprocesamiento, consulte este excelente PDF sobre el reensamblado de hilos de correo electrónico .

Cuando no tienes el hilo:

Si solo tiene un mensaje del hilo, tendrá que intentar adivinar cuál es el presupuesto. En ese caso, aquí están los diferentes métodos de cotización que he visto:

  1. una línea (como se ve en outlook).
  2. Paréntesis angulares
  3. “—Mensaje original—”
  4. “En tal y tal día, Fulano escribió:”

Elimina el texto de allí hacia abajo y listo. La desventaja de cualquiera de estos es que todos suponen que el remitente colocó su respuesta sobre el texto citado y no lo intercalaba (como era el estilo anterior en Internet). Si eso sucede, buena suerte. Espero que esto ayude a algunos de ustedes por ahí!

En primer lugar, esta es una tarea difícil.

Debería recostackr respuestas típicas de diferentes clientes de correo electrónico y preparar expresiones regulares correctas (o lo que sea) para analizarlas. He recostackdo respuestas de Outlook, Thunderbird, Gmail, Apple Mail y Mail.ru.

Estoy usando expresiones regulares para analizar la respuesta de la siguiente manera: si la expresión no coincide, trato de usar la siguiente.

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

Para eliminar la cita al final:

 new Regex("^>.*$", RegexOptions.IgnoreCase | RegexOptions.Multiline); 

Aquí está mi pequeña colección de respuestas de prueba (muestras divididas por ):

 From: test@test.com [mailto:test@test.com] Sent: Tuesday, January 13, 2009 1:27 PM ---- 2008/12/26  > text ---- test@test.com wrote: > text ---- test@test.com wrote: text text ---- 2009/1/13  > text ---- test@test.com wrote: text text ---- 2009/1/13  > text > text ---- 2009/1/13  > text > text ---- test@test.com wrote: > text > text  ---- --- On Fri, 23/1/09, test@test.com  wrote: > text > text 

Un saludo, Oleg Yaroshevych

¡Gracias, Goleg, por los regexes! Realmente ayudado. Esto no es C #, pero para los googlers, aquí está mi script de análisis de 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 

Hasta ahora ha funcionado bastante bien.

Con mucho, la manera más fácil de hacerlo es colocando un marcador en su contenido, como:

— Responda arriba de esta línea —

Como sin duda ha notado, el análisis del texto entrecomillado no es una tarea trivial, ya que los diferentes clientes de correo electrónico citan el texto de diferentes maneras. Para resolver este problema correctamente, debe contabilizar y probar en cada cliente de correo electrónico.

Facebook puede hacer esto, pero a menos que su proyecto tenga un gran presupuesto, probablemente no pueda hacerlo.

Oleg resolvió el problema usando expresiones regulares para encontrar el “El 13 de julio de 2012, a las 13:09, xxx escribió:” texto. Sin embargo, si el usuario elimina este texto o responde en la parte inferior del correo electrónico, como hacen muchas personas, esta solución no funcionará.

Del mismo modo, si el cliente de correo electrónico utiliza una cadena de fecha diferente, o no incluye una cadena de fecha, la expresión regular fallará.

No hay un indicador universal de una respuesta en un correo electrónico. Lo mejor que puede hacer es tratar de detectar los patrones más comunes y analizar nuevos a medida que los encuentre.

Tenga en cuenta que algunas personas insertan respuestas dentro del texto citado (Mi jefe, por ejemplo, responde preguntas en la misma línea que yo les pregunté) así que hagas lo que hagas, es posible que pierdas algo de información que te hubiera gustado conservar.

Aquí está mi versión C # del código Ruby de @hurshagrawal. No conozco a Ruby realmente bien, así que podría estar apagado, pero creo que lo entendí bien.

 public string ExtractReply(string text, string address) { var regexes = new List() { 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(); } 

Si controla el mensaje original (por ejemplo, notificaciones desde una aplicación web), puede colocar un encabezado distinto e identificable en su lugar y usarlo como el delimitador de la publicación original.

Esta es una buena solución. Lo encontré después de buscar durante tanto tiempo.

Una adición, como se mencionó anteriormente, esto es en mayúsculas y minúsculas, por lo que las expresiones anteriores no analizaron correctamente mis respuestas de gmail y outlook (2010), para lo cual agregué los siguientes dos Regex (s). Avísame si hay algún problema.

 //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), 

Aclamaciones

Es una publicación anterior, sin embargo, no estoy seguro si eres consciente de que github tiene una lib de Ruby extrayendo la respuesta. Si usa .NET, tengo uno de .NET en https://github.com/EricJWHuang/EmailReplyParser

Este es un problema súper duro. Pasé años desarrollando una herramienta de análisis para este problema exacto. Si usa SigParser.com , le dará una selección de todos los correos electrónicos descompuestos en una cadena de respuesta de una sola cadena de texto de correo electrónico. Entonces, si hay 10 correos electrónicos, obtendrá el texto para los 10 correos electrónicos.

También le dará los datos de contacto de todos los contactos que encuentre en toda la cadena de respuestas, como números de teléfono, títulos, direcciones y algunas URL seleccionadas.

Yo soy el creador de SigParser.