2009-05-05 24 views
6

Tengo una aplicación de rieles que procesa los correos electrónicos entrantes a través de IMAP. Actualmente se utiliza un método que busca en las partes de un objeto TMail para un determinado content_type:Al procesar una respuesta por correo electrónico, ¿cómo puedo ignorar las especificaciones del cliente de correo electrónico y el historial?

def self.search_parts_for_content_type(parts, content_type = 'text/html') 
    parts.each do |part| 
     if part.content_type == content_type 
     return part.body 
     else 
     if part.multipart? 
      if body = self.search_parts_for_content_type(part.parts, content_type) 
      return body 
      end 
     end 
     end 
    end 

    return false 
end 

Estos mensajes son por lo general en respuesta a un correo electrónico HTML que envió a cabo en el primer lugar. (El correo electrónico saliente original nunca es el mismo.) El texto del cuerpo que muestra el método anterior contiene el historial completo del correo electrónico y me gustaría simplemente analizar el texto de respuesta.

  1. Me pregunto si es razonable colocar un poco '--- por favor, responda por encima de esta línea ---' de texto en la parte superior del correo como he visto en una aplicación de 37 señales.

  2. ¿Hay alguna otra manera de ignorar las adiciones específicas del cliente al correo electrónico, aparte de escribir una multitud de expresiones regulares (que aún no he intentado) para cada cliente de correo? Todos parecen abordar su propio puntaje en la parte superior de todas las respuestas.

Respuesta

9

Tengo que hacer un análisis de respuesta por correo electrónico en un proyecto en el que estoy trabajando en este momento. Terminé usando la coincidencia de patrones para identificar la parte de respuesta, por lo que los usuarios no tendrían que preocuparse por dónde insertar su respuesta.

La buena noticia es que la implementación realmente no es demasiado difícil. La parte difícil es simplemente probar todos los diferentes clientes y servicios de correo electrónico que desea admitir y averiguar cómo identificarlos. En general, puede usar el ID del mensaje o el encabezado X-Mailer o Return-Path para determinar de dónde proviene el correo electrónico entrante.

Aquí hay un método que toma un objeto TMail y extrae la parte de respuesta del mensaje y lo devuelve junto con el cliente/servicio de correo electrónico desde el que se envió. Supone que tiene el mensaje original De: nombre y dirección en las constantes FROM_NAME y FROM_ADDRESS.

def find_reply(email) 
    message_id = email.message_id('') 
    x_mailer = email.header_string('x-mailer') 

    # For optimization, this list could be sorted from most popular to least popular email client/service 
    rules = [ 
    [ 'Gmail', lambda { message_id =~ /.+gmail\.com>\z/}, /^.*#{FROM_NAME}\s+<#{FROM_ADDRESS}>\s*wrote:.*$/ ], 
    [ 'Yahoo! Mail', lambda { message_id =~ /.+yahoo\.com>\z/}, /^_+\nFrom: #{FROM_NAME} <#{FROM_ADDRESS}>$/ ], 
    [ 'Microsoft Live Mail/Hotmail', lambda { email.header_string('return-path') =~ /<[email protected](hotmail|live).com>/}, /^Date:.+\nSubject:.+\nFrom: #{FROM_ADDRESS}$/ ], 
    [ 'Outlook Express', lambda { x_mailer =~ /Microsoft Outlook Express/ }, /^----- Original Message -----$/ ], 
    [ 'Outlook', lambda { x_mailer =~ /Microsoft Office Outlook/ }, /^\s*_+\s*\nFrom: #{FROM_NAME}.*$/ ], 

    # TODO: other email clients/services 

    # Generic fallback 
    [ nil, lambda { true }, /^.*#{FROM_ADDRESS}.*$/ ] 
    ] 

    # Default to using the whole body as the reply (maybe the user deleted the original message when they replied?) 
    notes = email.body 
    source = nil 

    # Try to detect which email service/client sent this message 
    rules.find do |r| 
    if r[1].call 
     # Try to extract the reply. If we find it, save it and cancel the search. 
     reply_match = email.body.match(r[2]) 
     if reply_match 
     notes = email.body[0, reply_match.begin(0)] 
     source = r[0] 
     next true 
     end 
    end 
    end 

    [notes.strip, source] 
end 
0

Creo que estarás atrapado en este caso. He estado haciendo algunas cosas con mensajes de correo electrónico a mí mismo en TMail recientemente, y lo que generalmente encontrará es que un correo electrónico que tiene una parte HTML es generalmente estructurado como:

part 1 - multipart/mixed 
    sub part 1 - text/plain 
    sub part 2 - text/html 
end 

Los clientes de correo electrónico que he jugado con Outlook y Gmail ambos generan respuestas en este formato, y generalmente citan el correo electrónico original en línea en la respuesta. Al principio pensé que las partes "viejas" del correo electrónico original serían partes separadas, pero en realidad no lo son: la parte anterior simplemente se fusionó en la parte de respuesta.

Puede buscar en la parte una línea que comience 'De:' (ya que la mayoría de los clientes colocan un encabezado en la parte superior del texto del correo electrónico original que lo envía, etc.), pero probablemente no esté garantizado.

Realmente no veo nada de malo con un --- responda por encima de esta línea --- en general, no es tan invasivo, y podría hacer las cosas mucho más simples.

+0

Gracias por su respuesta, he tenido un juego con algunas variaciones en los correos electrónicos entrantes, incluidos los correos electrónicos con archivos adjuntos. He encontrado la misma configuración que mencionaste. Como dices, parece que nada está garantizado. Me parece una tontería que la coincidencia de patrones como esta sea la única manera de continuar.Incluso con la respuesta --- aquí arriba --- usted todavía necesita manejar los detalles del cliente de correo electrónico, ya que naturalmente va más allá de la línea de todos modos :( – tsdbrown

Cuestiones relacionadas