Necessity:
Nowadays media queries support for email is considered a must due to the increasing number of client/device that supports them.

Hoped solution proposed by gabriel.achille in #7:
A recent update in the Emogrifier code (on which mimemail_compress is based on) does preserve @media queries now. So a solution could be to update mimemail_compress with a fresh version of emogrifier

Temporary solution provided by Dmitriy.trt in #3:
Dmitriy.trt has developed a sandbox module based on an external compressor that supports media queries (it is necessary to disable the built-in Mime Mail CSS Compressor)

Original issue reported by glynster:
I have been searching through the cases here and cannot seem to find anyone who has the issue I am experiencing. First and foremost, Mimemail and the compressor work very well. This means when we create our newsletter every week we do not have to worry about all the inline css, so a big props for this.

The issue I have is that I always add a media style sheet to the mimemail-message.tpl.php to help optimize handheld devices. Of course what happens is that css is converted to inline and the newsletter has the media queries applied to it.

Not sure if this is possible but the ultimate idea would be to keep the media style sheet untouched in the head while compressing the rest as per usual. If this is already possible any help would be greatly appreciated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

kruser’s picture

I ran into this issue too. I had to disable the Mime Mail CSS Compressor to get my media queries to work properly. I'm thinking there should be an option similar to the existing "Preserve class attributes", but instead called "Preserve CSS" - meaning that it would still compress the css, but also leave it in the Style tag in the Head. Then the media queries would still be there... the down side is the email size would get bigger.

Dmitriy.trt’s picture

A better option would be to leave only rules in media queries, not all styles.

Dmitriy.trt’s picture

Here is a sandbox project with a fork of the built-in Mime Mail CSS Compressor module that uses external CSS parser class to get contents of the <style> tag and separate simple rule sets from the ones wrapped with the @media block. It's really dirty at the moment, but it works for our use case and I'm going to continue development. Patches are really welcome!

I'm not proposing this solution as a patch for Mime Mail because it depends on the external library and requires PHP 5.3. Or, maybe, I should? After proper code rewrite, of course.

grantlucas’s picture

Thanks for that sandbox Dmitriy. I was having an issue with inline styles and it worked great.

dmsmidt’s picture

Would love to see this working without adding a sandbox project to my install.
Hopefully Dmitriy's work can somehow be integrated.

Dmitriy.trt’s picture

Looks like I won't have an opportunity to work on that project as a part of my job and my free time is really limited right now. But if anyone wants to maintain and develop it, please contact me through the contact form, I'll help with promoting it to a full project.

gabriel.achille’s picture

Issue summary: View changes

A recent update in the Emogrifier code (on which mimemail_compress is based on) does preserve @media queries now. So another solution could be to update mimemail_compress with a fresh version of emogrifier...

MXT’s picture

Title: Mimemail Compressor + Media Queries » Ugrade Mimemail Compressor to support Media Queries (like last Emogrifier already does)
Category: Support request » Feature request
Issue summary: View changes
mibfire’s picture

Any progress on this?

smiletrl’s picture

#3 works for me greatly.

mibfire’s picture

Yes, but it is just a temporary hack solution. This modules should be integrated into mimemail module.

dxx’s picture

Thanks Dmitriy.trt! :) It's works (successfully tested with PHP-CSS-Parser v6).

+1 for #11.

DanChadwick’s picture

Any progress on this? It would be great to see #7 go forward, or to incorporate Dmitriy.trt's work as an alternative compressor.

sgabe’s picture

The problem is that MimeMail Compressor contains some additional modifications and we need to preserve those changes in the update.

gabriel.achille’s picture

Status: Active » Needs review
FileSize
13.22 KB

@sgabe: if you are referring to the fact that before you had to extract first the style tags from the message (in the hook_mail_post_process) now this could be done by the emogrifier library itself.

Here is a patch proposal to upgrade Emogrifier for that: Please note the following:

  • The library emogrifier is kept outside of the module: hence it requires the user to dowload it.
  • It introduces a new dependencies: to the module libraries
  • I removed completely the file mimemail_compress.inc (which contained only the customised version of the lib)

Working ok for me.

joelpittet’s picture

This seems like a very sane approach. Other than the @todos in there I think this is a great patch! Thank you and I'll give it a try.

joelpittet’s picture

@gabriel.achille why not just require emogrifier module?

That way you don't have to check for DOM in the requirements or deal with the requirements at all.

joelpittet’s picture

How about this being the simplest version and taking that preg_replace from #15?

If the module exists, use it's process method. I'm not totally sure if the preg_replace is needed?

Also, I left the other method in there because it doesn't have any dependencies for BC.

