Giter Site home page Giter Site logo

premailer-rails's Introduction

premailer-rails

CSS styled emails without the hassle.

Build Status Gem Version Code Climate

Introduction

This gem is a drop in solution for styling HTML emails with CSS without having to do the hard work yourself.

Styling emails is not just a matter of linking to a stylesheet. Most clients, especially web clients, ignore linked stylesheets or <style> tags in the HTML. The workaround is to write all the CSS rules in the style attribute of each tag inside your email. This is a rather tedious and hard to maintain approach.

Premailer to the rescue! The great premailer gem applies all CSS rules to each matching HTML element by adding them to the style attribute. This allows you to keep HTML and CSS in separate files, just as you're used to from web development, thus keeping your sanity.

This gem is an adapter for premailer to work with actionmailer out of the box. Actionmailer is the email framework used in Rails, which also works outside of Rails. Although premailer-rails has certain Rails specific features, it also works in the absence of Rails making it compatible with other frameworks such as sinatra.

How It Works

premailer-rails works with actionmailer by registering a delivery hook. This causes all emails that are delivered to be processed by premailer-rails. This means that by simply including premailer-rails in your Gemfile you'll get styled emails without having to set anything up.

Whenever premailer-rails processes an email, it collects the URLs of all linked stylesheets (<link rel="stylesheet" href="css_url">). Then, for each of these URLs, it tries to get the content through a couple of strategies. As long as a strategy does not return anything, the next one is used. The strategies available are:

  • :filesystem: If there's a file inside public/ with the same path as in the URL, it is read from disk. E.g. if the URL is http://cdn.example.com/assets/email.css the contents of the file located at public/assets/email.css gets returned if it exists.

  • :asset_pipeline: If Rails is available and the asset pipeline is enabled, the file is retrieved through the asset pipeline. E.g. if the URL is http://cdn.example.com/assets/email-fingerprint123.css, the file email.css is requested from the asset pipeline. That is, the fingerprint and the prefix (in this case assets is the prefix) are stripped before requesting it from the asset pipeline.

  • :network: As a last resort, the URL is simply requested and the response body is used. This is useful when the assets are not bundled in the application and only available on a CDN. On Heroku e.g. you can add assets to your .slugignore causing your assets to not be available to the app (and thus resulting in a smaller app) and deploy the assets to a CDN such as S3/CloudFront.

You can configure which strategies you want to use as well as specify their order. Refer to the Configuration section for more on this.

Note that the retrieved CSS is cached when the gem is running with Rails in production.

Installation

Simply add the gem to your Gemfile:

gem 'premailer-rails'

premailer-rails and premailer require a gem that is used to parse the email's HTML. For a list of supported gems and how to select which one to use, please refer to the Adapter section of premailer. Note that there is no hard dependency from either gem so you should add one yourself. Also note that this gem is only tested with nokogiri.

Configuration

Premailer itself accepts a number of options. In order for premailer-rails to pass these options on to the underlying premailer instance, specify them as follows (in Rails you could do that in an initializer such as config/initializers/premailer_rails.rb):

Premailer::Rails.config.merge!(preserve_styles: true, remove_ids: true)

For a list of options, refer to the premailer documentation. The default configs are:

{
  input_encoding: 'UTF-8',
  generate_text_part: true,
  strategies: [:filesystem, :asset_pipeline, :network]
}

If you don't want to automatically generate a text part from the html part, set the config :generate_text_part to false.

Note that the options :with_html_string and :css_string are used internally by premailer-rails and thus will be overridden.

If you're using this gem outside of Rails, you'll need to call Premailer::Rails.register_interceptors manually in order for it to work. This is done ideally in some kind of initializer, depending on the framework you're using.

premailer-rails reads all stylesheet <link> tags, inlines the linked CSS and removes the tags. If you wish to ignore a certain tag, e.g. one that links to external fonts such as Google Fonts, you can add a data-premailer="ignore" attribute.

Usage

premailer-rails processes all outgoing emails by default. If you wish to skip premailer for a certain email, simply set the :skip_premailer header:

class UserMailer < ActionMailer::Base
  def welcome_email(user)
    mail to: user.email,
         subject: 'Welcome to My Awesome Site',
         skip_premailer: true
  end
end

Note that the mere presence of this header causes premailer to be skipped, i.e., even setting skip_premailer: false will cause premailer to be skipped. The reason for that is that the skip_premailer is a simple header and the value is transformed into a string, causing 'false' to become truthy.

Emails are only processed upon delivery, i.e. when calling #deliver on the email, or when previewing them in rails. If you wish to manually trigger the inlining, you can do so by calling the hook:

mail = SomeMailer.some_message(args)
Premailer::Rails::Hook.perform(mail)

This will modify the email in place, useful e.g. in tests.

Supported Rails Versions

This gem is tested on Rails versions 5 through 7.

For Rails 7, it support both the classical Sprockets asset pipeline as well as the new Propshaft gem.

If you're looking to integrate with Webpacker, check out these instructions.

Small Print

Author

Philipe Fatio (@fphilipe)

License

premailer-rails is released under the MIT license. See the license file.

premailer-rails's People

Contributors

alethea avatar andrewhubbs avatar atinder avatar bitdeli-chef avatar brandonhilkert avatar c960657 avatar der-flo avatar dnagir avatar eclubb avatar edwardbetts avatar elmassimo avatar eveevans avatar fphilipe avatar guiocavalcanti avatar igas avatar iloveitaly avatar intrepidd avatar javierjulio avatar jezstephens avatar jonnii avatar kendrikat avatar kirs avatar lime avatar lujanfernaud avatar luma avatar maschwenk avatar masterexploder avatar pabloh avatar panthomakos avatar rafbm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

premailer-rails's Issues

Looks like doesn't play well with `turbo-sprockets-rails3'

It works fine in development environment, but on remote server, it throw exception Sass::SyntaxError

Full Error:

Sass::SyntaxError: File to import not found or unreadable: compass. 

Here's the backtrace on the application.

