概要
ActionMailerで送信したメールの本文を添付ファイルの有無にかかわらず取得します1。
メール本文の内容をテストするときなどにお使いください。
コード
def get_mail_body(mail)
parts = mail.body.parts
# partsにさらにマルチパートメールが含まれる(=添付ファイルがある)場合はメール部分のみを取得
if parts.map(&:multipart?).inject(:|)
multipart_mails = parts.find(&:multipart?).parts
else
multipart_mails = parts
end
# テキストメールの本文を取得して返す
multipart_mails.find{|part| part.content_type.match 'text/plain'}.body.raw_source
end
mail = HogeMailer.send_mail.deliver
body = get_mail_body(mail)
解説
Mail::Messageのインスタンスはpartsという配列を持っています。ここに格納されるのは、
-
添付ファイルがない場合
- テキストとHTMLのメール
-
添付ファイルがある場合
- メールの配列2
- 添付ファイル
になります。
ですから、メール本文を取得しようと思うと、添付ファイルの有無で調べなくてはならない配列の深さが変わります。
ところで、partsの成分はすべてMail::Partというラッパーのインスタンスになっており、Mail::Part#multipart?を叩くとメールの配列であるかどうかを真偽値で返してくれます。
これを利用して**partsの各要素に対してmultipart?を実行して論理和を取れ**ば、partsにメールの配列があるかどうかわかるという寸法です。
ちなみに
if文の部分はワンライナーでも書けます。見づらいですけど。
multipart_mails = (parts.map(&:multipart?).inject(:|) ? parts.find(&:multipart?).parts : parts)
バージョン
- Ruby 2.2.6
- Rails, ActionMailer 3.2.22.5
古い環境で調べたので最新の環境で動くかはわかりません(変わったことはしてないので動くと思いますが……)。