rails mailer with different layouts

holden picture holden · Sep 6, 2010 · Viewed 9.8k times · Source

I use one layout for all my emails in my Notifier model (20+ emails)... however sometimes I just want to send a plain text email with no layout or html at all. I can't seem to be able to figure out how? If I try to send a plain text email i still get the layout, and all the HTML in the email.

I'm using Rails 2.3.8.

I read about this monkey patch here... but it seemed to indicate a newer version of rails had over come this? And I don't really wanna monkey patch if I can avoid one.

Rails - setting multiple layouts for a multipart email with mailer templates

  layout "email" # use email.text.(html|plain).erb as the layout


  def welcome_email(property)
    subject    'New Signup'
    recipients property.email
    from       '[email protected]'
    body       :property => property
    content_type "text/html"
  end

  def send_inquiry(inquire)
    subject    "#{inquire.the_subject}"
    recipients inquire.ob.email
    from       "Test on behalf of #{inquire.name} <#{inquire.email}>"
    body       :inquire => inquire
    content_type "text/plain"

  end

I also have 2 files.

email.text.html.erb
email.text.plain.erb

It always uses text.html.erb... even if the content_type is "text/plain"

Answer

Peter Duijnstee picture Peter Duijnstee · Sep 14, 2010

edit: Figured it out, the layouts follow a different naming scheme to the email templates. Just rename them as follows:

layout.text.html.erb    => layout.html.erb
layout.text.plain.erb   => layout.text.erb

I also made the mistake of manually defining the parts, if you use this:

part :content_type => 'text/plain',
     :body => render_message('my_template')

Then Rails can't determine the content_type for your part and it assumes it's HTML.

After I changed those two things it worked for me!

original reply follows..


I've struggled with this question many times in the past, usually ending up with some sort of non-dry quick and dirty solution. I always thought I was the only one with this problem because Google turns up exactly nothing useful on the subject.

This time I decided to dig into Rails to figure it out but so far without much success, but maybe my findings will help someone else figure this out.

What I found was that in ActionMailer::Base the #render_message method is tasked with determining the proper content_type and should assign it to @current_template_content_type. #default_template_format then either returns the proper mime type for the layout or, if @current_template_content_type isn't set, it will default to :html.

This is what ActionMailer::Base#render_message looks like in my app (2.3.5)

  def render_message(method_name, body)
    if method_name.respond_to?(:content_type)
      @current_template_content_type = method_name.content_type
    end
    render :file => method_name, :body => body
  ensure
    @current_template_content_type = nil
  end

The trouble is that method_name appears to be a string (the name of the local view, in my case "new_password.text.html") and strings of course do not respond_to #content_type, meaning @current_template_content_type will always remain nil, and so the #default_template_format will always default to :html.

Not much closer to an actual solution, I know. The ActionMailer internals are just too opaque for me.