sass-3.2.1/lib/sass/tree/import_node.rb:64โ†’ rescue in import
sass-3.2.1/lib/sass/tree/import_node.rb:42โ†’ import
sass-3.2.1/lib/sass/tree/import_node.rb:25โ†’ imported_file
sass-3.2.1/lib/sass/tree/visitors/perform.rb:227โ†’ rescue in visit_import
sass-3.2.1/lib/sass/tree/visitors/perform.rb:232โ†’ visit_import
sass-3.2.1/lib/sass/tree/visitors/base.rb:37โ†’ visit
sass-3.2.1/lib/sass/tree/visitors/perform.rb:98โ†’ visit
sass-3.2.1/lib/sass/tree/visitors/base.rb:53โ†’ block in visit_children
sass-3.2.1/lib/sass/tree/visitors/base.rb:53โ†’ map
sass-3.2.1/lib/sass/tree/visitors/base.rb:53โ†’ visit_children
sass-3.2.1/lib/sass/tree/visitors/perform.rb:107โ†’ block in visit_children
sass-3.2.1/lib/sass/tree/visitors/perform.rb:119โ†’ with_environment
sass-3.2.1/lib/sass/tree/visitors/perform.rb:106โ†’ visit_children
sass-3.2.1/lib/sass/tree/visitors/base.rb:37โ†’ block in visit
sass-3.2.1/lib/sass/tree/visitors/perform.rb:126โ†’ visit_root
sass-3.2.1/lib/sass/tree/visitors/base.rb:37โ†’ visit
sass-3.2.1/lib/sass/tree/visitors/perform.rb:98โ†’ visit
sass-3.2.1/lib/sass/tree/visitors/perform.rb:7โ†’ visit
sass-3.2.1/lib/sass/tree/root_node.rb:20โ†’ render
sass-3.2.1/lib/sass/engine.rb:315โ†’ _render
sass-3.2.1/lib/sass/engine.rb:262โ†’ render
tilt-1.3.3/lib/tilt/css.rb:24โ†’ evaluate
tilt-1.3.3/lib/tilt/template.rb:76โ†’ render
sprockets-2.1.3/lib/sprockets/context.rb:177โ†’ block in evaluate
sprockets-2.1.3/lib/sprockets/context.rb:174โ†’ each
sprockets-2.1.3/lib/sprockets/context.rb:174โ†’ evaluate
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/processed_asset.rb:16โ†’ initialize
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:18โ†’ new
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:18โ†’ block in build_asset
sprockets-2.1.3/lib/sprockets/base.rb:262โ†’ circular_call_protection
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:14โ†’ build_asset
sprockets-2.1.3/lib/sprockets/index.rb:89โ†’ block in build_asset
sprockets-2.1.3/lib/sprockets/caching.rb:19โ†’ cache_asset
sprockets-2.1.3/lib/sprockets/index.rb:88โ†’ build_asset
sprockets-2.1.3/lib/sprockets/base.rb:163โ†’ find_asset
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/index.rb:14โ†’ find_asset
turbo-sprockets-rails3-0.2.10/lib/sprockets/asset_with_dependencies.rb:91โ†’ block in build_required_assets
turbo-sprockets-rails3-0.2.10/lib/sprockets/asset_with_dependencies.rb:85โ†’ each
turbo-sprockets-rails3-0.2.10/lib/sprockets/asset_with_dependencies.rb:85โ†’ build_required_assets
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/processed_asset.rb:20โ†’ initialize
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:18โ†’ new
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:18โ†’ block in build_asset
sprockets-2.1.3/lib/sprockets/base.rb:262โ†’ circular_call_protection
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:14โ†’ build_asset
sprockets-2.1.3/lib/sprockets/index.rb:89โ†’ block in build_asset
sprockets-2.1.3/lib/sprockets/caching.rb:19โ†’ cache_asset
sprockets-2.1.3/lib/sprockets/index.rb:88โ†’ build_asset
sprockets-2.1.3/lib/sprockets/base.rb:163โ†’ find_asset
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/index.rb:14โ†’ find_asset
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/bundled_asset.rb:12โ†’ initialize
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:22โ†’ new
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/base.rb:22โ†’ build_asset
sprockets-2.1.3/lib/sprockets/index.rb:89โ†’ block in build_asset
sprockets-2.1.3/lib/sprockets/caching.rb:19โ†’ cache_asset
sprockets-2.1.3/lib/sprockets/index.rb:88โ†’ build_asset
sprockets-2.1.3/lib/sprockets/base.rb:163โ†’ find_asset
turbo-sprockets-rails3-0.2.10/lib/turbo-sprockets/sprockets_overrides/index.rb:14โ†’ find_asset
premailer-rails3-1.3.1/lib/premailer-rails3/css_loaders.rb:40โ†’ load
premailer-rails3-1.3.1/lib/premailer-rails3/css_helper.rb:44โ†’ block in load_css
premailer-rails3-1.3.1/lib/premailer-rails3/css_helper.rb:43โ†’ each
premailer-rails3-1.3.1/lib/premailer-rails3/css_helper.rb:43โ†’ load_css
premailer-rails3-1.3.1/lib/premailer-rails3/css_helper.rb:22โ†’ css_for_doc
premailer-rails3-1.3.1/lib/premailer-rails3/premailer.rb:14โ†’ initialize
premailer-rails3-1.3.1/lib/premailer-rails3/hook.rb:18โ†’ new
premailer-rails3-1.3.1/lib/premailer-rails3/hook.rb:18โ†’ delivering_email
mail-2.4.4/lib/mail/mail.rb:230โ†’ block in inform_interceptors
mail-2.4.4/lib/mail/mail.rb:229โ†’ each
mail-2.4.4/lib/mail/mail.rb:229โ†’ inform_interceptors
mail-2.4.4/lib/mail/message.rb:217โ†’ inform_interceptors
mail-2.4.4/lib/mail/message.rb:227โ†’ deliver
devise-2.1.2/lib/devise/models/authenticatable.rb:163โ†’ send_devise_notification
devise-2.1.2/lib/devise/models/recoverable.rb:48โ†’ send_reset_password_instructions
devise-2.1.2/lib/devise/models/recoverable.rb:110โ†’ send_reset_password_instructions
devise-2.1.2/app/controllers/devise/passwords_controller.rb:13โ†’ create
actionpack-3.2.8/lib/action_controller/metal/implicit_render.rb:4โ†’ send_action
actionpack-3.2.8/lib/abstract_controller/base.rb:167โ†’ process_action
actionpack-3.2.8/lib/action_controller/metal/rendering.rb:10โ†’ process_action
actionpack-3.2.8/lib/abstract_controller/callbacks.rb:18โ†’ block in process_action
activesupport-3.2.8/lib/active_support/callbacks.rb:447โ†’ _run__FRAGMENT__process_action__FRAGMENT__callbacks
activesupport-3.2.8/lib/active_support/callbacks.rb:405โ†’ __run_callback
activesupport-3.2.8/lib/active_support/callbacks.rb:385โ†’ _run_process_action_callbacks
activesupport-3.2.8/lib/active_support/callbacks.rb:81โ†’ run_callbacks
actionpack-3.2.8/lib/abstract_controller/callbacks.rb:17โ†’ process_action
actionpack-3.2.8/lib/action_controller/metal/rescue.rb:29โ†’ process_action
actionpack-3.2.8/lib/action_controller/metal/instrumentation.rb:30โ†’ block in process_action
activesupport-3.2.8/lib/active_support/notifications.rb:123โ†’ block in instrument
activesupport-3.2.8/lib/active_support/notifications/instrumenter.rb:20โ†’ instrument
activesupport-3.2.8/lib/active_support/notifications.rb:123โ†’ instrument
actionpack-3.2.8/lib/action_controller/metal/instrumentation.rb:29โ†’ process_action
actionpack-3.2.8/lib/action_controller/metal/params_wrapper.rb:207โ†’ process_action
activerecord-3.2.8/lib/active_record/railties/controller_runtime.rb:18โ†’ process_action
actionpack-3.2.8/lib/abstract_controller/base.rb:121โ†’ process
actionpack-3.2.8/lib/abstract_controller/rendering.rb:45โ†’ process
actionpack-3.2.8/lib/action_controller/metal.rb:203โ†’ dispatch
actionpack-3.2.8/lib/action_controller/metal/rack_delegation.rb:14โ†’ dispatch
actionpack-3.2.8/lib/action_controller/metal.rb:246โ†’ block in action
actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:73โ†’ call
actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:73โ†’ dispatch
actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:36โ†’ call
actionpack-3.2.8/lib/action_dispatch/routing/mapper.rb:42โ†’ call
journey-1.0.4/lib/journey/router.rb:68โ†’ block in call
journey-1.0.4/lib/journey/router.rb:56โ†’ each
journey-1.0.4/lib/journey/router.rb:56โ†’ call
actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:600โ†’ call
warden-1.2.1/lib/warden/manager.rb:35โ†’ block in call
warden-1.2.1/lib/warden/manager.rb:34โ†’ catch
warden-1.2.1/lib/warden/manager.rb:34โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/best_standards_support.rb:17โ†’ call
rack-1.4.1/lib/rack/etag.rb:23โ†’ call
rack-1.4.1/lib/rack/conditionalget.rb:35โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/head.rb:14โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/params_parser.rb:21โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/flash.rb:242โ†’ call
rack-1.4.1/lib/rack/session/abstract/id.rb:205โ†’ context
rack-1.4.1/lib/rack/session/abstract/id.rb:200โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/cookies.rb:339โ†’ call
activerecord-3.2.8/lib/active_record/query_cache.rb:64โ†’ call
activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_pool.rb:473โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/callbacks.rb:28โ†’ block in call
activesupport-3.2.8/lib/active_support/callbacks.rb:405โ†’ _run__FRAGMENT__call__FRAGMENT__callbacks
activesupport-3.2.8/lib/active_support/callbacks.rb:405โ†’ __run_callback
activesupport-3.2.8/lib/active_support/callbacks.rb:385โ†’ _run_call_callbacks
activesupport-3.2.8/lib/active_support/callbacks.rb:81โ†’ run_callbacks
actionpack-3.2.8/lib/action_dispatch/middleware/callbacks.rb:27โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/remote_ip.rb:31โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/debug_exceptions.rb:16โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/show_exceptions.rb:56โ†’ call
railties-3.2.8/lib/rails/rack/logger.rb:26โ†’ call_app
railties-3.2.8/lib/rails/rack/logger.rb:16โ†’ call
actionpack-3.2.8/lib/action_dispatch/middleware/request_id.rb:22โ†’ call
rack-1.4.1/lib/rack/methodoverride.rb:21โ†’ call
rack-1.4.1/lib/rack/runtime.rb:17โ†’ call
activesupport-3.2.8/lib/active_support/cache/strategy/local_cache.rb:72โ†’ call
rack-1.4.1/lib/rack/lock.rb:15โ†’ call
rack-cache-1.2/lib/rack/cache/context.rb:136โ†’ forward
rack-cache-1.2/lib/rack/cache/context.rb:143โ†’ pass
rack-cache-1.2/lib/rack/cache/context.rb:155โ†’ invalidate
rack-cache-1.2/lib/rack/cache/context.rb:71โ†’ call!
rack-cache-1.2/lib/rack/cache/context.rb:51โ†’ call
railties-3.2.8/lib/rails/engine.rb:479โ†’ call
railties-3.2.8/lib/rails/application.rb:223โ†’ call
railties-3.2.8/lib/rails/railtie/configurable.rb:30โ†’ method_missing
rack-1.4.1/lib/rack/commonlogger.rb:20โ†’ call
sinatra-1.3.3/lib/sinatra/base.rb:136โ†’ call
puma-1.6.3/lib/puma/server.rb:412โ†’ handle_request
puma-1.6.3/lib/puma/server.rb:306โ†’ process_client
puma-1.6.3/lib/puma/server.rb:215โ†’ block in run
puma-1.6.3/lib/puma/thread_pool.rb:94โ†’ call
puma-1.6.3/lib/puma/thread_pool.rb:94โ†’ block in spawn_thread

