web-dev-qa-db-ja.com

Rails-メール、本文をプレーンテキストとして取得

与えられた:message = Mail.new(params[:message])

ここに見られるように: http://docs.heroku.com/cloudmailin

これは、message.bodyをHTMLとして取得する方法、プレーン/テキストバージョンを取得する方法を示しています。

ありがとう

42
AnApprentice

上記のコード:

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など)にエンコードされていることを確認することも重要です。

70
Steve Smith

Mailとは何ですか?

質問で定義されたmessageは、同じMailまたは_Mail::Message_クラスのインスタンスであるように見えます。これは、_ActionMailer::Base_または mailman gem

これがRailsに統合されている場所はわかりませんが、 メールgem で定義されていると Steve Smithが指摘した です。

マルチパートメールからのパートの抽出

Gemのreadmeには、 マルチパートメールの読み取りに関するセクションの例 があります。

メソッド_html_part_および_text_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
_

this SO question のように)。

これを回避するために、メッセージ部分から文字セットを読み取り、UTF-8にエンコードする前に、どの文字セットであったかをRailsに伝えることができます。

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

ここで、decodedメソッドは、 メール宝石のreadmeのエンコードセクション に示すように、ヘッダー行を削除します。

編集:ハードエンコーディングの問題

エンコーディングの問題が本当に難しい場合は、前者の方法では解決できません。優れた charlock_holmes gem をご覧ください。

この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
_
48
fiedl
email = Mail.new(params[:message])
text_body = (email.text_part || email.html_part || email).body.decoded

私はこのソリューションを RedmineCRM Helpdesk plugin で使用しています

13
Kirill Bezrukov

Message.text_part.body.decodedを呼び出すと、Mail gemによってUTF-8に変換されると思いますが、これについてはドキュメントが100%明確ではありません。

3

Rails USEでHTML本文形式を保存するUSE <%= @ email.body.html_safe%>これは、電子メールのテキストエディターで書かれたテキストをそのまま電子メールで送信します。

0
Dhanshree