Rails - 邮件,将正文作为纯文本获取
Posted
技术标签:
【中文标题】Rails - 邮件,将正文作为纯文本获取【英文标题】:Rails - Mail, getting the body as Plain Text 【发布时间】:2011-06-19 14:04:13 【问题描述】:给定:message = Mail.new(params[:message])
如此处所示:http://docs.heroku.com/cloudmailin
它展示了如何将 message.body 获取为 html,如何获取纯文本版本?
谢谢
【问题讨论】:
【参考方案1】:以上代码:
message = Mail.new(params[:message])
将从完整消息中创建mail gem 的新实例。然后,您可以使用该消息上的任何方法来获取内容。因此,您可以使用以下方法获取纯内容:
message.text_part
或带有
的HTMLmessage.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
似乎是同一Mail
或Mail::Message
类的实例,该类也用于ActionMailer::Base
或mailman gem。
我不确定这是在哪里集成到 Rails 中的,但 Steve Smith has pointed out 这是在 mail gem 中定义的。
Usage Section of the gem's readme on github。 Documentation ofMail::Message
on rubydoc.info。
从多部分电子邮件中提取部分
在 gem 的自述文件中,有一个 example section on reading multipart emails。
除了html_part
和text_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::Part
是 documented 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)以上是关于Rails - 邮件,将正文作为纯文本获取的主要内容,如果未能解决你的问题,请参考以下文章