And part of the email.css file

/*
 *= require email_layout
 */

part of the email_layout.css.scss file

@import 'compass';

$base: #019AD2;

The same error happens when I try to run Rails.application.assets.find_asset('email.css') on remote server's console.

Sorry I cannot put more details because it happens on my company's project, and I dont have time to create a example app now.

Hope these will help. ๐ŸŽƒ

Asset precompilation and strategy order

Hello hello,

I have forked premailer-rails3 because it has caused me a small problem in production.

I compile all assets during deployment, and have disabled asset compilation during runtime. premailer-rails3 asks Sprockets for assets, which doesn't work because in my case compass isn't loaded in production, and attempting to import it raises a Sass error.

Accessing the file via the filesystem or by downloading it over HTTP works, so for now I'm using the filesystem, although this will break as soon as I switch to asset_sync in this app (I'll probably have to download the assets instead).

I was thinking it would be a nice feature to be able to choose the order of strategies, or perhaps register your own?

Thanks for the gem. It's cool.

JCF.

uninitialized constant Mail

I'm getting an 'uninitialized constant Mail' when trying to use premailer.

I think the Mail.register_interceptor call needs to be changed to the following:

ActionMailer::Base.register_interceptor

Version 1.2.0 breaks my mailers

With 1.2.0 on development, as well as on Heroku, I get this output when attempting to send an email via Delayed Job:

