actionmailer 1.3.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionmailer might be problematic. Click here for more details.

Files changed (96) hide show
  1. data/CHANGELOG +40 -28
  2. data/MIT-LICENSE +1 -1
  3. data/README +2 -2
  4. data/Rakefile +4 -3
  5. data/install.rb +1 -1
  6. data/lib/action_mailer.rb +5 -3
  7. data/lib/action_mailer/base.rb +57 -36
  8. data/lib/action_mailer/helpers.rb +4 -4
  9. data/lib/action_mailer/part.rb +2 -5
  10. data/lib/action_mailer/test_case.rb +59 -0
  11. data/lib/action_mailer/test_helper.rb +67 -0
  12. data/lib/action_mailer/vendor.rb +14 -0
  13. data/lib/action_mailer/vendor/{text → text-format-0.6.3/text}/format.rb +0 -0
  14. data/lib/action_mailer/vendor/tmail-1.1.0/tmail.rb +4 -0
  15. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/Makefile +19 -0
  16. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/address.rb +6 -3
  17. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/attachments.rb +10 -2
  18. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/base64.rb +52 -0
  19. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/compat.rb +39 -0
  20. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/config.rb +5 -3
  21. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/core_extensions.rb +67 -0
  22. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/encode.rb +23 -9
  23. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/facade.rb +0 -0
  24. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/header.rb +23 -6
  25. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/info.rb +0 -0
  26. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/interface.rb +540 -0
  27. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/loader.rb +0 -0
  28. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mail.rb +20 -5
  29. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mailbox.rb +5 -3
  30. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mbox.rb +0 -0
  31. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/net.rb +5 -3
  32. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/obsolete.rb +5 -3
  33. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/parser.rb +234 -281
  34. data/lib/action_mailer/vendor/tmail-1.1.0/tmail/parser.y +381 -0
  35. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/port.rb +5 -3
  36. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/quoting.rb +12 -1
  37. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/scanner.rb +5 -3
  38. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/scanner_r.rb +1 -1
  39. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/stringio.rb +6 -4
  40. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/tmail.rb +0 -0
  41. data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/utils.rb +50 -7
  42. data/lib/action_mailer/vendor/{tmail/base64.rb → tmail-1.1.0/tmail/version.rb} +7 -40
  43. data/lib/action_mailer/version.rb +3 -3
  44. data/lib/actionmailer.rb +1 -0
  45. data/test/abstract_unit.rb +19 -0
  46. data/test/delivery_method_test.rb +51 -0
  47. data/test/fixtures/first_mailer/share.erb +1 -0
  48. data/test/fixtures/first_mailer/share.rhtml +0 -1
  49. data/test/fixtures/helper_mailer/use_example_helper.erb +1 -0
  50. data/test/fixtures/helper_mailer/use_example_helper.rhtml +0 -0
  51. data/test/fixtures/helper_mailer/use_helper.erb +1 -0
  52. data/test/fixtures/helper_mailer/use_helper.rhtml +0 -1
  53. data/test/fixtures/helper_mailer/use_helper_method.erb +1 -0
  54. data/test/fixtures/helper_mailer/use_helper_method.rhtml +0 -1
  55. data/test/fixtures/helper_mailer/use_mail_helper.erb +5 -0
  56. data/test/fixtures/helper_mailer/use_mail_helper.rhtml +0 -5
  57. data/test/fixtures/helpers/{test_helper.rb → example_helper.rb} +2 -2
  58. data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb +1 -0
  59. data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.rhtml +0 -1
  60. data/test/fixtures/raw_base64_decoded_string +0 -0
  61. data/test/fixtures/raw_base64_encoded_string +1 -0
  62. data/test/fixtures/raw_email_with_invalid_characters_in_content_type +104 -0
  63. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  64. data/test/fixtures/second_mailer/share.erb +1 -0
  65. data/test/fixtures/second_mailer/share.rhtml +0 -1
  66. data/test/fixtures/templates/signed_up.erb +3 -0
  67. data/test/fixtures/templates/signed_up.rhtml +0 -3
  68. data/test/fixtures/test_mailer/_subtemplate.text.plain.erb +1 -0
  69. data/test/fixtures/test_mailer/custom_templating_extension.text.html.haml +6 -0
  70. data/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml +6 -0
  71. data/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb +1 -0
  72. data/test/fixtures/test_mailer/implicitly_multipart_example.ignored.rhtml +0 -1
  73. data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb +10 -0
  74. data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.rhtml +0 -10
  75. data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb +2 -0
  76. data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.rhtml +0 -2
  77. data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb +1 -0
  78. data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml +0 -1
  79. data/test/fixtures/test_mailer/included_subtemplate.text.plain.erb +1 -0
  80. data/test/fixtures/test_mailer/rxml_template.builder +2 -0
  81. data/test/fixtures/test_mailer/rxml_template.rxml +2 -0
  82. data/test/fixtures/test_mailer/signed_up.erb +3 -0
  83. data/test/fixtures/test_mailer/signed_up.rhtml +0 -3
  84. data/test/fixtures/test_mailer/signed_up_with_url.erb +5 -0
  85. data/test/fixtures/test_mailer/signed_up_with_url.rhtml +0 -3
  86. data/test/mail_helper_test.rb +10 -6
  87. data/test/mail_render_test.rb +45 -2
  88. data/test/mail_service_test.rb +150 -27
  89. data/test/quoting_test.rb +57 -3
  90. data/test/test_helper_test.rb +117 -0
  91. data/test/tmail_test.rb +9 -0
  92. data/test/url_test.rb +10 -2
  93. metadata +69 -32
  94. data/lib/action_mailer/vendor/tmail.rb +0 -3
  95. data/test/fixtures/helper_mailer/use_test_helper.rhtml +0 -1
  96. data/test/fixtures/raw_email11 +0 -34
