Rails - 邮件,以纯文本形式获取正文

发布于 2024-10-15 12:22:45 字数 239 浏览 5 评论 0原文

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

如下所示:http: //docs.heroku.com/cloudmailin

它显示了如何获取 HTML 形式的 message.body,如何获取纯文本/文本版本?

谢谢

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

as seen here: http://docs.heroku.com/cloudmailin

It shows how to get the message.body as HTML, how to do you get the plain/text version?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你另情深 2024-10-22 12:22:45

上面的代码:

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

The code above:

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

will create a new instance of the mail gem from the full message. You can then use any of the methods on that message to get the content. You can therefore get the plain content using:

message.text_part

or the HTML with

message.html_part

These methods will just guess and find the first part in a multipart message of either text/plain or text/html content type. CloudMailin also provides these as convenience methods however via params[:plain] and params[:html]. It's worth remembering that the message is never guaranteed to have a plain or html part. It may be worth using something like the following to be sure:

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

As a side note it's also important to extract the content encoding from the message when you use these methods and make sure that the output is encoded into the encoding method you desire (such as UTF-8).

早乙女 2024-10-22 12:22:45

什么是邮件

问题中定义的 message 似乎是同一 MailMail::Message 类的实例,该类也用于 >ActionMailer::Base,或在 mailman gem 中。

我不确定它在哪里集成到 Rails 中,但是 Steve Smith 指出 这是在 邮件宝石

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

在 gem 的自述文件中,有一个关于阅读的 示例部分多部分电子邮件

除了方法 html_parttext_part 之外,只需找到相应 mime 类型的第一部分,即可手动访问和循环这些部分,并根据需要按条件进行过滤。

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

Mail::Part 记录在此处

编码问题

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

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

(例如在这个问题中)。

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

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

这里,decoded 方法删除了标题行,如下所示邮件 gem 自述文件的编码部分

编辑:硬编码问题

如果确实存在硬编码问题,前一种方法无法解决,请查看优秀的 charlock_holmes宝石

将这个 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

What is Mail?

The message defined in the question appears to be an instance of the same Mail or Mail::Message class, which is also used in ActionMailer::Base, or in the mailman gem.

I'm not sure where this is integrated into rails, but Steve Smith has pointed out that this is defined in the mail gem.

Extracting a Part From a Multipart Email

In the gem's readme, there is an example section on reading multipart emails.

Besides the methods html_part and text_part, which simply find the first part of the corresponding mime type, one can access and loop through the parts manually and filter by the criteria as needed.

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

The Mail::Part is documented here.

Encoding Issues

Depending on the source of the received mail, there might be encoding issues. For example, rails could identify the wrong encoding type. If, then, one tries to convert the body to UTF-8 in order to store it in the database (body_string.encode('UTF-8')), there might be encoding errors like

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

(like in this SO question).

In order to circumvent this, one can readout the charset from the message part and tell rails what charset it has been before encoding to UTF-8:

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

Here, the decoded method removes the header lines, as shown in the encoding section of the mail gem's readme.

EDIT: Hard Encoding Issues

If there are really hard encoding issues, the former approach does not solve, have a look at the excellent charlock_holmes gem.

After adding this gem to the Gemfile, there is a more reliable way to convert email encodings, using the detect_encoding method, which is added to Strings by this gem.

I found it helpful to define a body_in_utf8 method for mail messages. (Mail::Part also inherits from 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

Summary

# 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

EDIT: Or, after defining a body_in_utf8 method, as shown above, the same as one-liner:

(message.html_part || message.text_part || message).body_in_utf8
躲猫猫 2024-10-22 12:22:45
email = Mail.new(params[:message])
text_body = (email.text_part || email.html_part || email).body.decoded

我在 RedmineCRM Helpdesk 插件 上使用此解决方案

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

I'm using this solution on RedmineCRM Helpdesk plugin

策马西风 2024-10-22 12:22:45

我相信如果您调用 message.text_part.body.decoded 您将通过 Mail gem 将其转换为 UTF-8,但文档对此并不是 100% 清楚。

I believe if you call message.text_part.body.decoded you will get it converted to UTF-8 for you by the Mail gem, the documentation isn't 100% clear on this though.

仲春光 2024-10-22 12:22:45

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

Save HTML Body Format in Rails
USE <%= @email.body.html_safe%>
This will send text written in email text editor as it is to email.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文