No such file or directory - /assets/
/usr/local/lib/ruby/1.9.1/open-uri.rb:35:in `initialize'
/usr/local/lib/ruby/1.9.1/open-uri.rb:35:in `open'
/usr/local/lib/ruby/1.9.1/open-uri.rb:35:in `open'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/css_helper.rb:70:in `request_and_unzip'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/css_helper.rb:45:in `load_css_at_path'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/css_helper.rb:15:in `css_for_doc'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/premailer.rb:14:in `initialize'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/hook.rb:18:in `new'
/app/vendor/bundle/ruby/1.9.1/gems/premailer-rails3-1.2.0/lib/premailer-rails3/hook.rb:18:in `delivering_email'
/app/vendor/bundle/ruby/1.9.1/gems/mail-2.4.4/lib/mail/mail.rb:230:in `block in inform_interceptors'
/app/vendor/bundle/ruby/1.9.1/gems/mail-2.4.4/lib/mail/mail.rb:229:in `each'
/app/vendor/bundle/ruby/1.9.1/gems/mail-2.4.4/lib/mail/mail.rb:229:in `inform_interceptors'
/app/vendor/bundle/ruby/1.9.1/gems/mail-2.4.4/lib/mail/message.rb:217:in `inform_interceptors'
/app/vendor/bundle/ruby/1.9.1/gems/mail-2.4.4/lib/mail/message.rb:227:in `deliver'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/performable_mailer.rb:6:in `perform'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/backend/base.rb:94:in `block in invoke_job'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:60:in `call'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:60:in `block in initialize'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:65:in `call'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:65:in `execute'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:38:in `run_callbacks'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/backend/base.rb:91:in `invoke_job'
(eval):3:in `block in invoke_job_with_newrelic_transaction_trace'
/app/vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.4.0/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:257:in `block in perform_action_with_newrelic_trace'
/app/vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.4.0/lib/new_relic/agent/method_tracer.rb:242:in `trace_execution_scoped'
/app/vendor/bundle/ruby/1.9.1/gems/newrelic_rpm-3.4.0/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:252:in `perform_action_with_newrelic_trace'
(eval):2:in `invoke_job_with_newrelic_transaction_trace'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:182:in `block (2 levels) in run'
/usr/local/lib/ruby/1.9.1/timeout.rb:58:in `timeout'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:182:in `block in run'
/usr/local/lib/ruby/1.9.1/benchmark.rb:310:in `realtime'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:181:in `run'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:238:in `block in reserve_and_run_one_job'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:60:in `call'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:60:in `block in initialize'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:65:in `call'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:65:in `execute'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/lifecycle.rb:38:in `run_callbacks'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:238:in `reserve_and_run_one_job'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:166:in `block in work_off'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:165:in `times'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:165:in `work_off'
/app/vendor/bundle/ruby/1.9.1/gems/delayed_job-3.0.3/lib/delayed/worker.rb:133:in `block (4 levels)`

Reverting to 1.1.0 fixes it, but still has the "No such file or directory - /assets/" as a warning.

default rails stylesheet tag will not be detected

