Estoy tratando de averiguar cómo analizar el texto de un correo electrónico a partir de cualquier texto de respuesta citado que pueda incluir. He notado que, por lo general, los clientes de correo electrónico colocarán un "En tal o cual fecha tal y tal escribió" o prefijarán las líneas con un corchete angular. Desafortunadamente, no todo el mundo hace esto. ¿Alguien tiene alguna idea sobre cómo detectar mediante programación el texto de respuesta? Estoy usando C # para escribir este analizador.
c#
ruby
email
email-parsing
VanOrman
fuente
fuente
Respuestas:
Hice muchas más búsquedas sobre esto y esto es lo que encontré. Básicamente, hay dos situaciones en las que está haciendo esto: cuando tiene el hilo completo y cuando no lo tiene. Lo dividiré en esas dos categorías:
Cuando tienes el hilo:
Si tiene toda la serie de correos electrónicos, puede lograr un alto nivel de seguridad de que lo que está eliminando es en realidad texto citado. Hay dos maneras de hacer esto. Uno, puede usar el ID de mensaje, el ID de respuesta a, y el índice de subproceso del mensaje para determinar el mensaje individual, su padre y el subproceso al que pertenece. Para obtener más información sobre esto, consulte RFC822 , RFC2822 , este interesante artículo sobre subprocesos o este artículo sobre subprocesos . Una vez que haya vuelto a ensamblar el hilo, puede eliminar el texto externo (como Para, De, CC, etc ... líneas) 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 similitudes para determinar el texto que se repite. En este caso, es posible que desee buscar un algoritmo de distancia de Levenshtein como este en Code Project o este .
Pase lo que pase, si está interesado en el proceso de subprocesamiento, consulte este excelente PDF sobre cómo volver a ensamblar los subprocesos de correo electrónico .
Cuando no tienes el hilo:
Si está atascado con un solo mensaje del hilo, debe intentar adivinar cuál es la cita. En ese caso, aquí están los diferentes métodos de cotización que he visto:
Elimina el texto de allí hacia abajo y listo. La desventaja de cualquiera de estos es que todos asumen que el remitente puso su respuesta encima del texto citado y no lo intercalo (como era el estilo antiguo en Internet). Si eso sucede, buena suerte. ¡Espero que esto ayude a algunos de ustedes!
fuente
Primero que nada, esta es una tarea complicada.
Debe recopilar respuestas típicas de diferentes clientes de correo electrónico y preparar expresiones regulares correctas (o lo que sea) para analizarlas. He recopilado 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 cotización al final:
new Regex("^>.*$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
Aquí está mi pequeña colección de respuestas de prueba (muestras divididas por --- ):
From: [email protected] [mailto:[email protected]] Sent: Tuesday, January 13, 2009 1:27 PM ---- 2008/12/26 <[email protected]> > text ---- [email protected] wrote: > text ---- [email protected] wrote: text text ---- 2009/1/13 <[email protected]> > text ---- [email protected] wrote: text text ---- 2009/1/13 <[email protected]> > text > text ---- 2009/1/13 <[email protected]> > text > text ---- [email protected] wrote: > text > text <response here> ---- --- On Fri, 23/1/09, [email protected] <[email protected]> wrote: > text > text
Saludos cordiales, Oleg Yaroshevych
fuente
¡Gracias, Goleg, por las expresiones regulares! Realmente ayudó. 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
Ha funcionado bastante bien hasta ahora.
fuente
De lejos, la forma más fácil de hacerlo es colocando un marcador en su contenido, como:
--- Responda por encima de esta línea ---
Como sin duda habrá notado, analizar el texto citado no es una tarea trivial ya que 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.
Oleg ha resuelto el problema usando expresiones regulares para encontrar el texto "El 13 de julio de 2012, a las 13:09, xxx escribió:". Sin embargo, si el usuario elimina este texto o responde al final del correo electrónico, como hacen muchas personas, esta solución no funcionará.
Del mismo modo, si el cliente de correo electrónico usa una cadena de fecha diferente o no incluye una cadena de fecha, la expresión regular fallará.
fuente
-- Please reply above this line. DO NOT REMOVE IT! --
. Además, lo que experimenté es que no siempre funcionará, ya que algunos clientes de correo electrónico agregan unaxxx wrote on <datetime>:
línea antes de toda la cotización y, por lo tanto, antes de esa línea. Esta línea se puede analizar con expresiones regulares, sin embargo, puede estar en diferentes idiomas y en un formato diferente, ya que los clientes de correo electrónico son diferentes.No existe un indicador universal de una respuesta en un correo electrónico. Lo mejor que puede hacer es intentar captar los patrones más comunes y analizar nuevos patrones a medida que los encuentre.
Tenga en cuenta que algunas personas insertan respuestas dentro del texto citado (mi jefe, por ejemplo, responde las preguntas en la misma línea que yo les hice), así que, hagas lo que hagas, es posible que pierdas información que te hubiera gustado conservar.
fuente
Aquí está mi versión C # del código Ruby de @ hurshagrawal. No conozco muy bien a Ruby, así que podría fallar, pero creo que lo hice bien.
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(); }
fuente
Si controlas el mensaje original (por ejemplo, notificaciones de una aplicación web), puedes colocar un encabezado identificable y distinto en su lugar y usarlo como delimitador de la publicación original.
fuente
Esta es una buena solución. Lo encontré después de buscar durante tanto tiempo.
Una adición, como se mencionó anteriormente, esto es sabio, por lo que las expresiones anteriores no analizaron correctamente mis respuestas de Gmail y Outlook (2010), para lo cual agregué las siguientes dos Regex (s). Avísame si tienes 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),
Salud
fuente
Es una publicación antigua, sin embargo, no estoy seguro de si sabe que github tiene una lib de Ruby extrayendo la respuesta. Si usa .NET, tengo uno .NET en https://github.com/EricJWHuang/EmailReplyParser
fuente
Si usa la API de SigParser.com , le dará una serie de todos los correos electrónicos desglosados en una cadena de respuesta a partir de una sola cadena de texto de correo electrónico. Entonces, si hay 10 correos electrónicos, obtendrá el texto de los 10 correos electrónicos.
Puede ver las especificaciones detalladas de la API aquí.
https://api.sigparser.com/
fuente