@@ -0,0 +1,540 @@
1
+ =begin rdoc
2
+
3
+ = Facade.rb Provides an interface to the TMail object
4
+
5
+ =end
6
+ #--
7
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
29
+ # with permission of Minero Aoki.
30
+ #++
31
+
32
+ require 'tmail/utils'
33
+
34
+ module TMail
35
+
36
+ class Mail
37
+
38
+ def header_string( name, default = nil )
39
+ h = @header[name.downcase] or return default
40
+ h.to_s
41
+ end
42
+
43
+ ###
44
+ ### attributes
45
+ ###
46
+
47
+ include TextUtils
48
+
49
+ def set_string_array_attr( key, strs )
50
+ strs.flatten!
51
+ if strs.empty?
52
+ @header.delete key.downcase
53
+ else
54
+ store key, strs.join(', ')
55
+ end
56
+ strs
57
+ end
58
+ private :set_string_array_attr
59
+
60
+ def set_string_attr( key, str )
61
+ if str
62
+ store key, str
63
+ else
64
+ @header.delete key.downcase
65
+ end
66
+ str
67
+ end
68
+ private :set_string_attr
69
+
70
+ def set_addrfield( name, arg )
71
+ if arg
72
+ h = HeaderField.internal_new(name, @config)
73
+ h.addrs.replace [arg].flatten
74
+ @header[name] = h
75
+ else
76
+ @header.delete name
77
+ end
78
+ arg
79
+ end
80
+ private :set_addrfield
81
+
82
+ def addrs2specs( addrs )
83
+ return nil unless addrs
84
+ list = addrs.map {|addr|
85
+ if addr.address_group?
86
+ then addr.map {|a| a.spec }
87
+ else addr.spec
88
+ end
89
+ }.flatten
90
+ return nil if list.empty?
91
+ list
92
+ end
93
+ private :addrs2specs
94
+
95
+ #
96
+ # date time
97
+ #
98
+
99
+ def date( default = nil )
100
+ if h = @header['date']
101
+ h.date
102
+ else
103
+ default
104
+ end
105
+ end
106
+
107
+ def date=( time )
108
+ if time
109
+ store 'Date', time2str(time)
110
+ else
111
+ @header.delete 'date'
112
+ end
113
+ time
114
+ end
115
+
116
+ def strftime( fmt, default = nil )
117
+ if t = date
118
+ t.strftime(fmt)
119
+ else
120
+ default
121
+ end
122
+ end
123
+
124
+ #
125
+ # destination
126
+ #
127
+
128
+ def to_addrs( default = nil )
129
+ if h = @header['to']
130
+ h.addrs
131
+ else
132
+ default
133
+ end
134
+ end
135
+
136
+ def cc_addrs( default = nil )
137
+ if h = @header['cc']
138
+ h.addrs
139
+ else
140
+ default
141
+ end
142
+ end
143
+
144
+ def bcc_addrs( default = nil )
145
+ if h = @header['bcc']
146
+ h.addrs
147
+ else
148
+ default
149
+ end
150
+ end
151
+
152
+ def to_addrs=( arg )
153
+ set_addrfield 'to', arg
154
+ end
155
+
156
+ def cc_addrs=( arg )
157
+ set_addrfield 'cc', arg
158
+ end
159
+
160
+ def bcc_addrs=( arg )
161
+ set_addrfield 'bcc', arg
162
+ end
163
+
164
+ def to( default = nil )
165
+ addrs2specs(to_addrs(nil)) || default
166
+ end
167
+
168
+ def cc( default = nil )
169
+ addrs2specs(cc_addrs(nil)) || default
170
+ end
171
+
172
+ def bcc( default = nil )
173
+ addrs2specs(bcc_addrs(nil)) || default
174
+ end
175
+
176
+ def to=( *strs )
177
+ set_string_array_attr 'To', strs
178
+ end
179
+
180
+ def cc=( *strs )
181
+ set_string_array_attr 'Cc', strs
182
+ end
183
+
184
+ def bcc=( *strs )
185
+ set_string_array_attr 'Bcc', strs
186
+ end
187
+
188
+ #
189
+ # originator
190
+ #
191
+
192
+ def from_addrs( default = nil )
193
+ if h = @header['from']
194
+ h.addrs
195
+ else
196
+ default
197
+ end
198
+ end
199
+
200
+ def from_addrs=( arg )
201
+ set_addrfield 'from', arg
202
+ end
203
+
204
+ def from( default = nil )
205
+ addrs2specs(from_addrs(nil)) || default
206
+ end
207
+
208
+ def from=( *strs )
209
+ set_string_array_attr 'From', strs
210
+ end
211
+
212
+ def friendly_from( default = nil )
213
+ h = @header['from']
214
+ a, = h.addrs
215
+ return default unless a
216
+ return a.phrase if a.phrase
217
+ return h.comments.join(' ') unless h.comments.empty?
218
+ a.spec
219
+ end
220
+
221
+
222
+ def reply_to_addrs( default = nil )
223
+ if h = @header['reply-to']
224
+ h.addrs
225
+ else
226
+ default
227
+ end
228
+ end
229
+
230
+ def reply_to_addrs=( arg )
231
+ set_addrfield 'reply-to', arg
232
+ end
233
+
234
+ def reply_to( default = nil )
235
+ addrs2specs(reply_to_addrs(nil)) || default
236
+ end
237
+
238
+ def reply_to=( *strs )
239
+ set_string_array_attr 'Reply-To', strs
240
+ end
241
+
242
+
243
+ def sender_addr( default = nil )
244
+ f = @header['sender'] or return default
245
+ f.addr or return default
246
+ end
247
+
248
+ def sender_addr=( addr )
249
+ if addr
250
+ h = HeaderField.internal_new('sender', @config)
251
+ h.addr = addr
252
+ @header['sender'] = h
253
+ else
254
+ @header.delete 'sender'
255
+ end
256
+ addr
257
+ end
258
+
259
+ def sender( default )
260
+ f = @header['sender'] or return default
261
+ a = f.addr or return default
262
+ a.spec
263
+ end
264
+
265
+ def sender=( str )
266
+ set_string_attr 'Sender', str
267
+ end
268
+
269
+
270
+ #
271
+ # subject
272
+ #
273
+
274
+ def subject( default = nil )
275
+ if h = @header['subject']
276
+ h.body
277
+ else
278
+ default
279
+ end
280
+ end
281
+ alias quoted_subject subject
282
+
283
+ def subject=( str )
284
+ set_string_attr 'Subject', str
285
+ end
286
+
287
+ #
288
+ # identity & threading
289
+ #
290
+
291
+ def message_id( default = nil )
292
+ if h = @header['message-id']
293
+ h.id || default
294
+ else
295
+ default
296
+ end
297
+ end
298
+
299
+ def message_id=( str )
300
+ set_string_attr 'Message-Id', str
301
+ end
302
+
303
+ def in_reply_to( default = nil )
304
+ if h = @header['in-reply-to']
305
+ h.ids
306
+ else
307
+ default
308
+ end
309
+ end
310
+
311
+ def in_reply_to=( *idstrs )
312
+ set_string_array_attr 'In-Reply-To', idstrs
313
+ end
314
+
315
+ def references( default = nil )
316
+ if h = @header['references']
317
+ h.refs
318
+ else
319
+ default
320
+ end
321
+ end
322
+
323
+ def references=( *strs )
324
+ set_string_array_attr 'References', strs
325
+ end
326
+
327
+ #
328
+ # MIME headers
329
+ #
330
+
331
+ def mime_version( default = nil )
332
+ if h = @header['mime-version']
333
+ h.version || default
334
+ else
335
+ default
336
+ end
337
+ end
338
+
339
+ def mime_version=( m, opt = nil )
340
+ if opt
341
+ if h = @header['mime-version']
342
+ h.major = m
343
+ h.minor = opt
344
+ else
345
+ store 'Mime-Version', "#{m}.#{opt}"
346
+ end
347
+ else
348
+ store 'Mime-Version', m
349
+ end
350
+ m
351
+ end
352
+
353
+ def content_type( default = nil )
354
+ if h = @header['content-type']
355
+ h.content_type || default
356
+ else
357
+ default
358
+ end
359
+ end
360
+
361
+ def main_type( default = nil )
362
+ if h = @header['content-type']
363
+ h.main_type || default
364
+ else
365
+ default
366
+ end
367
+ end
368
+
369
+ def sub_type( default = nil )
370
+ if h = @header['content-type']
371
+ h.sub_type || default
372
+ else
373
+ default
374
+ end
375
+ end
376
+
377
+ def set_content_type( str, sub = nil, param = nil )
378
+ if sub
379
+ main, sub = str, sub
380
+ else
381
+ main, sub = str.split(%r</>, 2)
382
+ raise ArgumentError, "sub type missing: #{str.inspect}" unless sub
383
+ end
384
+ if h = @header['content-type']
385
+ h.main_type = main
386
+ h.sub_type = sub
387
+ h.params.clear
388
+ else
389
+ store 'Content-Type', "#{main}/#{sub}"
390
+ end
391
+ @header['content-type'].params.replace param if param
392
+ str
393
+ end
394
+
395
+ alias content_type= set_content_type
396
+
397
+ def type_param( name, default = nil )
398
+ if h = @header['content-type']
399
+ h[name] || default
400
+ else
401
+ default
402
+ end
403
+ end
404
+
405
+ def charset( default = nil )
406
+ if h = @header['content-type']
407
+ h['charset'] or default
408
+ else
409
+ default
410
+ end
411
+ end
412
+
413
+ def charset=( str )
414
+ if str
415
+ if h = @header[ 'content-type' ]
416
+ h['charset'] = str
417
+ else
418
+ store 'Content-Type', "text/plain; charset=#{str}"
419
+ end
420
+ end
421
+ str
422
+ end
423
+
424
+ def transfer_encoding( default = nil )
425
+ if h = @header['content-transfer-encoding']
426
+ h.encoding || default
427
+ else
428
+ default
429
+ end
430
+ end
431
+
432
+ def transfer_encoding=( str )
433
+ set_string_attr 'Content-Transfer-Encoding', str
434
+ end
435
+
436
+ alias encoding transfer_encoding
437
+ alias encoding= transfer_encoding=
438
+ alias content_transfer_encoding transfer_encoding
439
+ alias content_transfer_encoding= transfer_encoding=
440
+
441
+ def disposition( default = nil )
442
+ if h = @header['content-disposition']
443
+ h.disposition || default
444
+ else
445
+ default
446
+ end
447
+ end
448
+
449
+ alias content_disposition disposition
450
+
451
+ def set_disposition( str, params = nil )
452
+ if h = @header['content-disposition']
453
+ h.disposition = str
454
+ h.params.clear
455
+ else
456
+ store('Content-Disposition', str)
457
+ h = @header['content-disposition']
458
+ end
459
+ h.params.replace params if params
460
+ end
461
+
462
+ alias disposition= set_disposition
463
+ alias set_content_disposition set_disposition
464
+ alias content_disposition= set_disposition
465
+
466
+ def disposition_param( name, default = nil )
467
+ if h = @header['content-disposition']
468
+ h[name] || default
469
+ else
470
+ default
471
+ end
472
+ end
473
+
474
+ ###
475
+ ### utils
476
+ ###
477
+
478
+ def create_reply
479
+ mail = TMail::Mail.parse('')
480
+ mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '')
481
+ mail.to_addrs = reply_addresses([])
482
+ mail.in_reply_to = [message_id(nil)].compact
483
+ mail.references = references([]) + [message_id(nil)].compact
484
+ mail.mime_version = '1.0'
485
+ mail
486
+ end
487
+
488
+ def base64_encode
489
+ store 'Content-Transfer-Encoding', 'Base64'
490
+ self.body = Base64.folding_encode(self.body)
491
+ end
492
+
493
+ def base64_decode
494
+ if /base64/i === self.transfer_encoding('')
495
+ store 'Content-Transfer-Encoding', '8bit'
496
+ self.body = Base64.decode(self.body, @config.strict_base64decode?)
497
+ end
498
+ end
499
+
500
+ def destinations( default = nil )
501
+ ret = []
502
+ %w( to cc bcc ).each do |nm|
503
+ if h = @header[nm]
504
+ h.addrs.each {|i| ret.push i.address }
505
+ end
506
+ end
507
+ ret.empty? ? default : ret
508
+ end
509
+
510
+ def each_destination( &block )
511
+ destinations([]).each do |i|
512
+ if Address === i
513
+ yield i
514
+ else
515
+ i.each(&block)
516
+ end
517
+ end
518
+ end
519
+
520
+ alias each_dest each_destination
521
+
522
+ def reply_addresses( default = nil )
523
+ reply_to_addrs(nil) or from_addrs(nil) or default
524
+ end
525
+
526
+ def error_reply_addresses( default = nil )
527
+ if s = sender(nil)
528
+ [s]
529
+ else
530
+ from_addrs(default)
531
+ end
532
+ end
533
+
534
+ def multipart?
535
+ main_type('').downcase == 'multipart'
536
+ end
537
+
538
+ end # class Mail
539
+
540
+ end # module TMail