FIX: Make Email::Styles operate on html documents instead of fragments

FIX: Make Email::Styles operate on html documents instead of fragments

Nokogiri::HTML.fragment is a huge hack (a comment in the source code admits this). The current behavior of Email::Styles is to try to emulate fragment using nokogumbo, but it misses some edge cases. In particular, meta tags in a email template don’t make it through to the final email.

Instead of treating the provided HTML as an indeterminate fragment, this commit makes Email::Styles treat the HTML as a complete document. This means that the generated HTML for an email will now always contain top level structure (a doctype, html, head and body tags).

This new behavior is behind a hidden site setting for now and defaults off.

diff --git a/config/site_settings.yml b/config/site_settings.yml
index ecaf08d..c0488ee 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -1104,6 +1104,9 @@ email:
     client: true
     default: true
     hidden: true
+  preserve_email_structure_when_styling:
+    default: false
+    hidden: true
 
 files:
   max_image_size_kb:
diff --git a/lib/email/styles.rb b/lib/email/styles.rb
index 69bfc7e..9b879b2 100644
--- a/lib/email/styles.rb
+++ b/lib/email/styles.rb
@@ -242,7 +242,12 @@ module Email
       strip_classes_and_ids
       replace_relative_urls
       replace_secure_media_urls
-      include_body? ? @fragment.at("body").to_html : @fragment.at("body").children.to_html
+
+      if SiteSetting.preserve_email_structure_when_styling
+        @fragment.to_html
+      else
+        include_body? ? @fragment.at("body").to_html : @fragment.at("body").children.to_html
+      end
     end
 
     def include_body?

GitHub sha: 1bd8a075

1 Like