edit: It turned out that the layouts follow a different naming scheme for email templates. Just rename them as follows:
layout.text.html.erb => layout.html.erb layout.text.plain.erb => layout.text.erb
I also made a mistake when manually defining parts if you use this:
part :content_type => 'text/plain', :body => render_message('my_template')
Rails then cannot determine the content_type for your part and assumes that it is HTML.
After I changed these two things, it worked for me!
The original answer follows.
I have struggled with this issue many times in the past, usually ending with some kind of dry, quick and dirty solution. I always thought that I was the only one who has this problem, because Google has nothing useful in this matter.
This time I decided to delve into Rails to understand this, but so far without much success, but perhaps my results will help someone understand this.
I found that in ActionMailer :: Base, the #render_message method was given the definition of the correct content_type and assigned it @current_template_content_type. #default_template_format, it either returns the correct mime type for the layout, or if @current_template_content_type is not set, it will be by default: html.
This is what ActionMailer :: Base # render_message looks like in my application (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 problem is that the method name is a string (the name of the local view, in my case "new_password.text.html"), and the strings, of course, do not respond to_content_type, and the value of @current_template_content_type will always remain null, and therefore #default_template_format will always will be the default: html.
I do not know what is closer to the real solution. The internal elements of ActionMailer are too opaque to me.