2011-10-03
Rails3 ISO-2022-JPでメール送信
- Rails3.0.0 で iso-2022-jp メールを送る - 篳篥日記
- Rails3 ActionMailerを解析して、ISO-2022-JPに対応する - A Life Less Ordinary
先人達の知恵がありますが、別のアプローチを考えついたので記事にしてみます。
※検証したものの運用が不十分なため、問題が起きる可能性がありますので参考にされる場合はご注意ください
環境
- Ruby 1.9.2p290
- Rails(ActionMailer) 3.0.10
- Mail 2.2.19
要点
- ActionMailerクラスのdefaultやmailメソッドでcharsetを指定しても、メール本文は変換されない
- 本文を変換させるには、Mail::Bodyのインスタンスのcharsetを直接指定する
上記の記事ではMailライブラリにモンキーパッチをあてていますが、ActionMailerでも同様に、かつすっきり書くことができます。方法は2通りあります。
オーバーライド
app/mailers/application_mailer.rb (※ファイル名は自由)
#require 'nkf' class ApplicationMailer < ActionMailer::Base default :charset => 'iso-2022-jp' #件名はこれでok def mail(headers={}, &block) mail = super mail.body.charset = 'iso-2022-jp' #本文は直接指定 #mail.body = NKF.nkf('-w -J', NKF.nkf('-j -W', mail.body.raw_source)) #変換エラー対策 (旧) mail.body = mail.body.raw_source.encode('iso-2022-jp', :invalid => :replace, :undef => :replace).encode('utf-8') #変換エラー対策 mail end end
モンキーパッチ
config/initializers/mailer_fix.rb (※ファイル名は自由)
require 'action_mailer/base' module ActionMailer class Base < AbstractController::Base default :charset => 'iso-2022-jp' def mail_with_fix(headers={}, &block) mail = mail_without_fix(headers, &block) mail.body.charset = 'iso-2022-jp' mail.body = mail.body.raw_source.encode('iso-2022-jp', :invalid => :replace, :undef => :replace).encode('utf-8') mail end alias_method_chain :mail, :fix end end
変換エラー対策 (追記)
例えばWindowsの「〜」が入っていると、標準のencodeメソッドではうまく変換できません。
Encoding::UndefinedConversionError: U+FF5E to EUC-JP in conversion from UTF-8 to EUC-JP to stateless-ISO-2022-JP to ISO-2022-JP
id:ya_maさんの記事にあるようにNKFを使うのがいいようです。さらにActionMailerだけで完結するには、UTF-8→ISO-2022-JP→UTF-8という二重の変換を行う必要があります(ISO-2022-JPのままだとActiveSupport#blank?でエラーになる)。
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with ISO-2022-JP string)
さらに追記
丸数字や"はしごだか"は上記では回避できないようです。encodeメソッドのオプションを使う方法がありました。
mail.body = mail.body.raw_source.encode('ISO-2022-JP', :invalid => :replace, :undef => :replace).encode('UTF-8')
留意点としては、機種依存文字が「?」に置き換えられてしまいますので、それを許容する必要があります。
まとめ
mailersの中だけで完結するオーバーライドのほうがわかりやすいと思いますし、複数のMailerクラスがある場合でも継承をうまく使えば1箇所の記述で済みます。ただし、例えばDeviseのようなメール送信を行う他のライブラリへの対応ができません。モンキーパッチだと、ActionMailerの書き換えであるためその点も解消されます。
Appendix
- mail.transport_encoding = '8bit' とするとBase64エンコードを回避できる
- 添付ファイルもmail.parts.eachなどとしてcharsetを指定すればよさげ
- 最新版Mail 2.3.0でもbodyにcharsetが渡っていないため、同様に使えると思われる
- 二重の変換が無駄なため、Mail::Body#encoded相当の処理を今回上書きするメソッドに記述したほうがいい気がする
参考リンク
- mikel/mail ? GitHub
- Mail(gem) で送信するメールの本文を UTF-8 ではなく ISO-2022-JP にする方法 - Rubyとか Illustratorとか SFとか折紙とか
- 43 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CCsQFjAB&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=pLU4T7z4DY-VmQXn48T5AQ&usg=AFQjCNGalhroB5KRXyCKcGJSQU2uMmxyiw
- 32 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cts=1331100537087&ved=0CCYQFjAA&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=dvtWT5bGEMjCmQWJ3eXGDw&usg=AFQjCNGalhroB5KRXyCKcGJSQU2uMmxyiw&sig2=7XKdsrzUHK
- 25 http://www.google.co.jp/url?sa=t&rct=j&q=rails3 メール送信 サンプル&source=web&cd=1&ved=0CBwQFjAA&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=_6i
- 21 http://www.google.co.jp/url?sa=t&rct=j&q=メール iso変換&source=web&cd=4&ved=0CD8QFjAD&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=1wy8TuGADK7EmQXW5oihCA&usg=AFQjCNGalhroB5KRXyCKcGJS
- 18 http://reader.livedoor.com/reader/
- 15 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cts=1330756794780&ved=0CEQQFjAC&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=s7xRT5evEJDFmQWp7riJCg&usg=AFQjCNGalhroB5KRXyCKcGJSQU2uMmxyiw&sig2=gGScuNx7u8
- 14 http://www.google.co.jp/url?sa=t&rct=j&q=actionmailer::base charset&source=web&cd=3&ved=0CDgQFjAC&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=X1hBT_GKNOv2mAWC15zWBw&usg=AFQjCNGalhroB5KRXyCKcGJSQU2uMmxyiw
- 13 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cts=1331780517499&ved=0CD0QFjAD&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=kVthT8nWCojSmAXgueiECA&usg=AFQjCNGalhroB5KRXyCKcGJSQU2uMmxyiw&sig2=9DwZxentjj
- 12 http://t.co/HX3nup6x
- 11 http://www.google.co.jp/url?sa=t&rct=j&q=rails3.1+メール送信&source=web&cd=1&ved=0CEAQFjAA&url=http://d.hatena.ne.jp/deeeki/20111003/rails3_mailer_iso2022jp&ei=vqLcTuD1J4rRmAWAu9zdBw&usg=AFQjCNGalhroB5KRXyCKc





