Rails - 邮件,将正文作为纯文本

时间:2011-02-01 21:34:19

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

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

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

它显示了如何将message.body作为HTML获取,如何获得普通/文本版本?

由于

5 个答案:

答案 0 :(得分:63)

上面的代码:

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)。

答案 1 :(得分:46)

什么是Mail

问题中定义的message似乎是同一MailMail::Message类的实例,该类也用于ActionMailer::Base或{{ 3}}。

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

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

在宝石的自述文件中,有一个Documentation of Mail::Message on rubydoc.info

除了方法html_parttext_partexample section on reading multipart emails,人们可以手动访问和循环部分,并根据需要按标准进行过滤。

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

Mail::Partsimply find the first part of the corresponding mime type

编码问题

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

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

(例如documented here)。

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

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

此处,decoded方法会删除标题行,如this SO question所示。

编辑:硬编码问题

如果确实存在硬编码问题,前一种方法无法解决,请查看优秀的encoding section of the mail gem's readme

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

我发现为邮件消息定义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

答案 2 :(得分:13)

email = Mail.new(params[:message])
text_body = (email.text_part || email.html_part || email).body.decoded

我在RedmineCRM Helpdesk plugin

上使用此解决方案

答案 3 :(得分:3)

我相信如果你调用message.text_part.body.decoded,你将通过Mail gem将它转换为UTF-8,虽然文档不是100%明确的。

答案 4 :(得分:0)

在Rails中保存HTML正文格式 使用<%= @ email.body.html_safe%> 这样将发送在电子邮件文本编辑器中编写的文本,就像发送电子邮件一样。