views:

100

answers:

3

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.

http://stackoverflow.com/questions/364162/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"

A: 

If you are going to mention the

layout "email"

Its obviously going to render a layout. Comment or delete that line ! And have the corresponding erb view contain only the text you want to be sent (if any).

Shreyas Satish
well sure, but the point is i have about 20 other mailers which use the layout... and only one which does not.
holden
+1  A: 

OK, not sure if this works, but it seems the default content_type is text/plain, so you would only need to set the content type if you want something other than text/plain.

Try this:

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

I still think you should consider this:

layout "email", :except => [:send_inquiry]

I would use the above because the plain text email does not seem to have a 'layout', only the actual content you want to send.

captaintokyo
That's probably a quick fix, but I'd still like it if I could figure out why the functionality that is supposedly built in isn't working. IE, when I declare a content_type it is supposed to look for the appropriate file?
holden
I updated my answer.. not sure, but it's worth a try. Good luck.
captaintokyo
+2  A: 

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.

PeterD
Hm, interesting. Contrary to what you are saying, according to the API docs the default content_type is text/plain...
captaintokyo
That would've made more sense to me too, but look for #default_template_format in ActionMailer::Base, that's the culprit as far as I can work out. I will keep looking and update this as I find more.
PeterD
I think I've figured it out, more or less. My problem was that I was defining the parts manually with "part :body => render_message()", if you do this ActionMailer ignores the content_type and just defaults to html, like I described above.But if you let Rails automagically determine the parts, render_message gets an ActionView::ReloadableTemplate instead of a string passed as "method_name" (talk about misleading variable names) and content_type detection works.
PeterD
But after I changed that the layouts still weren't rendered properly. the problem was that the naming scheme for email layouts isn't the same as for email templates. The email template needs to be named e.g. contact_form.text.plain.erb, but the layouts need to be named email_layout.text.erb and email_layout.html.erbSo not the full mime type, but just text or html. Once I changed that it worked for me.
PeterD
Your last comment sounds like the solution. Great work. I wonder if it also works for holden.. If so, he should accept your answer, so others can find the solution to this problem too.
captaintokyo
That still doesn't do if for me... I changed the names of the templates as suggested but it still always uses the email.html.erb when I specify text/plain as content_type... no parts specified.
holden
The only difference I get is when content_type is set as text/plain, the html template gets rendered as pure text so I get all the html tags in my email and it looks horrific.
holden
Interestingly email.text.html.erb takes precedence over email.html.erb
holden
Yeah with the content-type set to plaintext the mail client would render the html layout as visible text, that makes sense. I did notice one other thing that might be causing your problem; you're manually setting "content_type 'text/html'", which Rails should be able to determine from the naming of your templates. What happens if you remove the content_type lines from the mailer model?(edit: curse SO's auto submit on enter ^^)
PeterD