joelpittet’s picture

Title: Ugrade Mimemail Compressor to support Media Queries (like last Emogrifier already does) » Upgrade Mimemail Compressor to support Media Queries (like last Emogrifier already does)
joelpittet’s picture

I'm quite sure that preg_replace isn't needed, and I made some typos.

Made a patch to make the API better on that module #2511742: Provide a public function for other modules to call if they require this module.

joelpittet’s picture

I should have tested that before posting... This patch actually works. Turns out I need to pass in lots of args because there are no defaults on that _emogrifier_process() function, that's a show stopper. Also needed to still run mimemail_compress_clean_message() or I'd get a bunch of garbage in the email (I assume that is because of those html comments in the style tag)

Not proud of the @ there... likely need to change that, see what others think.

gabriel.achille’s picture

@joelpittet: why not just require emogrifier module?:I guess we could have but I choose not to because it doesn't seem to be regularly maintained.
And I removed the DOM requirements check since Core requires it and already does this check.
Attached an updated version of the patch. The changes since #7 are:

  • Remove DOM check
  • add emogrifier version check in requirements
  • add more detailed requirements messages

not sure I did the interdiff right...

joelpittet’s picture

I agree that module doesn't seem to be getting much love, I like your approach here much better @gabriel.achille.

+++ b/modules/mimemail_compress/mimemail_compress.module
@@ -5,17 +5,38 @@
-    $output = new mimemail_compress($parts['html'], $parts['css']);
...
+  $emogrifier = new \Pelago\Emogrifier();
+  $emogrifier->setHtml($message);
+  // Apply the rules to create inline style attributes.
+  $text = @$emogrifier->emogrify();

Don't we have to put set the CSS too?

Ayesh’s picture

In relation to #7, I borrowed the media query regex, and used it in the modules compressor, which worked right away. I'm attaching a patch in case someone finds that approach suitable. (Requires PHP 5.3 due to the anonymous function used; not enforced from the .info file yet)

judahtanthony’s picture

What is the state of this? There seems to be talk of using emogrifier, but then it seems you just borrowed regex from it to pull out the media queires into $media; however, that patch does not actually do anything with that variable. What is the solution to this?

judahtanthony’s picture

FYI, I took the last patch but then did something with the $media. See below:

$ diff a/mimemail_compress.inc b/mimemail_compress.inc
14,24c14,33
<   $parts = array();
<   preg_match('|(<style[^>]+)>(.*)</style>|mis', $message, $matches);
<   if (isset($matches[0]) && isset($matches[2])) {
<     $css = str_replace('<!--', '', $matches[2]);
<     $css = str_replace('-->', '', $css);
<     $css = preg_replace('|\{|', "\n{\n", $css);
<     $css = preg_replace('|\}|', "\n}\n", $css);
<     $html = str_replace($matches[0], '', $message);
<     $parts = array('html' => $html, 'css' => $css);
<   }
<   return $parts;
---
>   $css = '';
>   // Let's strip out the CSS from the HTML.
>   $html = preg_replace_callback(
>     '|(<style[^>]+)>(.*)</style>|mis',
>     function($matches) use (&$css) {
>       $media = '';
>       // However, let's put back any media queries.
>       $css .= preg_replace_callback(
>         '#@media\\s+(?:only\\s)?(?:[\\s{\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU',
>         function($matches2) use (&$media) {
>           $media .= $matches2[0];
>           return '';
>         }, $matches[2]);
>       return empty($media) ? '' : str_replace($matches[2], $media, $matches[0]);
>     }, $message);
>   $css = str_replace('<!--', '', $css);
>   $css = str_replace('-->', '', $css);
>   $css = preg_replace('|\{|', "\n{\n", $css);
>   $css = preg_replace('|\}|', "\n}\n", $css);
>   return array('html' => $html, 'css' => $css);
jonloh’s picture

#26 above did work out pretty well for me without having to install the previous sandbox module.

This should be very much get committed to fix the @media issue.

sgabe’s picture

Sorry, I didn't get a chance to dive into this... Is only #26 needed to resolve this issue?

MrPeanut’s picture

I applied the patch from #24 and manually applied the changes from #26 but it doesn't seem to be working. My email is responsive if I test in something like PutsMail. Is there something else that needs done in conjunction with 24 and 26?

BryanGullan’s picture

Here's a patch for the mimemail module which combines #24 and #26. I've found this does the trick for me - thank you @Ayesh and @judahtanthony

The key other step is to ensure that you have "preserve classes" enabled in the mimemail settings: without the classes in place, media queries can't function. (@MrPeanut maybe that's what was missing for you.)