QA@IT

rails 3.2.8 でメールを受信すると Encoding::CompatibilityError

3369 PV

http://guides.rubyonrails.org/action_mailer_basics.html#receiving-emails のように receive(email) メソッドを定義した mailer を用意して、以下のように実行すると gem の中で Encoding::CompatibilityError になってしまって困っています。

ウェブで検索してみると送信での話はいろいろあるようですが、受信での話は見つけられませんでした。

% rails runner 'HogeMailer.receive(STDIN.read)' < hoge.eml
..../gems/railties-3.2.8/lib/rails/commands/runner.rb:53:in `eval': incompatible encoding regexp match (US-ASCII regexp with ISO-2022-JP string) (Encoding::CompatibilityError)
    from ..../gems/mail-2.4.4/lib/mail/fields/unstructured_field.rb:179:in `encode_crlf'
    from ..../gems/mail-2.4.4/lib/mail/fields/unstructured_field.rb:144:in `fold'
    from ..../gems/mail-2.4.4/lib/mail/fields/unstructured_field.rb:96:in `wrapped_value'
    from ..../gems/mail-2.4.4/lib/mail/fields/unstructured_field.rb:60:in `do_encode'
    from ..../gems/mail-2.4.4/lib/mail/fields/unstructured_field.rb:42:in `encoded'
    from ..../gems/mail-2.4.4/lib/mail/field.rb:133:in `method_missing'
    from ..../gems/mail-2.4.4/lib/mail/header.rb:190:in `block in encoded'
    from ..../gems/mail-2.4.4/lib/mail/header.rb:189:in `each'
    from ..../gems/mail-2.4.4/lib/mail/header.rb:189:in `encoded'
    from ..../gems/mail-2.4.4/lib/mail/message.rb:1708:in `encoded'
    from ..../gems/actionmailer-3.2.8/lib/action_mailer/base.rb:434:in `set_payload_for_mail'
    from ..../gems/actionmailer-3.2.8/lib/action_mailer/base.rb:403:in `block in receive'
    from ..../gems/activesupport-3.2.8/lib/active_support/notifications.rb:123:in `block in instrument'
    from ..../gems/activesupport-3.2.8/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from ..../gems/activesupport-3.2.8/lib/active_support/notifications.rb:123:in `instrument'
    from ..../gems/actionmailer-3.2.8/lib/action_mailer/base.rb:401:in `receive'
    from (eval):1:in `<top (required)>'
    from ..../gems/railties-3.2.8/lib/rails/commands/runner.rb:53:in `eval'
    from ..../gems/railties-3.2.8/lib/rails/commands/runner.rb:53:in `<top (required)>'
    from ..../gems/railties-3.2.8/lib/rails/commands.rb:64:in `require'
    from ..../gems/railties-3.2.8/lib/rails/commands.rb:64:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

回答

ActionMailer で試したわけではないのですが、mail-iso-2022-jp gem を使うと、ISO-2022-JP のメールでも Mail::Message#encoded で例外が起こらなくなります。

本文もヘッダもエンコーディングが ASCII-8BIT で、ヘッダはなぜか 2 重に B 符号化されていたりと、扱いが面倒ですが、ご参考になれば。

require "mail"
require "mail-iso-2022-jp"

iso2022jp_mail_string = File.read("mail.eml")
mail =  Mail.new(iso2022jp_mail_string)

puts mail.encoded
puts mail.body.to_s.encode("utf-8", "iso-2022-jp")
puts Mail::Encodings.b_value_decode(Mail::Encodings.b_value_decode(mail.subject))
編集 履歴 (0)
  • 情報ありがとうございます。
    gem 'mail-iso-2022-jp' を追加して
    -
  • def receive(mail)
    plain_part = mail.multipart? ? (mail.text_part ? mail.text_part.body.decoded : nil) : mail.body.decoded
    require 'nkf'
    body = NKF.nkf('-wd', plain_part)
    という感じでいけているようです。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。