Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails escapes HTML in my plain text mails

I am using the rails 3.2.5 ActionMailer to send plain text mails. Given I have a mail view like this:

message_from_user.text.erb:

Hi <%= @recipient.name %>,

You got the following message from <%= @sender.name %>:

<%= @message %>

When @message is "quotes & ampersands", then the plain text mail contains &quot;quotes &amp; ampersands&quot;. So it seems like rails just treats this as a HTML view and escapes any html in order to prevent cross site scripting. However this is a plain text mail. The extension is .text.erb and ActionMailer detectes this and sets the MIME to text/plain. So I never want to escape any html in it.

I have quite a few mail templates in my application, they are all plain text. I would consider patching all of them to include <%=raw @message%> or <%= @message.html_safe %> bad style - not very DRY.

I tried varios work-arounds that included money patching Erubis. None of them seem to work. I am looking for some patch or config option or anything to disable escaping html for all .text.erb files.

Any help is greatly appreciated!

like image 590
iblue Avatar asked Aug 01 '12 09:08

iblue


1 Answers

After some hours of debugging through the Erubis code, I found the following fix. You can just put it into config/initializers/fix_my_mails.rb. I've tested this with rails 3.2.7. It may work with other versions.

module ActionView
  class Template
    module Handlers
      class ERB
        def call(template)
          if template.source.encoding_aware?
            # First, convert to BINARY, so in case the encoding is
            # wrong, we can still find an encoding tag
            # (<%# encoding %>) inside the String using a regular
            # expression
            template_source = template.source.dup.force_encoding("BINARY")

            erb = template_source.gsub(ENCODING_TAG, '')
            encoding = $2

            erb.force_encoding valid_encoding(template.source.dup, encoding)

            # Always make sure we return a String in the default_internal
            erb.encode!
          else
            erb = template.source.dup
          end

          self.class.erb_implementation.new(
            erb,
            :trim => (self.class.erb_trim_mode == "-"),
            :escape => template.identifier =~ /\.text/ # only escape HTML templates
          ).src
        end
      end
    end
  end
end

It just disables HTML entities in every erb file containing .text in the file name.

like image 123
iblue Avatar answered Sep 18 '22 23:09

iblue