Rails Email 同時提供 plain 及 html 版本

讓 Email 同時提供 text/plain 跟 text/html 版本,讓不支援 HTML 的 Email client 也可以顯示 plain 是一種是具有親和力的作法。根據 multipart-alternative 的定義,正確的格式應該長這樣,用 boundary 分隔成兩個部份:

   From:  Nathaniel Borenstein <nsb@bellcore.com>
   To: Ned Freed <ned@innosoft.com>
   Subject: Formatted text mail
   MIME-Version: 1.0
   Content-Type: multipart/alternative; boundary=boundary42

   --boundary42

   Content-Type: text/plain; charset=utf-8

   ...plain text version of message goes here....

   --boundary42
   Content-Type: text/html; charset=utf-8

   .... html version of same message goes here ...

   --boundary42--


一個方法來自 Rails Recipes(for Rails 1.1) 書上的作法:


  def signup_notification(user)
    @from        = EXTERNAL_MAIL_SENDER
    @subject     = "Please activate your new account"
    @sent_on     = Time.now
    @recipients  = user.email
    @body[:user] = user

    content_type "multipart/alternative"
    
    part :content_type => "text/plain",
       :body => render_message("signup_notification_plain", @body )
     part :content_type => "text/html",
       :body => render_message("signup_notification", @body )
  end

檔案則是 signup_notification_plain.rhtml 跟 signup_notification.rhtml

不過經過 IRC #elixus 的朋友反應,在 mutt 跟 thunderbird 上看不到正確的 encoding。這才仔細看了 raw email data,竟然出來了三段 part 且第一段少了 charset utf-8。試著幾種不同寫法仍得不到看起來正確的格式,Rails Wiki 上的作法出來的格式也很奇怪。

本來想棄守 console-based email client 了,只提供 HTML 就好,但是布丁大人堅持要有 Gracefully Degrading 啊。於是再去看 ActionMailer API 發現其實有更簡單厲害的作法:

  def signup_notification(user)
    @from        = EXTERNAL_MAIL_SENDER
    @subject     = "Please activate your new account"
    @sent_on     = Time.now
    @recipients  = user.email
    @body[:user] = user
  end

檔案則要命名成 signup_notification.text.plain.erbsignup_notification.text.html.erb。嗯,Rails 依據副檔名慣例會自動合併成一封信,而無須寫明 content_type 跟使用 part。

我自己還有用Globalize plugin提供中英文不同版本,所以又還有 signup_notification.zh-TW.text.plain.erbsignup_notification.zh-TW.text.html.erb,真是長的副檔名啊 :>

參與討論

1 則留言

  1. 這自動合併plain及html的部份,在rails 2.3.2能用嗎?
    我試了都不行,是那裏不對呢?

發佈留言

發表迴響