Skip to content

Instantly share code, notes, and snippets.

@dblock
Created May 17, 2012 14:57
Show Gist options
  • Save dblock/2719486 to your computer and use it in GitHub Desktop.
Save dblock/2719486 to your computer and use it in GitHub Desktop.
Insert an automatic text MIME part into HTML e-mail.
#
# Insert an automatic text MIME part into HTML e-mail.
# (c) Daniel Doubrovkine, Art.sy 2012
# MIT License
#
class ActionMailerWithTextPart < ActionMailer::Base
def collect_responses_and_parts_order(headers)
responses, parts_order = super(headers)
html_part = responses.detect { |response| response[:content_type] == "text/html" }
text_part = responses.detect { |response| response[:content_type] == "text/plain" }
if html_part && ! text_part
body_parts = []
Nokogiri::HTML(html_part[:body]).traverse do |node|
if node.text? and ! (content = node.content ? node.content.strip : nil).blank?
body_parts << content
elsif node.name == "a" && (href = node.attr("href")) && href.match(/^https?:/)
body_parts << href
end
end
responses.insert 0, { content_type: "text/plain", body: body_parts.uniq.join("\n") }
parts_order.insert 0, "text/plain"
end
[responses, parts_order]
end
end
@nateberkopec
Copy link

I've added a Rails 4 compatible fork. As the person that introduced the commit that broke this neat little trick, I felt obliged 😅

EDIT: also, I think this method as written doesn't work unless you explicitly provide a block to #mail. Changing line 22 to:

  parts_order && parts_order.insert(0, "text/plain")

should do the trick I think if you do your mail method implicitly.

@dblock
Copy link
Author

dblock commented Mar 29, 2013

Thanks @nateberkopec !

@dblock
Copy link
Author

dblock commented Oct 25, 2013

For Rails 4:

class ActionMailerWithTextPart < ActionMailer::Base
  def collect_responses(headers)
    responses = super headers
    html_part = responses.detect { |response| response[:content_type] == "text/html" }
    text_part = responses.detect { |response| response[:content_type] == "text/plain" }
    if html_part && ! text_part
      body_parts = []
      Nokogiri::HTML(html_part[:body]).traverse do |node|
        if node.text? and ! (content = node.content ? node.content.strip : nil).blank?
          body_parts << content
        elsif node.name == "a" && (href = node.attr("href")) && href.match(/^https?:/)
          body_parts << href
        end
      end
      responses.insert 0, { content_type: "text/plain", body: body_parts.uniq.join("\n") }
      headers[:parts_order] = [ "text/plain" ] + headers[:parts_order] unless headers[:parts_order].include?("text/plain")
    end
    responses
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment