legacy_mailers 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/README.md +29 -0
  2. data/lib/action_mailer/adv_attr_accessor.rb +28 -0
  3. data/lib/action_mailer/deprecated_api.rb +152 -0
  4. data/lib/action_mailer/old_api.rb +258 -0
  5. data/lib/legacy_mailers.rb +10 -0
  6. data/lib/legacy_mailers/version.rb +3 -0
  7. data/test/abstract_unit.rb +70 -0
  8. data/test/adv_attr_test.rb +36 -0
  9. data/test/asset_host_test.rb +56 -0
  10. data/test/fixtures/another.path/base_mailer/welcome.erb +1 -0
  11. data/test/fixtures/asset_host_mailer/email_with_asset.html.erb +1 -0
  12. data/test/fixtures/asset_mailer/welcome.html.erb +1 -0
  13. data/test/fixtures/attachments/foo.jpg +0 -0
  14. data/test/fixtures/attachments/test.jpg +0 -0
  15. data/test/fixtures/auto_layout_mailer/hello.html.erb +1 -0
  16. data/test/fixtures/auto_layout_mailer/multipart.html.erb +1 -0
  17. data/test/fixtures/auto_layout_mailer/multipart.text.erb +1 -0
  18. data/test/fixtures/base_mailer/attachment_with_content.erb +1 -0
  19. data/test/fixtures/base_mailer/different_layout.html.erb +1 -0
  20. data/test/fixtures/base_mailer/different_layout.text.erb +1 -0
  21. data/test/fixtures/base_mailer/email_custom_layout.text.html.erb +1 -0
  22. data/test/fixtures/base_mailer/email_with_translations.html.erb +1 -0
  23. data/test/fixtures/base_mailer/explicit_multipart_templates.html.erb +1 -0
  24. data/test/fixtures/base_mailer/explicit_multipart_templates.text.erb +1 -0
  25. data/test/fixtures/base_mailer/explicit_multipart_with_one_template.erb +1 -0
  26. data/test/fixtures/base_mailer/html_only.html.erb +1 -0
  27. data/test/fixtures/base_mailer/implicit_multipart.html.erb +1 -0
  28. data/test/fixtures/base_mailer/implicit_multipart.text.erb +1 -0
  29. data/test/fixtures/base_mailer/implicit_with_locale.en.html.erb +1 -0
  30. data/test/fixtures/base_mailer/implicit_with_locale.html.erb +1 -0
  31. data/test/fixtures/base_mailer/implicit_with_locale.pl.text.erb +1 -0
  32. data/test/fixtures/base_mailer/implicit_with_locale.text.erb +1 -0
  33. data/test/fixtures/base_mailer/inline_attachment.html.erb +5 -0
  34. data/test/fixtures/base_mailer/inline_attachment.text.erb +4 -0
  35. data/test/fixtures/base_mailer/plain_text_only.text.erb +1 -0
  36. data/test/fixtures/base_mailer/welcome.erb +1 -0
  37. data/test/fixtures/explicit_layout_mailer/logout.html.erb +1 -0
  38. data/test/fixtures/explicit_layout_mailer/signup.html.erb +1 -0
  39. data/test/fixtures/first_mailer/share.erb +1 -0
  40. data/test/fixtures/i18n_test_mailer/mail_with_i18n_subject.erb +4 -0
  41. data/test/fixtures/layouts/auto_layout_mailer.html.erb +1 -0
  42. data/test/fixtures/layouts/auto_layout_mailer.text.erb +1 -0
  43. data/test/fixtures/layouts/different_layout.html.erb +1 -0
  44. data/test/fixtures/layouts/different_layout.text.erb +1 -0
  45. data/test/fixtures/layouts/spam.html.erb +1 -0
  46. data/test/fixtures/nested_layout_mailer/signup.html.erb +1 -0
  47. data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb +1 -0
  48. data/test/fixtures/raw_email +14 -0
  49. data/test/fixtures/raw_email10 +20 -0
  50. data/test/fixtures/raw_email12 +32 -0
  51. data/test/fixtures/raw_email13 +29 -0
  52. data/test/fixtures/raw_email2 +114 -0
  53. data/test/fixtures/raw_email3 +70 -0
  54. data/test/fixtures/raw_email4 +59 -0
  55. data/test/fixtures/raw_email5 +19 -0
  56. data/test/fixtures/raw_email6 +20 -0
  57. data/test/fixtures/raw_email7 +66 -0
  58. data/test/fixtures/raw_email8 +47 -0
  59. data/test/fixtures/raw_email9 +28 -0
  60. data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
  61. data/test/fixtures/raw_email_with_invalid_characters_in_content_type +104 -0
  62. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  63. data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
  64. data/test/fixtures/second_mailer/share.erb +1 -0
  65. data/test/fixtures/templates/signed_up.erb +3 -0
  66. data/test/fixtures/test_mailer/_subtemplate.text.erb +1 -0
  67. data/test/fixtures/test_mailer/custom_templating_extension.html.haml +6 -0
  68. data/test/fixtures/test_mailer/custom_templating_extension.text.haml +6 -0
  69. data/test/fixtures/test_mailer/implicitly_multipart_example.html.erb +10 -0
  70. data/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~ +10 -0
  71. data/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb +1 -0
  72. data/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak +1 -0
  73. data/test/fixtures/test_mailer/implicitly_multipart_example.text.erb +2 -0
  74. data/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb +1 -0
  75. data/test/fixtures/test_mailer/included_subtemplate.text.erb +1 -0
  76. data/test/fixtures/test_mailer/multipart_alternative.html.erb +1 -0
  77. data/test/fixtures/test_mailer/multipart_alternative.plain.erb +1 -0
  78. data/test/fixtures/test_mailer/rxml_template.rxml +2 -0
  79. data/test/fixtures/test_mailer/signed_up.html.erb +3 -0
  80. data/test/fixtures/url_test_mailer/signed_up_with_url.erb +5 -0
  81. data/test/mail_layout_test.rb +126 -0
  82. data/test/mail_render_test.rb +162 -0
  83. data/test/mail_service_test.rb +1214 -0
  84. metadata +308 -0
