При обработке ответа по электронной почте, как я могу игнорировать специфику и историю почтового клиента? - PullRequest
6 голосов
/ 05 мая 2009

У меня есть приложение rails, которое обрабатывает входящие письма через IMAP. В настоящее время используется метод, который ищет в частях объекта TMail заданный тип содержимого:

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

Эти электронные письма, как правило, являются ответом на HTML-письмо, которое оно отправило в первую очередь. (Исходное сообщение электронной почты никогда не бывает прежним.) Основной текст, который возвращает метод, содержит полную историю сообщения электронной почты, и я хотел бы просто разобрать текст ответа.

  1. Мне интересно, разумно ли разместить какой-нибудь текст "--- ответьте над этой строкой ---" в верхней части письма, как я видел в приложении с 37 сигналами.

  2. Есть ли другой способ игнорировать специфичные для клиента дополнения к электронному письму, кроме написания множества регулярных выражений (которые я еще не пытался) для каждого почтового клиента? Похоже, что все они, как ни в чем не бывало, в верхней части ответов.

Ответы [ 2 ]

9 голосов
/ 06 мая 2009

Я должен сделать парсинг ответа по электронной почте о проекте, над которым я сейчас работаю. В итоге я использовал сопоставление с образцом для идентификации части ответа, поэтому пользователям не нужно было беспокоиться о том, куда вставить свой ответ.

Хорошей новостью является то, что реализация на самом деле не так уж сложна. Сложная часть - просто протестировать все почтовые клиенты и сервисы, которые вы хотите поддерживать, и выяснить, как идентифицировать каждого из них. Как правило, вы можете использовать либо идентификатор сообщения, либо заголовок X-Mailer или Return-Path, чтобы определить, откуда пришло электронное письмо.

Вот метод, который берет объект TMail и извлекает ответную часть сообщения и возвращает его вместе с почтовым клиентом / сервисом, из которого оно было отправлено. Предполагается, что у вас есть исходное сообщение От: имя и адрес в константах FROM_NAME и 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') =~ /<.+@(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 голосов
/ 06 мая 2009

Я думаю, что вы застряли на этом. Недавно я самостоятельно занимался электронной почтой в TMail, и вы, как правило, обнаружите, что электронная почта, содержащая часть HTML, обычно имеет такую ​​структуру:

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

Почтовые клиенты, с которыми я играл в Outlook и Gmail, генерируют ответы в этом формате, и они обычно указывают в ответе оригинальное письмо, встроенное в ответ. Сначала я подумал, что «старые» части исходного письма будут отдельными частями, но на самом деле это не так - старая часть просто объединяется с ответной частью.

Вы можете найти в этой строке строку, начинающуюся с «От:» (поскольку большинство клиентов обычно размещают заголовок в верхней части исходного текста письма, в котором указывается, кто его отправил и т. Д.), Но это, вероятно, не гарантируется.

На самом деле я не вижу ничего плохого в --- пожалуйста, ответьте над этой строкой - как правило, это не так уж инвазивно и может сделать все намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...