grimen-awesome_email 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 imedo GmbH
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,90 @@
1
+ h2. For the impatient
2
+
3
+ Check out the demo application:
4
+
5
+ "http://opensource.imedo.de/htmlmail":http://opensource.imedo.de/htmlmail
6
+
7
+ Install as plugin:
8
+
9
+ <pre>script/plugin install git://github.com/grimen/awesome_email.git</pre>
10
+
11
+ Install as gem:
12
+
13
+ <pre>sudo install grimen-awesome_email</pre>
14
+
15
+ Learn how to use it below.
16
+
17
+ h2. Introduction
18
+
19
+ Have you ever tried sending HTML emails to your users? If you did, you know for sure that it sucks big time: none of the usual ActionView helpers want to work, URL routing is disabled, layouts don't work, and last but not least, the CSS you wrote for your email "simply won't work in any e-mail client":http://www.sitepoint.com/blogs/2007/01/10/microsoft-breaks-html-email-rendering-in-outlook except maybe Apple Mail. To solve all of the above problems, the <code>awesome_email</code> plugin comes to the rescue. Just install it into your <code>vendor/plugins</code> folder, and the rest comes by itself.
20
+ If you are interested in what works in which Email client check this link: "A guide to css support in Email":http://www.campaignmonitor.com/css/
21
+
22
+ h2. What does it do?
23
+
24
+ There are a few interesting components in <code>awesome_email</code>:
25
+
26
+ * awesome_email adds layout support to emails. That means that you can use templates for e-mails just like you would with normal Rails Views.
27
+ * The HTML Mail's CSS is automatcally inlined. That means that your designer and/or CSS guy can design the email in a web browser without worrying about how it might look like in excotic email clients. Yes, it works in Outlook, too, and no, it "doesn't work in Outlook 2007 without tweaking":http://www.sitepoint.com/blogs/2007/01/10/microsoft-breaks-html-email-rendering-in-outlook. The reason is a "stupid decision from Microsoft about Outlook 2007", but we're working on that one.
28
+ * ConvertEntities replaces Umlauts and other crazy symbols like &auml;, &Ouml; etc. with their HTML Entitiy counterparts e.g. <code>&amp;auml;</code> and so on.
29
+ * HelperMethods allow you to dump the content of the CSS file right into a style tag inside the header of your HTML mail.
30
+
31
+ h2. How to use it
32
+
33
+ In your Mailer.delivery_xxx methods you can use
34
+
35
+ <macro:code lang="ruby">
36
+ layout "template_filename"
37
+ css "css_filename"
38
+ </macro:code>
39
+
40
+ to define which layout should be used and which css file should be used to create inline styles
41
+
42
+ h3. CSS inlining
43
+
44
+ The cummulated style of each DOM element will be set as an style attribute when using css inlining.
45
+
46
+ Example:
47
+
48
+ your css file:
49
+ <macro:code lang="css">
50
+ #some-id { font-size:2em; }
51
+ .some-class { color:red; }
52
+ </macro:code>
53
+
54
+ your template:
55
+ <macro:code lang="html">
56
+ <p id="some-id" class="some-class">Hello World!</p>
57
+ </macro:code>
58
+
59
+ will result in the following code:
60
+ <macro:code lang="html">
61
+ <p id="some-id" class="some-class" style="color:red; font-size:2em;">Hello World!</p>
62
+ </macro:code>
63
+
64
+ h2. Important!
65
+
66
+ Be sure to follow these simple conventions or otherwise awesome_emails's magic will fail:
67
+
68
+ * The layout must be located inside <code>app/views/layouts/{mailer_name}</code>
69
+ * If you send mutlipart mails, check out the conventions on how to name your files: "http://rails.rubyonrails.com/classes/ActionMailer/Base.html":http://rails.rubyonrails.com/classes/ActionMailer/Base.html
70
+ ** So if you have these files inside of /app/views/{mailer_name}: *signup_notification.text.plain.erb*, *signup_notification.text.html.erb* ActionMailer will send a multipart mail with two parts: *text/plain* and *text/html*
71
+ * Your CSS file must be inside of <code>/public/stylesheets</code>
72
+
73
+ h2. Dependencies
74
+
75
+ Gems:
76
+
77
+ * "rails 2.0.1+":http://github.com/rails/rails
78
+ * "nokogiri 1.3.3+":http://github.com/tenderlove/nokogiri
79
+ * "csspool 2.0.0+":http://github.com/tenderlove/csspool
80
+
81
+ h2. Getting it, License and Patches
82
+
83
+ Get the original source code through "http://github.com/imedo/awesome_email":http://github.com/imedo/awesome_email. License is MIT. That means that you can do whatever you want with the software, as long as the copyright statement stays intact. Please be a kind open source citizen, and give back your patches and extensions. Just fork the code on Github, and after you're done, send us a pull request. Thanks for your help!
84
+
85
+ h2. ToDo
86
+
87
+ * More test coverage (as usual) - especially testing multiple rules (!)
88
+ * Make it more flexible with view paths
89
+
90
+ Copyright (c) 2008 imedo GmbH, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ NAME = "awesome_email"
6
+ SUMMARY = %Q{Rails ActionMailer with HTML layouts, inline CSS and entity substitution.}
7
+ HOMEPAGE = "http://github.com/grimen/#{NAME}/tree/master"
8
+ AUTHORS = ["imedo GmbH"]
9
+ EMAIL = "entwickler@imedo.de"
10
+
11
+ require 'rubygems'
12
+ gem 'technicalpickles-jeweler', '1.2.1'
13
+
14
+ begin
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = NAME
18
+ gem.summary = SUMMARY
19
+ gem.description = SUMMARY
20
+ gem.homepage = HOMEPAGE
21
+ gem.authors = AUTHORS
22
+ gem.email = EMAIL
23
+
24
+ gem.require_paths = %w{lib}
25
+ gem.files = %w(MIT-LICENSE README.textile Rakefile) + Dir.glob(File.join('{lib,rails,test}', '**', '*'))
26
+ gem.executables = %w()
27
+ gem.extra_rdoc_files = %w{README.textile}
28
+ end
29
+ rescue LoadError
30
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
31
+ end
32
+
33
+ desc %Q{Run unit tests for "#{NAME}".}
34
+ task :default => :test
35
+
36
+ desc %Q{Run unit tests for "#{NAME}".}
37
+ Rake::TestTask.new(:test) do |test|
38
+ test.libs << ['lib', 'test']
39
+ test.pattern = File.join('test', '**', '*_test.rb')
40
+ test.verbose = true
41
+ end
42
+
43
+ desc %Q{Generate documentation for "#{NAME}".}
44
+ Rake::RDocTask.new(:rdoc) do |rdoc|
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = NAME
47
+ rdoc.options << '--line-numbers' << '--inline-source' << '--charset=UTF-8'
48
+ rdoc.rdoc_files.include('README.textile')
49
+ rdoc.rdoc_files.include(File.join('lib', '**', '*.rb'))
50
+ end
@@ -0,0 +1,55 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ module ActionMailer
5
+ module ConvertEntities
6
+
7
+ # Add more if replacements you need
8
+ UMLAUTS = {
9
+ 'ä' => '&auml;',
10
+ 'ö' => '&ouml;',
11
+ 'ü' => '&uuml;',
12
+ 'Ä' => '&Auml;',
13
+ 'Ö' => '&Ouml;',
14
+ 'Ü' => '&Uuml;',
15
+ 'ß' => '&szlig;'
16
+ }.freeze
17
+
18
+ module ClassMethods
19
+ # none
20
+ end
21
+
22
+ module InstanceMethods
23
+
24
+ # Replace all umlauts
25
+ # Add more if replacements you need them
26
+ def convert_to_entities(text)
27
+ text.gsub(/[#{UMLAUTS.keys.join}]/u) { |match| UMLAUTS[match] }
28
+ end
29
+
30
+ # Convert entities only when rendering html
31
+ def render_message_with_converted_entities(method_name, body)
32
+ message = render_message_without_converted_entities(method_name, body)
33
+ html_part?(method_name) ? convert_to_entities(message) : message
34
+ end
35
+
36
+ # Check if the part we are rendering is html
37
+ def html_part?(method_name)
38
+ method_name.to_s.gsub('.', '/') =~ /#{Mime::EXTENSION_LOOKUP['html']}/
39
+ end
40
+
41
+ end
42
+
43
+ def self.included(receiver)
44
+ receiver.class_eval do
45
+ extend ClassMethods
46
+ include InstanceMethods
47
+
48
+ alias_method_chain :render_message, :converted_entities
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ ActionMailer::Base.send :include, ActionMailer::ConvertEntities
@@ -0,0 +1,49 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ module AwesomeEmail
5
+ module Helpers
6
+
7
+ # helper methods for ActionView::Base
8
+ module Views
9
+
10
+ # prints the contents of a file to the page
11
+ # default file_name is 'html-mail.css'
12
+ def render_css_file(file_name = 'html-mail.css')
13
+ file_name = "#{file_name}.css" unless file_name.end_with?('.css')
14
+ relative_path = File.join('public', 'stylesheets', 'mails', file_name)
15
+ files = Dir.glob(File.join(RAILS_ROOT, '**', relative_path))
16
+ full_path = files.blank? ? File.join(RAILS_ROOT, relative_path) : files.first
17
+ File.read(full_path) rescue ''
18
+ end
19
+
20
+ # outputs style sheet information into the header of a webpage
21
+ # to link the stylesheet absolute, we have to pass in the server_url like: "http://localhost" or "https://localhost:3001"
22
+ def mail_header_styles(server_url, file_name)
23
+ return '' if file_name.blank?
24
+ %Q{<link rel="stylesheet" href="#{File.join(server_url, file_name)}" />\n<style type="text/css"><!-- #{render_css_file(file_name)} --></style>}
25
+ end
26
+
27
+ end
28
+
29
+ # helper methods for ActionMailer::Base
30
+ module Mailer
31
+
32
+ protected
33
+
34
+ # sets a few variables that ensure good delivery of the mail
35
+ def setup_multipart_mail
36
+ headers 'Content-transfer-encoding' => '8bit'
37
+ sent_on Time.now
38
+ content_type 'text/html'
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ ActionView::Base.class_eval do
47
+ include AwesomeEmail::Helpers::Views
48
+ include AwesomeEmail::Helpers::Mailer
49
+ end
@@ -0,0 +1,92 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ require 'rubygems'
5
+
6
+ gem 'nokogiri', '>= 1.3.3'
7
+ gem 'csspool', '>= 2.0.0'
8
+
9
+ require 'nokogiri'
10
+ require 'csspool'
11
+
12
+ module ActionMailer
13
+ module InlineStyles
14
+
15
+ STYLE_ATTR = (RUBY_VERSION >= '1.9') ? :style : 'style'
16
+
17
+ module ClassMethods
18
+ # none
19
+ end
20
+
21
+ module InstanceMethods
22
+
23
+ def inline(html)
24
+ css_doc = parse_css_doc(build_css_file_name_from_css_setting)
25
+ html_doc = parse_html_doc(html)
26
+ render_inline(css_doc, html_doc)
27
+ end
28
+
29
+ def render_message_with_inline_styles(method_name, body)
30
+ message = render_message_without_inline_styles(method_name, body)
31
+ return message if @css.blank?
32
+ inline(message)
33
+ end
34
+
35
+ protected
36
+
37
+ def render_inline(css_doc, html_doc)
38
+ css_doc.rule_sets.each do |rule_set|
39
+ inline_css = css_for_rule(rule_set)
40
+
41
+ html_doc.css(rule_set.selectors.first.to_s).each do |element|
42
+ element[STYLE_ATTR] = [inline_css, element[STYLE_ATTR]].compact.join('').strip
43
+ element[STYLE_ATTR] << ';' unless element[STYLE_ATTR] =~ /;$/
44
+ end
45
+ end
46
+ html_doc.to_html
47
+ end
48
+
49
+ def css_for_rule(rule_set)
50
+ rule_set.declarations.map do |declaration|
51
+ declaration.to_s.strip
52
+ end.join
53
+ end
54
+
55
+ def parse_html_doc(html)
56
+ html_doc = Nokogiri::HTML.parse(html)
57
+ end
58
+
59
+ def parse_css_doc(file_name)
60
+ css_doc = CSSPool.CSS(parse_css_from_file(file_name))
61
+ end
62
+
63
+ def parse_css_from_file(file_name)
64
+ files = Dir.glob(File.join(RAILS_ROOT, '**', file_name))
65
+ files.blank? ? '' : File.read(files.first)
66
+ end
67
+
68
+ def build_css_file_name_from_css_setting
69
+ @css.blank? ? '' : build_css_file_name(@css)
70
+ end
71
+
72
+ def build_css_file_name(css_name)
73
+ file_name = "#{css_name}.css"
74
+ Dir.glob(File.join(RAILS_ROOT, '**', file_name)).first || File.join(RAILS_ROOT, 'public', 'stylesheets', 'mails', file_name)
75
+ end
76
+
77
+ end
78
+
79
+ def self.included(receiver)
80
+ receiver.class_eval do
81
+ extend ClassMethods
82
+ include InstanceMethods
83
+
84
+ adv_attr_accessor :css
85
+ alias_method_chain :render_message, :inline_styles
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+
92
+ ActionMailer::Base.send :include, ActionMailer::InlineStyles
@@ -0,0 +1,81 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ module ActionMailer
5
+ module Layouts
6
+
7
+ module ClassMethods
8
+ # none
9
+ end
10
+
11
+ module InstanceMethods
12
+
13
+ # render with layout, if it is set through the "layout" accessor method and a corresponding file is found
14
+ def render_message_with_layouts(method_name, body)
15
+ return render_message_without_layouts(method_name, body) if @layout.blank?
16
+ # template was set, now render with layout
17
+ template = initialize_template_class body
18
+ template = render_content method_name, template
19
+ render_layout_template template, method_name
20
+ end
21
+
22
+ protected
23
+
24
+ # tries to find a matching template and renders the inner content back to the template
25
+ def render_content(method_name, template)
26
+ template.instance_variable_set(:@content_for_layout, render_content_for_layout(method_name, template))
27
+ template
28
+ end
29
+
30
+ # builds the filename from the method_name, then renders the inner content
31
+ def render_content_for_layout(method_name, template)
32
+ file_name = extend_with_mailer_name(method_name)
33
+ template.render(:file => file_name)
34
+ end
35
+
36
+ # finds the layout file and renders it, if the file is not found an exception is raised
37
+ # default path for all mailer layouts is layouts/mailers below app/views/
38
+ # you can pass in another layout path as 3rd arguments
39
+ def render_layout_template(template, method_name, layout_path = File.join('layouts', 'mailers'))
40
+ extension_parts = method_name.to_s.split('.')[1..-1]
41
+ while !extension_parts.blank?
42
+ file_name = File.join(layout_path, ([@layout.to_s] + extension_parts).join('.'))
43
+ return render_layout(file_name, template) if template_exists?(file_name)
44
+ extension_parts.shift
45
+ end
46
+ # nothing found, complain
47
+ raise "Layout '#{@layout}' not found"
48
+ end
49
+
50
+ def render_layout(file_name, template)
51
+ template.render(:file => file_name)
52
+ end
53
+
54
+ # check if a the given view exists within the app/views folder
55
+ def template_exists?(file_name)
56
+ full_path = File.join(RAILS_ROOT, '**', 'views', file_name)
57
+ files = Dir.glob(full_path)
58
+ !files.blank?
59
+ end
60
+
61
+ def extend_with_mailer_name(template_name)
62
+ template_name.to_s =~ /\// ? template_name : File.join(mailer_name, template_name)
63
+ end
64
+
65
+ end
66
+
67
+ # create "layout" method to define the layout name
68
+ def self.included(receiver)
69
+ receiver.class_eval do
70
+ extend ClassMethods
71
+ include InstanceMethods
72
+
73
+ adv_attr_accessor :layout
74
+ alias_method_chain :render_message, :layouts
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+
81
+ ActionMailer::Base.send :include, ActionMailer::Layouts
@@ -0,0 +1,4 @@
1
+ require File.join(File.dirname(__FILE__), 'awesome_email', 'layouts.rb')
2
+ require File.join(File.dirname(__FILE__), 'awesome_email', 'inline_styles.rb')
3
+ require File.join(File.dirname(__FILE__), 'awesome_email', 'convert_entities.rb')
4
+ require File.join(File.dirname(__FILE__), 'awesome_email', 'helpers.rb')
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib', '..', 'awesome_email.rb'))
@@ -0,0 +1,199 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ require 'rubygems'
5
+
6
+ gem 'actionmailer', '>= 2.0.1'
7
+ gem 'actionpack', '>= 2.0.1'
8
+
9
+ require 'action_mailer'
10
+ require 'action_view'
11
+
12
+ require 'awesome_email'
13
+
14
+ require 'test/unit'
15
+ require 'test_helper'
16
+
17
+ ActionMailer::Base.delivery_method = :test
18
+
19
+ RAILS_ROOT = '/' << File.join('some', 'dir')
20
+ CSS_TEST_FILE = File.join(RAILS_ROOT, 'public', 'stylesheets', 'mails', 'test.css')
21
+
22
+ #################################################################
23
+
24
+ # Do some mocking, use Mocha here?
25
+ class SimpleMailer < ActionMailer::Base
26
+
27
+ def test
28
+ setup_multipart_mail
29
+ layout 'test'
30
+ end
31
+
32
+ protected
33
+
34
+ def setup_multipart_mail
35
+ headers 'Content-transfer-encoding' => '8bit'
36
+ sent_on Time.now
37
+ content_type 'text/html'
38
+ end
39
+
40
+ def html_part?(method_name)
41
+ true
42
+ end
43
+
44
+ def render_content_for_layout(method_name, template)
45
+ 'test inner content'
46
+ end
47
+
48
+ # mock rendering
49
+ def render_layout_template(template, method_name, layout_path = File.join('layouts', 'mailers'))
50
+ return template.render(:inline => "<html><body><h1>Fäncy</h1><p><%= yield %></p></body></html>")
51
+ html = %{
52
+ <!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">
53
+ <html>
54
+ <head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head>
55
+ <body><p><%= yield %></p></body>
56
+ </html>
57
+ }
58
+ return template.render(:inline => html)
59
+ end
60
+
61
+ end
62
+
63
+ ###############################################################
64
+
65
+ # test mailer
66
+ class MyMailer
67
+ def render_message(method_name, body)
68
+ end
69
+
70
+ def parse_css_from_file(file_name)
71
+ 'h1 {font-size: 140.0% !important}'
72
+ end
73
+
74
+ def mailer_name
75
+ 'my_mailer'
76
+ end
77
+
78
+ # include neccessary mixins
79
+ include ActionMailer::AdvAttrAccessor
80
+ include ActionMailer::ConvertEntities
81
+ include ActionMailer::InlineStyles
82
+ include ActionMailer::Layouts
83
+ end
84
+
85
+ MyMailer.send(:public, *MyMailer.protected_instance_methods)
86
+ MyMailer.send(:public, *MyMailer.private_instance_methods)
87
+
88
+ ###############################################################
89
+
90
+ # not so great actually, please do help improve this
91
+ class AwesomeEmailTest < Test::Unit::TestCase
92
+
93
+ def setup
94
+ ActionMailer::Base.delivery_method = :test
95
+ ActionMailer::Base.perform_deliveries = true
96
+ ActionMailer::Base.deliveries = []
97
+ @css = 'h1 {font-size: 140.0% !important}'
98
+ @mailer = MyMailer.new
99
+ end
100
+
101
+ #######################
102
+ # inline styles tests #
103
+ #######################
104
+
105
+ def test_should_build_correct_find_css_file_name
106
+
107
+ assert_equal CSS_TEST_FILE, @mailer.build_css_file_name("test")
108
+ end
109
+
110
+ def test_should_build_correct_file_name_from_set_css
111
+ @mailer.css 'test'
112
+ assert_equal CSS_TEST_FILE, @mailer.build_css_file_name_from_css_setting
113
+ end
114
+
115
+ def test_should_build_no_file_name_if_css_not_set
116
+ assert_equal '', @mailer.build_css_file_name_from_css_setting
117
+ end
118
+
119
+ def test_should_not_change_html_if_no_styles_were_found
120
+ html = build_html('', '')
121
+ result = render_inline(html)
122
+ assert_not_nil result
123
+ assert_equal html.gsub(/\n/, ''), result.gsub(/\n/, '')
124
+ end
125
+
126
+ def test_should_add_style_information_found_in_css_file
127
+ html = build_html('<h1>bla</h1>')
128
+ result = render_inline(html)
129
+ assert_not_nil result
130
+ assert_not_equal html, result
131
+ assert result =~ /<h1 style="(.*)font-size:/
132
+ end
133
+
134
+ def test_should_find_matching_rules
135
+ rules = find_rules(build_html('', '<h1>bla</h1>'))
136
+ assert rules.size > 0
137
+ end
138
+
139
+ def test_should_create_css_for_h1
140
+ rules = find_rules(build_html('<h1>bla</h1>'))
141
+ css = @mailer.css_for_rule(rules.first)
142
+ assert_not_nil css
143
+ assert_equal 'font-size: 140.0% !important;', css
144
+ end
145
+
146
+ def test_should_cummulate_style_information
147
+ html = build_html(%Q{<h1 id="oh-hai" class="green-thing" style="border-bottom: 1px solid black;">u haz a flavor</h1>})
148
+ inlined = render_inline(html)
149
+ assert inlined =~ /border-bottom/
150
+ end
151
+
152
+ ##########################
153
+ # convert entities tests #
154
+ ##########################
155
+
156
+ def test_should_replace_entities
157
+ expected = '&auml; &Auml;'
158
+ result = @mailer.convert_to_entities('ä Ä')
159
+ assert_equal expected, result
160
+ end
161
+
162
+ ################
163
+ # layout tests #
164
+ ################
165
+
166
+ def test_should_extend_with_mailer_name
167
+ template_name = 'some_mail'
168
+ result = @mailer.extend_with_mailer_name(template_name)
169
+ assert_equal "my_mailer/#{template_name}", result
170
+ end
171
+
172
+ # make sure the accessors are available
173
+ def test_should_have_awesome_email_accessor_methods
174
+ if RUBY_VERSION >= '1.9'
175
+ assert ActionMailer::Base.instance_methods.include?(:'css')
176
+ assert ActionMailer::Base.instance_methods.include?(:'css=')
177
+ assert ActionMailer::Base.instance_methods.include?(:'layout')
178
+ assert ActionMailer::Base.instance_methods.include?(:'layout=')
179
+ else
180
+ assert ActionMailer::Base.instance_methods.include?('css')
181
+ assert ActionMailer::Base.instance_methods.include?('css=')
182
+ assert ActionMailer::Base.instance_methods.include?('layout')
183
+ assert ActionMailer::Base.instance_methods.include?('layout=')
184
+ end
185
+ end
186
+
187
+ # check for delivery errors
188
+ def test_should_deliver
189
+ SimpleMailer.deliver_test
190
+ assert SimpleMailer.deliveries.size > 0
191
+ end
192
+
193
+ # test all of the awesomeness
194
+ def test_should_render_layout_convert_entities_and_apply_css
195
+ SimpleMailer.deliver_test
196
+ assert SimpleMailer.deliveries.last.body =~ /<h1>F&auml;ncy<\/h1><p>test inner content<\/p>/
197
+ end
198
+
199
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ $KCODE = 'u' unless RUBY_VERSION >= '1.9'
3
+
4
+ class Test::Unit::TestCase
5
+
6
+ protected
7
+
8
+ def find_rules(html)
9
+ css_doc = @mailer.parse_css_doc(@css)
10
+ html_doc = @mailer.parse_html_doc(html)
11
+ css_doc.rule_sets
12
+ end
13
+
14
+ def render_inline(html)
15
+ css_doc = @mailer.parse_css_doc(@css)
16
+ html_doc = @mailer.parse_html_doc(html)
17
+ @mailer.render_inline(css_doc, html_doc)
18
+ end
19
+
20
+ def build_html(content = '', head = '')
21
+ %Q{<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">#{head}</head><body>#{content}</body></html>}
22
+ end
23
+
24
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grimen-awesome_email
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - imedo GmbH
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-31 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Rails ActionMailer with HTML layouts, inline CSS and entity substitution.
17
+ email: entwickler@imedo.de
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.textile
24
+ files:
25
+ - MIT-LICENSE
26
+ - README.textile
27
+ - Rakefile
28
+ - lib/awesome_email.rb
29
+ - lib/awesome_email/convert_entities.rb
30
+ - lib/awesome_email/helpers.rb
31
+ - lib/awesome_email/inline_styles.rb
32
+ - lib/awesome_email/layouts.rb
33
+ - rails/init.rb
34
+ - test/awesome_email_test.rb
35
+ - test/test_helper.rb
36
+ has_rdoc: true
37
+ homepage: http://github.com/grimen/awesome_email/tree/master
38
+ post_install_message:
39
+ rdoc_options:
40
+ - --charset=UTF-8
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.2.0
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: Rails ActionMailer with HTML layouts, inline CSS and entity substitution.
62
+ test_files:
63
+ - test/awesome_email_test.rb
64
+ - test/test_helper.rb