@@ -0,0 +1,29 @@
1
+ # LegacyMailers
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'legacy_mailers'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install legacy_mailers
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,28 @@
1
+ module ActionMailer
2
+ module AdvAttrAccessor #:nodoc:
3
+ def adv_attr_accessor(name, deprecation=nil)
4
+ ivar = "@#{name}"
5
+ deprecation ||= "Please pass :#{name} as hash key to mail() instead"
6
+
7
+ class_eval <<-ACCESSORS, __FILE__, __LINE__ + 1
8
+ def #{name}=(value)
9
+ ActiveSupport::Deprecation.warn "#{name}= is deprecated. #{deprecation}"
10
+ #{ivar} = value
11
+ end
12
+
13
+ def #{name}(*args)
14
+ raise ArgumentError, "expected 0 or 1 parameters" unless args.length <= 1
15
+ if args.empty?
16
+ ActiveSupport::Deprecation.warn "#{name}() is deprecated and will be removed in future versions."
17
+ #{ivar} if instance_variable_names.include?(#{ivar.inspect})
18
+ else
19
+ ActiveSupport::Deprecation.warn "#{name}(value) is deprecated. #{deprecation}"
20
+ #{ivar} = args.first
21
+ end
22
+ end
23
+ ACCESSORS
24
+
25
+ self.protected_instance_variables << ivar if self.respond_to?(:protected_instance_variables)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,152 @@
1
+ require 'active_support/core_ext/object/try'
2
+
3
+ module ActionMailer
4
+ # This is the API which is deprecated and is going to be removed on Rails 3.1 release.
5
+ # Part of the old API will be deprecated after 3.1, for a smoother deprecation process.
6
+ # Check those in OldApi instead.
7
+ module DeprecatedApi #:nodoc:
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ [:charset, :content_type, :mime_version, :implicit_parts_order].each do |method|
12
+ class_eval <<-FILE, __FILE__, __LINE__ + 1
13
+ def self.default_#{method}
14
+ @@default_#{method}
15
+ end
16
+
17
+ def self.default_#{method}=(value)
18
+ ActiveSupport::Deprecation.warn "ActionMailer::Base.default_#{method}=value is deprecated, " <<
19
+ "use default :#{method} => value instead"
20
+ @@default_#{method} = value
21
+ end
22
+
23
+ @@default_#{method} = nil
24
+ FILE
25
+ end
26
+
27
+ class << self
28
+ alias_method_chain :respond_to?, :deprecated_api
29
+ alias_method_chain :method_missing, :deprecated_api
30
+ end
31
+ end
32
+
33
+ module ClassMethods
34
+ # Deliver the given mail object directly. This can be used to deliver
35
+ # a preconstructed mail object, like:
36
+ #
37
+ # email = MyMailer.create_some_mail(parameters)
38
+ # email.set_some_obscure_header "frobnicate"
39
+ # MyMailer.deliver(email)
40
+ def deliver(mail, show_warning=true)
41
+ if show_warning
42
+ ActiveSupport::Deprecation.warn "#{self}.deliver is deprecated, call " <<
43
+ "deliver in the mailer instance instead", caller[0,2]
44
+ end
45
+
46
+ raise "no mail object available for delivery!" unless mail
47
+ wrap_delivery_behavior(mail)
48
+ mail.deliver
49
+ mail
50
+ end
51
+
52
+ def template_root
53
+ self.view_paths && self.view_paths.first
54
+ end
55
+
56
+ def template_root=(root)
57
+ ActiveSupport::Deprecation.warn "template_root= is deprecated, use prepend_view_path instead", caller[0,2]
58
+ self.view_paths = ActionView::Base.process_view_paths(root)
59
+ end
60
+
61
+ def respond_to_with_deprecated_api?(method_symbol, include_private = false)
62
+ matches_dynamic_method?(method_symbol) || respond_to_without_deprecated_api?(method_symbol, false)
63
+ end
64
+
65
+ def method_missing_with_deprecated_api(method_symbol, *parameters)
66
+ if match = matches_dynamic_method?(method_symbol)
67
+ case match[1]
68
+ when 'create'
69
+ ActiveSupport::Deprecation.warn "#{self}.create_#{match[2]} is deprecated, " <<
70
+ "use #{self}.#{match[2]} instead", caller[0,2]
71
+ new(match[2], *parameters).message
72
+ when 'deliver'
73
+ ActiveSupport::Deprecation.warn "#{self}.deliver_#{match[2]} is deprecated, " <<
74
+ "use #{self}.#{match[2]}.deliver instead", caller[0,2]
75
+ new(match[2], *parameters).message.deliver
76
+ else method_missing_without_deprecated_api(method_symbol, *parameters)
77
+ end
78
+ else
79
+ method_missing_without_deprecated_api(method_symbol, *parameters)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def matches_dynamic_method?(method_name)
86
+ method_name = method_name.to_s
87
+ /^(create|deliver)_([_a-z]\w*)/.match(method_name) || /^(new)$/.match(method_name)
88
+ end
89
+ end
90
+
91
+ # Delivers a Mail object. By default, it delivers the cached mail
92
+ # object (from the <tt>create!</tt> method). If no cached mail object exists, and
93
+ # no alternate has been given as the parameter, this will fail.
94
+ def deliver!(mail = @_message)
95
+ ActiveSupport::Deprecation.warn "Calling deliver in the AM::Base object is deprecated, " <<
96
+ "please call deliver in the Mail instance", caller[0,2]
97
+ self.class.deliver(mail, false)
98
+ end
99
+ alias :deliver :deliver!
100
+
101
+ def render(*args)
102
+ options = args.last.is_a?(Hash) ? args.last : {}
103
+
104
+ if file = options[:file] and !file.index("/")
105
+ ActiveSupport::Deprecation.warn("render :file is deprecated except for absolute paths. " \
106
+ "Please use render :template instead")
107
+ options[:prefix] = _prefix
108
+ end
109
+
110
+ if options[:body].is_a?(Hash)
111
+ ActiveSupport::Deprecation.warn(':body in render deprecated. Please use instance ' <<
112
+ 'variables as assigns instead', caller[0,1])
113
+
114
+ options[:body].each { |k,v| instance_variable_set(:"@#{k}", v) }
115
+ end
116
+ super
117
+ end
118
+
119
+ # Render a message but does not set it as mail body. Useful for rendering
120
+ # data for part and attachments.
121
+ #
122
+ # Examples:
123
+ #
124
+ # render_message "special_message"
125
+ # render_message :template => "special_message"
126
+ # render_message :inline => "<%= 'Hi!' %>"
127
+ #
128
+ def render_message(*args)
129
+ ActiveSupport::Deprecation.warn "render_message is deprecated, use render instead", caller[0,2]
130
+ render(*args)
131
+ end
132
+
133
+ private
134
+
135
+ def initialize_defaults(*)
136
+ @charset ||= self.class.default_charset.try(:dup)
137
+ @content_type ||= self.class.default_content_type.try(:dup)
138
+ @implicit_parts_order ||= self.class.default_implicit_parts_order.try(:dup)
139
+ @mime_version ||= self.class.default_mime_version.try(:dup)
140
+ super
141
+ end
142
+
143
+ def create_parts
144
+ if @body.is_a?(Hash) && !@body.empty?
145
+ ActiveSupport::Deprecation.warn "Giving a hash to body is deprecated, please use instance variables instead", caller[0,2]
146
+ @body.each { |k, v| instance_variable_set(:"@#{k}", v) }
147
+ end
148
+ super
149
+ end
150
+
151
+ end
152
+ end
@@ -0,0 +1,258 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/object/try'
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ module ActionMailer
6
+ module OldApi #:nodoc:
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ extend ActionMailer::AdvAttrAccessor
11
+ self.protected_instance_variables.concat %w(@parts @mail_was_called @headers)
12
+
13
+ # Specify the BCC addresses for the message
14
+ adv_attr_accessor :bcc
15
+
16
+ # Specify the CC addresses for the message.
17
+ adv_attr_accessor :cc
18
+
19
+ # Specify the charset to use for the message. This defaults to the
20
+ # +default_charset+ specified for ActionMailer::Base.
21
+ adv_attr_accessor :charset
22
+
23
+ # Specify the content type for the message. This defaults to <tt>text/plain</tt>
24
+ # in most cases, but can be automatically set in some situations.
25
+ adv_attr_accessor :content_type
26
+
27
+ # Specify the from address for the message.
28
+ adv_attr_accessor :from
29
+
30
+ # Specify the address (if different than the "from" address) to direct
31
+ # replies to this message.
32
+ adv_attr_accessor :reply_to
33
+
34
+ # Specify the order in which parts should be sorted, based on content-type.
35
+ # This defaults to the value for the +default_implicit_parts_order+.
36
+ adv_attr_accessor :implicit_parts_order
37
+
38
+ # Defaults to "1.0", but may be explicitly given if needed.
39
+ adv_attr_accessor :mime_version
40
+
41
+ # The recipient addresses for the message, either as a string (for a single
42
+ # address) or an array (for multiple addresses).
43
+ adv_attr_accessor :recipients, "Please pass :to as hash key to mail() instead"
44
+
45
+ # The date on which the message was sent. If not set (the default), the
46
+ # header will be set by the delivery agent.
47
+ adv_attr_accessor :sent_on, "Please pass :date as hash key to mail() instead"
48
+
49
+ # Specify the subject of the message.
50
+ adv_attr_accessor :subject
51
+
52
+ # Specify the template name to use for current message. This is the "base"
53
+ # template name, without the extension or directory, and may be used to
54
+ # have multiple mailer methods share the same template.
55
+ adv_attr_accessor :template, "Please pass :template_name or :template_path as hash key to mail() instead"
56
+
57
+ # Define the body of the message. This is either a Hash (in which case it
58
+ # specifies the variables to pass to the template when it is rendered),
59
+ # or a string, in which case it specifies the actual text of the message.
60
+ adv_attr_accessor :body
61
+
62
+ def process(method_name, *args)
63
+ lookup_context.skip_default_locale!
64
+
65
+ initialize_defaults(method_name)
66
+ super
67
+
68
+ unless @mail_was_called
69
+ create_parts
70
+ create_mail
71
+ end
72
+ @_message
73
+ end
74
+ end
75
+
76
+ # Add a part to a multipart message, with the given content-type. The
77
+ # part itself is yielded to the block so that other properties (charset,
78
+ # body, headers, etc.) can be set on it.
79
+ def part(params)
80
+ ActiveSupport::Deprecation.warn "part() is deprecated and will be removed in future versions. " <<
81
+ "Please pass a block to mail() instead."
82
+ params = {:content_type => params} if String === params
83
+
84
+ if custom_headers = params.delete(:headers)
85
+ params.merge!(custom_headers)
86
+ end
87
+
88
+ part = Mail::Part.new(params)
89
+
90
+ yield part if block_given?
91
+ @parts << part
92
+ end
93
+
94
+ # Add an attachment to a multipart message. This is simply a part with the
95
+ # content-disposition set to "attachment".
96
+ def attachment(params, &block)
97
+ ActiveSupport::Deprecation.warn "attachment() is deprecated and will be removed in future versions. " <<
98
+ "Please use the attachments[] API instead."
99
+ params = { :content_type => params } if String === params
100
+
101
+ params[:content] ||= params.delete(:data) || params.delete(:body)
102
+
103
+ if params[:filename]
104
+ params = normalize_file_hash(params)
105
+ else
106
+ params = normalize_nonfile_hash(params)
107
+ end
108
+
109
+ part(params, &block)
110
+ end
111
+
112
+ protected
113
+
114
+ def normalize_nonfile_hash(params)
115
+ content_disposition = "attachment;"
116
+
117
+ mime_type = params.delete(:mime_type)
118
+
119
+ if content_type = params.delete(:content_type)
120
+ content_type = "#{mime_type || content_type};"
121
+ end
122
+
123
+ params[:body] = params.delete(:data) if params[:data]
124
+
125
+ { :content_type => content_type,
126
+ :content_disposition => content_disposition }.merge(params)
127
+ end
128
+
129
+ def normalize_file_hash(params)
130
+ filename = File.basename(params.delete(:filename))
131
+ content_disposition = "attachment; filename=\"#{File.basename(filename)}\""
132
+
133
+ mime_type = params.delete(:mime_type)
134
+
135
+ if (content_type = params.delete(:content_type)) && (content_type !~ /filename=/)
136
+ content_type = "#{mime_type || content_type}; filename=\"#{filename}\""
137
+ end
138
+
139
+ params[:body] = params.delete(:data) if params[:data]
140
+
141
+ { :content_type => content_type,
142
+ :content_disposition => content_disposition }.merge(params)
143
+ end
144
+
145
+ def create_mail
146
+ m = @_message
147
+
148
+ set_fields!({:subject => @subject, :to => @recipients, :from => @from,
149
+ :bcc => @bcc, :cc => @cc, :reply_to => @reply_to}, @charset)
150
+
151
+ m.mime_version = @mime_version if @mime_version
152
+ m.date = @sent_on.to_time rescue @sent_on if @sent_on
153
+
154
+ @headers.each { |k, v| m[k] = v }
155
+
156
+ real_content_type, ctype_attrs = parse_content_type
157
+ main_type, sub_type = split_content_type(real_content_type)
158
+
159
+ if @parts.size == 1 && @parts.first.parts.empty?
160
+ m.content_type([main_type, sub_type, ctype_attrs])
161
+ m.body = @parts.first.body.encoded
162
+ else
163
+ @parts.each do |p|
164
+ m.add_part(p)
165
+ end
166
+
167
+ m.body.set_sort_order(@implicit_parts_order)
168
+ m.body.sort_parts!
169
+
170
+ if real_content_type =~ /multipart/
171
+ ctype_attrs.delete "charset"
172
+ m.content_type([main_type, sub_type, ctype_attrs])
173
+ end
174
+ end
175
+
176
+ wrap_delivery_behavior!
177
+ m.content_transfer_encoding = '8bit' unless m.body.only_us_ascii?
178
+
179
+ @_message
180
+ end
181
+
182
+ # Set up the default values for the various instance variables of this
183
+ # mailer. Subclasses may override this method to provide different
184
+ # defaults.
185
+ def initialize_defaults(method_name)
186
+ @charset ||= self.class.default[:charset].try(:dup)
187
+ @content_type ||= self.class.default[:content_type].try(:dup)
188
+ @implicit_parts_order ||= self.class.default[:parts_order].try(:dup)
189
+ @mime_version ||= self.class.default[:mime_version].try(:dup)
190
+
191
+ @cc, @bcc, @reply_to, @subject, @from, @recipients = nil, nil, nil, nil, nil, nil
192
+
193
+ @mailer_name ||= self.class.mailer_name.dup
194
+ @template ||= method_name
195
+ @mail_was_called = false
196
+
197
+ @parts ||= []
198
+ @headers ||= {}
199
+ @sent_on ||= Time.now
200
+ @body ||= {}
201
+ end
202
+
203
+ def create_parts
204
+ if String === @body
205
+ @parts.unshift create_inline_part(@body)
206
+ elsif @parts.empty? || @parts.all? { |p| p.content_disposition =~ /^attachment/ }
207
+ lookup_context.find_all(@template, [@mailer_name]).each do |template|
208
+ self.formats = template.formats
209
+ @parts << create_inline_part(render(:template => template), template.mime_type)
210
+ end
211
+
212
+ if @parts.size > 1
213
+ @content_type = "multipart/alternative" if @content_type !~ /^multipart/
214
+ end
215
+
216
+ # If this is a multipart e-mail add the mime_version if it is not
217
+ # already set.
218
+ @mime_version ||= "1.0" unless @parts.empty?
219
+ end
220
+ end
221
+
222
+ def create_inline_part(body, mime_type=nil)
223
+ ct = mime_type || "text/plain"
224
+ main_type, sub_type = split_content_type(ct.to_s)
225
+
226
+ Mail::Part.new(
227
+ :content_type => [main_type, sub_type, {:charset => charset}],
228
+ :content_disposition => "inline",
229
+ :body => body
230
+ )
231
+ end
232
+
233
+ def set_fields!(headers, charset) #:nodoc:
234
+ m = @_message
235
+ m.charset = charset
236
+ m.subject ||= headers.delete(:subject) if headers[:subject]
237
+ m.to ||= headers.delete(:to) if headers[:to]
238
+ m.from ||= headers.delete(:from) if headers[:from]
239
+ m.cc ||= headers.delete(:cc) if headers[:cc]
240
+ m.bcc ||= headers.delete(:bcc) if headers[:bcc]
241
+ m.reply_to ||= headers.delete(:reply_to) if headers[:reply_to]
242
+ end
243
+
244
+ def split_content_type(ct)
245
+ ct.to_s.split("/")
246
+ end
247
+
248
+ def parse_content_type
249
+ if @content_type.blank?
250
+ [ nil, {} ]
251
+ else
252
+ ctype, *attrs = @content_type.split(/;\s*/)
253
+ attrs = Hash[attrs.map { |attr| attr.split(/=/, 2) }]
254
+ [ctype, {"charset" => @charset}.merge!(attrs)]
255
+ end
256
+ end
257
+ end
258
+ end