代码之家  ›  专栏  ›  技术社区  ›  tsdbrown

在处理电子邮件回复时,我如何可以忽略任何电子邮件客户端细节和历史记录?

  •  6
  • tsdbrown  · 技术社区  · 17 年前

    我有一个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 signals应用程序中看到的那样。

    2. 除了为每个邮件客户端编写大量正则表达式(我还没有尝试过),还有其他方法可以忽略特定于客户端的电子邮件添加内容吗?他们似乎都在任何回复的顶部加上了自己的一点。

    2 回复  |  直到 17 年前
        1
  •  9
  •   Keith Platfoot    17 年前

    我必须做一个项目,我现在正在工作的电子邮件回复解析。我最终使用了模式匹配来识别响应部分,这样用户就不必担心在哪里插入他们的回复了。

    好消息是实现起来并不太困难。困难的部分只是测试所有你想要支持的不同的电子邮件客户端和服务,并找出如何识别每一个。通常,您可以使用消息ID或X-Mailer或返回路径头来确定传入电子邮件的来源。

    这里有一个方法,它接受一个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
    
        2
  •  0
  •   Stephen ODonnell    17 年前

    我想你会被困在这个问题上。我最近在TMail做了一些关于电子邮件的事情,你通常会发现,一封包含HTML部分的电子邮件的结构通常如下所示:

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

    我用Outlook和Gmail玩过的电子邮件客户端都以这种格式生成回复,它们通常只在回复中内联引用原始电子邮件。起初,我认为原始电子邮件的“旧”部分应该是独立的部分,但事实并非如此——旧部分只是合并到回复部分中。

    我真的不认为a有什么问题——请在这一行上面回答——一般来说,它没有那么侵入性,而且可以使事情简单得多。