【问题标题】:Rails - Mail, getting the body as Plain TextRails - 邮件,将正文作为纯文本获取
【发布时间】:2011-06-19 14:04:13
【问题描述】:

给定:message = Mail.new(params[:message])

如此处所示:http://docs.heroku.com/cloudmailin

它展示了如何将 message.body 获取为 HTML,如何获取纯文本版本?

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 heroku actionmailer


    【解决方案1】:

    以上代码:

    message = Mail.new(params[:message])
    

    将从完整消息中创建mail gem 的新实例。然后,您可以使用该消息上的任何方法来获取内容。因此,您可以使用以下方法获取纯内容:

    message.text_part
    

    或带有

    的HTML
    message.html_part
    

    这些方法只会猜测并找到 text/plain 或 text/html 内容类型的多部分消息中的第一部分。 CloudMailin 还通过 params[:plain] 和 params[:html] 提供了这些便利方法。值得记住的是,消息永远不能保证包含纯文本或 html 部分。可能值得使用以下内容来确定:

    plain_part = message.multipart? ? (message.text_part ? message.text_part.body.decoded : nil) : message.body.decoded
    html_part = message.html_part ? message.html_part.body.decoded : nil
    

    附带说明,当您使用这些方法时,从消息中提取内容编码也很重要,并确保将输出编码为您想要的编码方法(例如 UTF-8)。

    【讨论】:

    • 谢谢!我在解码后解析电子邮件时遇到了一些问题,但获取 text_part 有助于解决此问题。
    • 优秀的答案。我必须说这适用于默认的 Rails Action Mailer。不需要任何邮件宝石。
    • 如何提取编码?我在做这个 ..force_encoding("ISO-8859-1").encode('utf_8') 和一些消息工作,在其他人不这样做。
    • @David "default Rails Action Mailer" mail gem。至少,很大程度上取决于它。
    • 天哪,谢谢。难怪我之前错过了,它在Message类的第1600+行。
    【解决方案2】:

    什么是Mail

    问题中定义的message 似乎是同一MailMail::Message 类的实例,该类也用于ActionMailer::Basemailman gem

    我不确定这是在哪里集成到 Rails 中的,但 Steve Smith has pointed out 这是在 mail gem 中定义的。

    从多部分电子邮件中提取部分

    在 gem 的自述文件中,有一个 example section on reading multipart emails

    除了html_parttext_part 方法simply find the first part of the corresponding mime type 之外,还可以手动访问和循环访问部件,并根据需要按条件过滤。

    message.parts.each do |part|
      if part.content_type == 'text/plain'
        # ...
      elsif part.content_type == 'text/html'
        # ...
      end 
    end
    

    Mail::Partdocumented here

    编码问题

    根据收到邮件的来源,可能存在编码问题。例如,rails 可以识别错误的编码类型。然后,如果尝试将正文转换为 UTF-8 以便将其存储在数据库中 (body_string.encode('UTF-8')),则可能会出现编码错误,例如

    Encoding::UndefinedConversionError - "\xFC" from ASCII-8BIT to UTF-8
    

    (如this SO question)。

    为了避免这种情况,可以从消息部分读出字符集,并告诉 Rails 在编码为 UTF-8 之前它是什么字符集:

    encoding = part_to_use.content_type_parameters['charset']
    body = part_to_use.body.decoded.force_encoding(encoding).encode('UTF-8')
    

    这里,decoded 方法删除了标题行,如encoding section of the mail gem's readme 所示。

    编辑:硬编码问题

    如果真的有硬编码问题,前一种方法解决不了,看看优秀的charlock_holmes gem

    将此 gem 添加到 Gemfile 后,有一种更可靠的方法来转换电子邮件编码,使用 detect_encoding 方法,该方法由此 gem 添加到 Strings。

    我发现为邮件消息定义一个body_in_utf8 方法很有帮助。 (Mail::Part 也继承自 Mail::Message。):

    module Mail
      class Message
        def body_in_utf8
          require 'charlock_holmes/string'
          body = self.body.decoded
          if body.present?
            encoding = body.detect_encoding[:encoding]
            body = body.force_encoding(encoding).encode('UTF-8')
          end
          return body
        end
      end
    end
    

    总结

    # select the part to use, either like shown above, or as one-liner
    part_to_use = message.html_part || message.text_part || message
    
    # readout the encoding (charset) of the part
    encoding = part_to_use.content_type_parameters['charset'] if part_to_use.content_type_parameters
    
    # get the message body without the header information
    body = part_to_use.body.decoded
    
    # and convert it to UTF-8
    body = body.force_encoding(encoding).encode('UTF-8') if encoding
    

    编辑:或者,定义一个body_in_utf8方法后,如上图,同单行:

    (message.html_part || message.text_part || message).body_in_utf8
    

    【讨论】:

    • 说真的??像这样的答案需要一个特殊的质量印章。
    • 多么棒的答案。非常感谢!!
    • 这么好的答案,谢谢。处理电子邮件是一个真正令人头疼的 80/20。
    【解决方案3】:
    email = Mail.new(params[:message])
    text_body = (email.text_part || email.html_part || email).body.decoded
    

    我在RedmineCRM Helpdesk plugin使用这个解决方案

    【讨论】:

      【解决方案4】:

      我相信,如果您调用 message.text_part.body.decoded,您会通过 Mail gem 为您将其转换为 UTF-8,但文档并没有 100% 清楚地说明这一点。

      【讨论】:

      • 不,它没有。它返回一个类似\xF0\xD2\x12... 的字符串
      【解决方案5】:

      在 Rails 中保存 HTML 正文格式 使用 这会将在电子邮件文本编辑器中编写的文本按原样发送到电子邮件。

      【讨论】:

      • 是的...html_safe 在用户提供的内容上,结果不会很好(XSS)
      猜你喜欢
      • 2016-07-04
      • 1970-01-01
      • 2011-10-09
      • 2015-11-05
      • 2012-06-14
      • 1970-01-01
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多