By default in rails 4 (I haven't experimented with rails 3), stylesheet_link_tag will not generate the type attributes. One must specify it like so:

stylesheet_link_tag "email", type: "text/css"

premailer-rails uses the type attribute to find stylesheet tags, so by default they will not be found. One solution is to instead use the rel="stylesheet" attribute to find the tags. If for some reason this is not comprehensive, then the need for type: "text/css" should be specified in the readme.

I could put together a fix, but first let me know what you think.

rails dependency not required

Howdy -- thanks for a great gem!

I'm using ActionMailer in a non-rails project, and I figured using premailer-rails3 would require some monkeypatching. The good news is, it didn't require this at all, it just works as-is.

However the gem lists rails as a dependency. I commented this out in a local fork and everything runs just fine. The spec suite even runs. I suppose you might want to list actionmailer as a dependency, but even there, the user would already be using it in their app.

So, you can remove the rails dependency, and also proudly advertise your plugin as supporting actionmailer in any environment.

(and maybe even change the name to premailer-actionmailer3 :-D )

cheers,
john

CSS rendered differently in production and development mode

When I send emails in development mode, the css is rendered perfectly in gmail.But, when I send the same email in production mode, the CSS gets broken in couple of places. I even tried rake:assets:precompile before sending the email. Stylesheet has been included in the HEAD section of mailer as <%= stylesheet_link_tag 'email/my_css' %> Is it a problem with a premailer or something that is to be configuerd for production mode. Am I missing something ?

Undefined method "force_encoding" in css_helper

UPDATE: Apparently I forgot to precompile this asset which explains why css helper couldn't find it. A more descriptive error when not found or an empty string returned could be a nice improvement. i can write a PR for this if you like the idea


I'm getting an error within premailer-rails when trying to send emails in my staging environment. It's working fine in dev.

My staging env is an Ubuntu server. Looks like the issue is that load_css is returning an array. It appears that the css is never found which would cause the block in load_css to return an array.

We're using cloudfront as an asset host, and I'm guessing that's the source of the problem.

Any ideas? I'm digging into this myself, too, but wanted to see if there were any quick fixes before I do a deep dive.

Stack trace:

premailer/rails/css_helper.rb:19:in `block in css_for_doc'
  urls.map { |url| load_css(url).force_encoding('UTF-8') }.join("\n")
premailer/rails/css_helper.rb:19:in `map'
  urls.map { |url| load_css(url).force_encoding('UTF-8') }.join("\n")
premailer/rails/css_helper.rb:19:in `css_for_doc'
  urls.map { |url| load_css(url).force_encoding('UTF-8') }.join("\n")
premailer/rails/customized_premailer.rb:15:in `initialize'
  options = @options.merge(css_string: CSSHelper.css_for_doc(doc))
premailer/rails/hook.rb:80:in `new'
  @premailer ||= CustomizedPremailer.new(html_part.decoded)
premailer/rails/hook.rb:80:in `premailer'
  @premailer ||= CustomizedPremailer.new(html_part.decoded)
premailer/rails/hook.rb:76:in `generate_text_part'
  body: premailer.to_plain_text)
premailer/rails/hook.rb:57:in `generate_alternative_part'
  part.add_part(generate_text_part)
.........

find_asset fails in unknown circumstance in rails 4

I'm encountering this problem on production:

  1. this call to find_asset will sometimes return nill.
  2. An attempt is then made to fetch the asset here.
  3. ::Rails.configuration.assets.digests is nil (always in rails 4?). So this blows up.

A quick test at the console on production shows that find_asset does succeed for "application.css" --- so next step for me is to figure out which asset is not being found.

possibly related to #84

Use without Rails docs

The Readme states that this gem can be used without Rails. Is there documentation anywhere on how to do this? I've looked through the code a bit, but don't see an obvious way to just pass HTML+CSS to premailer-rails and have it inline the styles, since the functionality seems to be wrapped up in ActionMailer hooks.

Documentation and default :input_encoding option is inconsistent with Premailer 1.7.3 (latest release) gem

A note here because I ran into this problem, and it was a real pain to track down, and it seems no new version of the premailer gem has been published for a long while:

Note that the latest gem of premailer (as opposed to the github version) uses :inputencoding as the option name. It also badly botches the encoding for anyone that doesn't happen to use an input encoding and default encoding that can safely roundtrip with ASCII-8BIT, as it does force_encoding('ASCII-8BIT').encode! on the input. Notably this fails horribly if you pass UTF-8 data in and have default_encoding UTF-8.

This illustrates the conversion Premailer 1.7.3 does:

1.9.1 :086 > "รฆรธรฅ".force_encoding('ASCII-8BIT')
 => "\xC3\xA6\xC3\xB8\xC3\xA5"  # correctly UTF-8 encoded
1.9.1 :087 > "รฆรธรฅ".force_encoding('ASCII-8BIT').encode!
 => "??????"  # The botched conversion Premailer 1.7.x does
1.9.1 :089 > "รฆรธรฅ".force_encoding('ASCII-8BIT').encode!.force_encoding('BINARY')
 => "\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD"   # ... as binary.

That was fixed in this commit: alexdunae/premailer@5f5cbb4

However that means your documentation is wrong for anyone depending on the 1.7.3 gem (the :input_encoding option doesn't exist in 1.7.3) which at the time of writing is the latest released one, and the default UTF-8 encoding specified by premailer-rails3 will not be respected by the premailer gem.

For anyone with these encoding problems, the immediate solution is to use the premailer git repo, where the fix is merged in. It might be worth making a note of that in the premailer-rails3 documentation. Alternatively, setting :inputencoding to the content of :input_encoding might help somewhat, at least for Ruby 1.8 users. On 1.9.x the only workaround with premailer 1.7.3 or below appears to be to make sure you do this or similar :

Encoding.default_internal = 'ASCII-8BIT'

(but you may want to do that just immediately around the call to premailer, unless you want a whole lot of other stuff to break horribly if your application expects to deal with UTF-8)

Overall the best alternative appears to currently be the git version.

disable plain text generation

can i disable the plain text generation somehow? I have a mail that has both parts already and only want to fix the html part of th email.

Premailer inserts responsive @media CSS inline for all clients / browsers to receive

Using the snippet below as an example, Premailer grabs the CSS and inserts it inline which affects desktop clients.

<style> @media only screen and (max-width: 480px) { .preheader { display: none !important; } ``` #bodyCell { width: 100% !important; } #templateContainer { width: 100% !important; } } ``` </style>

Premailer should ignore the @media settings and leave it in the for supported mobile browsers to read.

Hook duplicates HTML part

When the message already has an HTML part, the PremailerRails::Hook class passes a block to the message#html_part method defining a new HTML part. This method adds the new HTML part to the message, resulting in duplicate HTML parts.

I believe this:

message.html_part do
  content_type "text/html; charset=#{charset}"
  body premailer.to_inline_css
end

Should be replaced with this:

message.html_part do
  content_type "text/html; charset=#{charset}"
  body premailer.to_inline_css
end unless message.html_part

Monkeypatching load_html() causes problems

Hi there - I ran into some problems when using style tags with data-premailer-ignore set, where Nokogiri would insert CDATA tags. Premailer fix this (premailer/premailer@c039588), but Premailer-Rails undoes their fix with its load_html monkeypatch (https://github.com/fphilipe/premailer-rails/blob/master/lib/premailer/rails/nokogiri_fix.rb).

Is that monkeypatch still necessary? I commented it out & couldn't see any encoding problems, wasn't quite sure what it was trying to work around, though.

Feature request: Opt-in or opt-out of premailer hook per mailer

Since the mail gem only supports adding interceptors globally, it would be nice if there were a way to selectively turn off or turn on premailer depending on the mailer being used. In the application where I'm using premailer, we have one mailer which needs the premailer functionality, but every other mailer template needs to include an empty style tag (as described in #46) to avoid raising an exception when sending mail. To get around this, I've monkeypatched the PremailerRails::Hook class like this:

  PremailerRails::Hook.class_eval do
    def self.delivering_email_with_opt_in(message)
      return unless message.class.respond_to?(:use_premailer?) && message.class.use_premailer?

      delivering_email_without_opt_in(message)
    end

    singleton_class.alias_method_chain :delivering_email, :opt_in
  end

and then added used it like this:

class FancyMailer < ActionMailer
  # other stuff

  def self.use_premailer? ; true ; end
end

I'd be happy to work on a solution for this if you think it'd be a worthy addition to the project.

Collaboration?

Hi,

I've written an actionmailer_inline_css gem that does almost the same thing as premailer-rails3.

Differences:

  • Instead of email.css, use the Mailer name for default css files
  • Uses manually written text part if exists, and falls back to generating them from the html part
  • Handles UTF-8 characters properly and sends the html part with base64 encoding
  • I think premailer-rails3 tries a little too hard to figure out where CSS files are stored. I prefer just passing in the full file-path, but would be great if both ways could be supported.

Please feel free to have a look at the actionmailer_inline_css code when you have time, and let me know if we could work together on this. I'm very happy to close my project and merge some of those things into premailer-rails3.

Cheers

How I'm suppose to include external stylesheets to the email template?

Hi, I'm using premailer-rails 1.7.0 and I'm trying to place an external stylesheet into the email template, see it here.

When I run the tests I get an URI::InvalidURIError exception saying bad URI(is not URI?): https://fonts.googleapis.com/css?family=Montserrat:700|Lato:300,400,400italic,700

I looked into the premailer documentation and I found the external_style variable, but I'm looking for the right way to do it using premailer-rails.

Doesn't inline styles when calling `Notifier.email.deliver` from the console

One way I like to test emails is by delivering them from the console. Notifier.welcome_message(user).deliver.

I tried this by sending myself an email from my app from the console, but it doesn't appear that the premailer interceptor is called, because the email didn't have any inlined styles.

It's possible that interceptors aren't called at all when sending an email from the console, in which case, feel free to close directly. I dug around in the Rails core, but couldn't find anything about that.

If this is the case, and interceptors truly don't get called when sending email from the console, how would you recommend testing the emails that premailer generates on different email clients?

CSS helper fails with precompiled assets

If the application is running with precompiled assets (on heroku, by default, for example), and if config.assets.compile = false, then the css helper fails to load the given css.

How to reproduce

Run rake assets:precompile, and launch a console in a mode where config.assets.compile = false.

# The following can't be trusted
# On one of my files, I get an empty file
# On the other, it just fails because some required gems are only loaded in :asset mode
> Rails.application.assets.find_asset('application.css')
# throws an error, because some dependencies aren't there

# But the following works :
> helper.asset_path
"/assets/application-7e665a53800e4707726f7e685d167973.css"

The stylesheet_link_tag generated is with the public address (/assets/application-7e..73.css)
In css_helper.rb, we get path='application-7e..73.css' on line 36 (fine).

But then it stops working. The asset object is retrieved (some Sprockets::BundledAsset), but its body is empty ...
I guess the best chance here to read it is to directly read from this file ... but I haven't found an easy way to get its full path ...

Attachments not working

Attachments are interpreted as an 'alternative' to text/html and text/plain. To be more precise, this is as it is now:

Subject: [SUBJECT]
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_4f3f93ff19851_232b80434f4c466bf";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
X-Gm-Message-State: ALoCoQklBXxw350+ohWjgoEN7hwcLka6gnFP91+s2pgrQnmO68zsfOk2FytAG8lKURw+ZnSEGv09

----==_mimepart_4f3f93ff19851_232b80434f4c466bf
Date: Sat, 18 Feb 2012 13:05:19 +0100
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <[email protected]>

[HTML]

----==_mimepart_4f3f93ff19851_232b80434f4c466bf
Date: Sat, 18 Feb 2012 13:05:19 +0100
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <[email protected]>

[PLAIN_TEXT]

----==_mimepart_4f3f93ff19851_232b80434f4c466bf
Date: Sat, 18 Feb 2012 13:05:19 +0100
Mime-Version: 1.0
Content-Type: application/pdf;
 charset=UTF-8;
 filename="iubenda - invoice 2012-2 - boh-it.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="iubenda - invoice 2012-2 - boh-it.pdf"
Content-ID: <[email protected]>

[ATTACHMENT]

----==_mimepart_4f3f93ff19851_232b80434f4c466bf--


This is as it should be (the following *works)

Subject: [SUBJECT]
Mime-Version: 1.0
Content-Type: multipart/mixed;
 boundary="--==_mimepart_4f3f9a55ce2e8_27a480434f4c45522";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
X-Gm-Message-State: ALoCoQlheI2MEADdbZu+TmYeXlhJkmL8Nrxlcv6jUPhvXCXAQT2dlOIfsMx3vKnR5I/786l1g9X5



----==_mimepart_4f3f9a55ce2e8_27a480434f4c45522
Date: Sat, 18 Feb 2012 13:32:21 +0100
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_4f3f9a55c2d41_27a480434f4c454e3";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <[email protected]>



----==_mimepart_4f3f9a55c2d41_27a480434f4c454e3
Date: Sat, 18 Feb 2012 13:32:21 +0100
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <[email protected]>

[HTML]

----==_mimepart_4f3f9a55c2d41_27a480434f4c454e3
Date: Sat, 18 Feb 2012 13:32:21 +0100
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Content-ID: <[email protected]>

[PLAIN_TEXT]

----==_mimepart_4f3f9a55c2d41_27a480434f4c454e3--


----==_mimepart_4f3f9a55ce2e8_27a480434f4c45522
Date: Sat, 18 Feb 2012 13:32:21 +0100
Mime-Version: 1.0
Content-Type: application/pdf;
 charset=UTF-8;
 filename="iubenda - invoice 2012-2 - boh-it.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="iubenda - invoice 2012-2 - boh-it.pdf"
Content-ID: <[email protected]>

[ATTACHMENT]

----==_mimepart_4f3f9a55ce2e8_27a480434f4c45522--

I know that it's more likely to be a premailer's bug, but I'm reporting it here first since alexdunae doesn't seem to be that active.

Thank you in advance.

Load error in production

I get the following error in production:
undefined method 'config' for Premailer::Rails:Module (NoMethodError)

I have the following code in a initializer:
Premailer::Rails.config.merge!(:remove_ids => true, :remove_classes => true)

Which is what is causing the error.

Premailer Load error in production

Hi there!

I fell a bit lost on this.

rails-premailer seems not to be loaded on rails startup in production mode, causing configuration loading error and app to refuse to start.

Here is my initializer:

Premailer::Rails.config.merge!(
  :preserve_styles => false,
  :remove_ids      => false,
  :input_encoding  => 'UTF-8')

Here is the output when starting rails :

current/config/initializers/04_premailer.rb:1:in `<top (required)>': uninitialized constant Premailer (NameError)

Gemfile:

...
gem "nokogiri"
gem "hpricot"

gem 'premailer'
gem 'premailer-rails'
...

Any pointer?

Problem parsing mail with newline followed by an URL

Using premailer 1.3.2 with Rails 3.2.13.

We are using premailer to send mail to users that may contain content that is user generated. I found that we get the error below if someone enters some text that has some text followed by a carriage return followed by an URL like:

You can duplicate if your email template has something like the following:
<%= "some text\nhttps://somewhere.com" %>

Yes, I can parse out the newline but I don't thing premailer show blow up :-)

Here is the error:

#<URI::InvalidURIError: bad URI(is not URI?):
<content of mail shown here>
/usr/local/rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/uri/common.rb:176:in `split'
    /usr/local/rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/uri/common.rb:211:in `parse'
    /usr/local/rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/uri/common.rb:747:in `parse'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-1.7.3/lib/premailer/premailer.rb:405:in `resolve_link'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-1.7.3/lib/premailer/premailer.rb:244:in `block in load_css_from_html!'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/nokogiri-1.5.6/lib/nokogiri/xml/node_set.rb:239:in `block in each'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/nokogiri-1.5.6/lib/nokogiri/xml/node_set.rb:238:in `upto'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/nokogiri-1.5.6/lib/nokogiri/xml/node_set.rb:238:in `each'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-1.7.3/lib/premailer/premailer.rb:233:in `load_css_from_html!'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-1.7.3/lib/premailer/premailer.rb:190:in `initialize'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-rails-1.3.2/lib/premailer/rails/customized_premailer.rb:16:in `initialize'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-rails-1.3.2/lib/premailer/rails/hook.rb:19:in `new'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/premailer-rails-1.3.2/lib/premailer/rails/hook.rb:19:in `delivering_email'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/mail-2.5.3/lib/mail/mail.rb:230:in `block in inform_interceptors'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/mail-2.5.3/lib/mail/mail.rb:229:in `each'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/mail-2.5.3/lib/mail/mail.rb:229:in `inform_interceptors'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/mail-2.5.3/lib/mail/message.rb:217:in `inform_interceptors'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/mail-2.5.3/lib/mail/message.rb:227:in `deliver'
    /home/xxx/svnroot/app/timesheet2/lib/tasks/mailer.rake:38:in `block (4 levels) in <top (required)>'
    /home/xxx/svnroot/app/timesheet2/lib/tasks/mailer.rake:28:in `each'
    /home/xxx/svnroot/app/timesheet2/lib/tasks/mailer.rake:28:in `block (3 levels) in <top (required)>'
    /home/xxx/svnroot/app/timesheet2/lib/tasks/mailer.rake:24:in `each'
    /home/xxx/svnroot/app/timesheet2/lib/tasks/mailer.rake:24:in `block (2 levels) in <top (required)>'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:246:in `call'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:246:in `block in execute'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:241:in `each'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:241:in `execute'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:184:in `block in invoke_with_call_chain'
    /usr/local/rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:177:in `invoke_with_call_chain'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/task.rb:170:in `invoke'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:143:in `invoke_task'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:101:in `block (2 levels) in top_level'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:101:in `each'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:101:in `block in top_level'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:110:in `run_with_threads'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:95:in `top_level'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:73:in `block in run'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:160:in `standard_exception_handling'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/lib/rake/application.rb:70:in `run'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/gems/rake-10.0.4/bin/rake:33:in `<top (required)>'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/bin/rake:19:in `load'
    /usr/local/rvm/gems/ruby-1.9.3-p327@xxx/bin/rake:19:in `<top (required)>'
    -e:1:in `load'
    -e:1:in `<main>'

Ability to skip premailer

99% of the time in our app we want to use premailer, however we've come across one case where we don't. Would you be open to a patch that allowed you to skip premailer for certain messages?

I'd propose setting a header on the message like 'X-Premailer-Skip'. If that header is set, then remove the header and don't modify the content.

Are you open to this change? If so,

  1. I'd be happy to contribute a pull request for it
  2. Do you like the header idea or can you think of a better solution?

Asset Pipeline and Image URLs

Is it possible to have image_url and image_tag helpers in the CSS generate the full absolute URLs? I'm currently getting relative /assets/ URLs using premailer-rails3 1.0.1 and Rails 3.1.3.

Exception when no email.css is available

It took me quite a bit of time to figure out why my email sending was failing - it all boils down to this:

If no CSS file is linked to in the HTML it will try to load a default CSS file email.css.

I was using a template with built-in css and no link to outside css and this was failing.

Suggestions:

  • add an option to bypass that?
  • raise a clear exception message?

In the mean time I'm going to add an empty email.css and see if it works.

Just raw thoughts! Thanks for your work on the gem!

=3D

premailer-rails is changing all "=" to "=3d". Any ideas what could cause this? I'm using nokogiri, rails 3.2.11. I had the same problem with other versions of rails.

Remove read stylesheets from HTML

At the moment premailer-rails resolves the external stylesheets and puts their contents into a :css_string option for premailer to process. Then premailer itself does similar processing again to load external stylesheets.

Premailer-rails should remove the link elements or replace them with the inlined css so that premailer does not process them.

This a especially a problem when specifying an action_mailer.asset_host which results in premailer loading the css asset via HTTP because of this premailer issue: https://github.com/alexdunae/premailer/pull/131

couldn't find asset application.x.css for premailer-rails3

not sure if my issue is related to the others posted already here, i only get this issue when my app is now hosted in heroku.

I don't have this issue when i try to run locally - can anyone give me a suggestion or a workaround on this?

Heroku timeouts

Hi guys,
I'm having an issue with this gem causing timeouts on Heroku - is there something I'm missing for when deploying this on Heroku other than adding the gem?

2012-04-16T03:31:34+00:00 app[web.1]: Started POST "/users/password.json" for 203.189.83.189 at 2012-04-16 03:31:34 +0000
2012-04-16T03:32:04+00:00 heroku[router]: Error H12 (Request timeout) -> POST foo.com/users/password.json dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-04-16T03:32:05+00:00 heroku[router]: Error H12 (Request timeout) -> GET foo.com/assets/ dyno=web.1 queue= wait= service=30000ms status=503 bytes=0

The mail sends through fine - it's just the request timeout error causing me issues.

In my gemfile I have:
gem 'premailer-rails3'
gem "nokogiri"

Cheers!
Thomas

Ignoring CSS declared in the <head>

It would be great to be able to ignore css declared in the head, or a defined css file. This would be very helpful for setting optional CSS (e.g., for mobile devices).

why my css don't write to the view?

view:
<%=stylesheet_link_tag 'test' %>

Hello!

assets/stylesheets/test.css:

nav {float: left;font-size: 13px; font-weight: 100; padding: 0 0 0 15px;}

undefined method '[]' for nil:NilClass when running specs

After adding the premailer-rails3 gem, I'm seeing undefined method '[]' for nil:NilClass errors for every spec that triggers an email. So for instance, creating a object using FactoryGirl that sends an email I see the error, though for some reason the specs still pass. I'm assuming this has something to do with how the premailer intercepts mail objects before they are delivered.

Oddly enough, when running Specs fo the Mailer classes themselves I don't see this error.

running rails 3.2.2 with ruby 1.9.3

Beware asset_host that begin with "//" and not "http:// or https://"

This is just an FYI that if your asset_host is defined without the "http:" part, then premailer will fail to load the css file in CSSLoaders::request_and_unzip.

We define our asset_host w/o the http part so that we don't have to deal with http/https warnings. We fixed this issue like so in our env config files:

# Enable serving of images, stylesheets, and JavaScripts from an asset server
config.action_controller.asset_host = "//#{ENV['CLOUDFRONT_URL']}"

# set action_mailer asset_host for assets in emails
config.action_mailer.asset_host = "http:" + config.action_controller.asset_host

query for if asset pipeline is enabled is ineffective in Rails 4

The problem is here: https://github.com/fphilipe/premailer-rails/blob/master/lib/premailer/rails/css_loaders.rb#L31

Rails 4 (which I am using) no longer has the enabled flag/method. By default the asset pipeline is on.

You could perhaps check this instead: ::Rails.configuration.assets.compile

I haven't thought through if that will be the relevant thing to check in various cases.

I could put together a fix, but first let me know what you think.

Text portion is the default

Have a quick look at this: basecamp/mail_view#61

From the Rails docs, it appears that the order of parts can be controlled, and premailer-rails is putting the text portion first. I had a quick look at the code and couldn't immediately find the point at which it's inserted, but I didn't give it much time.

I figured you'd be better to answer this question. mail_view is choosing the first format it comes across and it my head makes sense that the HTML portion come first, as that's what I'd prefer my users to see.

BTW, I love this gem. It's in ALL of my projects.

I can take a look or you can just point me in the right direction and I can patch it if you'd prefer. Let me know.

Not rendering correctly, source attached

I was super excited to see the pre mailer-rails3 gem, and it is able to get the email mostly right, but not quite exactly. Using rails 3.2.3, ruby 1.9.3-p194, hpricot 0.8.6, and premailer-rails HEAD

Mail received

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="chrome=1,IE=9" />

    <meta charset="utf-8">
    <link href="http://cloudfront.giantuser.com/assets/application-fdb826aa1314de46086c7d455b772800.css" media="all" rel="stylesheet" type="text/css" />        
</head>

<body class='email'>

---------- Write your reply above this line ----------

<p class="spaced">
    <a href="http://giantuser.com/signatures/matt-coneybeare">Matt Coneybeare's Signature</a> has a new comment:
</p>

<div id='signature'>
    <div class='well'>
        <div class="comment">
            <div class="row-fluid">
    <div class="span1">
        <img alt="E026ee8c3c194bcf567dae6de25c3c90" class="thumbnail" src="http://gravatar.com/avatar/e026ee8c3c194bcf567dae6de25c3c90.png?s=48" />
    </div>
    <div class="span11">
        <span class="name">Matt Coneybeare</span>
        <span class="timestamp">May 9th, 2012 21:23</span>
        <p><p>This is another message using the pre mailer system.</p>

<p>Bacon ipsum dolor sit amet shoulder magna in, prosciutto excepteur nostrud fugiat tenderloin officia turkey. Pastrami bacon excepteur voluptate, ground round aute shank spare ribs occaecat cupidatat. Pork belly in frankfurter, cupidatat adipisicing tempor kielbasa fatback officia elit ham hock nulla veniam. Meatball pastrami ham hock strip steak, jerky ut duis laboris t-bone chicken sed exercitation.</p></p>
    </div>
</div>
                <div class="row-fluid">
        <div class="span1">&nbsp;</div>
        <div class="span11">
                <ul class="thumbnails">
                      <li class="span2">
                            <div class="thumbnail">
                                <a href="http://cloudfront.giantuser.com/data/images/ced084ac2179221a56f5915d4f0136b1/original.PNG?1336598622" class="thumb"><img alt="Small" src="http://cloudfront.giantuser.com/data/images/ced084ac2179221a56f5915d4f0136b1/small.PNG?1336598622" /></a>
                                <h6>aa</h6>
                            </div>
                      </li>
                </ul>
                    <a href="http://cloudfront.giantuser.com/data/attachments/f152874d8462459a15b4d6ad156094b2/MacUpdate_POST_Instructions_for_Thumbs.txt?1336598622" class="btn btn-small">Download txt</a>
        </div>
    </div>

        </div>
    </div>
</div>

</body>
</html>

Ihave the same code hooked up to a view controller and when rendered, it is supposed to look like this:

Mail received

Heroku running on one dyno times out when requesting CSS

Hi,

I've been using premailer-rails for my application in Heroku, and although it works fine in production where I have multiple dynos running, the application crashes on staging everytime I try to send an email, since it times out while waiting for the CSS file:

heroku[router]: at=error code=H12 desc="Request timeout" method=GET     path=/assets/email-299a00b67d82176278762ea55ec15b4c.css host=yg-shop-staging.herokuapp.com request_id=7b11b40f-2ca9-4de7-833e-1f19ca73bd5d fwd="54.221.164.141" dyno=web.1 connect=3ms service=30002ms status=503 bytes=0

I imagine this is happening because premailer is requesting the css while trying to send the email, and without any dyno to serve that request, the timeout occurs.

Is there a way around the issue? Could I preload the css somehow for my email?

Here are my premailer versions

premailer (1.7.9)
css_parser (>= 1.1.9)
htmlentities (>= 4.0.0)
premailer-rails (1.6.1)
actionmailer (>= 3, < 5)
premailer (~> 1.7, >= 1.7.9)

Thanks

Selective CSS inlining

Is there a way to select parts of CSS that will or will not be inlined? That is needed when we need to do styling for some specific email clients (like media queries for some advanced mobile devises). Is there a way to do it?

Best Regards,
Pekka

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.