yo-log

@yo-iidaのlog

ActionMailerのparts_orderのバージョンによる挙動の差異

railsのmultipartのメール配信で、ActionMailerのバージョンの差異で詰まったのでメモ。

multipartのメールを送る場合、parts_orderというパラメータでメール形式の優先度を指定することができます。

class ApplicationMailer < ActionMailer::Base
  default parts_order: ["text/plain", "text/html"]
end

こんなかんじで、parts_orderを指定します。 ぱっと見text/plainが一番優先されそうですが、RFCでは一番最後のものが優先される仕様になっています。 なので、上の場合だと、

text/html > text/plain

という優先度になり、htmlメールを閲覧できるクライアントではデフォルトでhtmlメールが表示されます。

ただ、ActionMailer4.0.0未満では、mailメソッドにブロックを渡すと、ブロック内で定義した形式順に優先度を上書きできる仕様になっていました。

class ApplicationMailer < ActionMailer::Base
  default parts_order: ["text/plain", "text/html"]

  def _multipart_mail(headers={})
    mail(headers) do |format|
      format.html {...}
      format.text {...} # ActionMailer4.0.0未満ではparts_order関係なく後に書いた方が優先される
    end
  end
end

なので、上記のようにparts_orderの順序とblock内の順序が異なると思わぬ挙動になる可能性があります。 multipartで意図した形式でメール配信されない場合にはこのあたりを疑ってみるとよいかもしれません。

上記のActionMailerの仕様変更は下記にまとまっています。

ActionMailer overrides header[:parts_order] when a block is passed to #mail · Issue #7978 · rails/rails · GitHub

rails/CHANGELOG.md at 4-0-stable · rails/rails · GitHub

change logみると4.0.0に下記が含まれています。

Explicit multipart messages no longer set the order of the MIME parts.

Nate Berkopec