mail 2.4.4 → 2.5.5

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.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +140 -1
  3. data/CONTRIBUTING.md +4 -4
  4. data/Gemfile +14 -8
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +24 -23
  7. data/Rakefile +3 -22
  8. data/lib/VERSION +2 -2
  9. data/lib/load_parsers.rb +35 -0
  10. data/lib/mail/attachments_list.rb +2 -2
  11. data/lib/mail/body.rb +5 -5
  12. data/lib/mail/check_delivery_params.rb +57 -0
  13. data/lib/mail/configuration.rb +1 -1
  14. data/lib/mail/core_extensions/nil.rb +4 -2
  15. data/lib/mail/core_extensions/object.rb +8 -8
  16. data/lib/mail/core_extensions/smtp.rb +12 -13
  17. data/lib/mail/core_extensions/string.rb +4 -4
  18. data/lib/mail/elements/address.rb +13 -5
  19. data/lib/mail/elements/envelope_from_element.rb +15 -2
  20. data/lib/mail/elements.rb +12 -12
  21. data/lib/mail/encodings/quoted_printable.rb +4 -3
  22. data/lib/mail/encodings.rb +66 -35
  23. data/lib/mail/field.rb +76 -99
  24. data/lib/mail/fields/bcc_field.rb +2 -2
  25. data/lib/mail/fields/cc_field.rb +2 -2
  26. data/lib/mail/fields/comments_field.rb +1 -1
  27. data/lib/mail/fields/common/common_address.rb +19 -4
  28. data/lib/mail/fields/common/common_field.rb +8 -2
  29. data/lib/mail/fields/common/common_message_id.rb +9 -5
  30. data/lib/mail/fields/content_disposition_field.rb +1 -0
  31. data/lib/mail/fields/content_id_field.rb +1 -2
  32. data/lib/mail/fields/content_transfer_encoding_field.rb +2 -2
  33. data/lib/mail/fields/content_type_field.rb +5 -2
  34. data/lib/mail/fields/date_field.rb +14 -14
  35. data/lib/mail/fields/from_field.rb +2 -2
  36. data/lib/mail/fields/in_reply_to_field.rb +2 -1
  37. data/lib/mail/fields/keywords_field.rb +1 -1
  38. data/lib/mail/fields/message_id_field.rb +2 -3
  39. data/lib/mail/fields/references_field.rb +2 -1
  40. data/lib/mail/fields/reply_to_field.rb +2 -2
  41. data/lib/mail/fields/resent_bcc_field.rb +2 -2
  42. data/lib/mail/fields/resent_cc_field.rb +2 -2
  43. data/lib/mail/fields/resent_from_field.rb +2 -2
  44. data/lib/mail/fields/resent_sender_field.rb +2 -2
  45. data/lib/mail/fields/resent_to_field.rb +2 -2
  46. data/lib/mail/fields/sender_field.rb +7 -7
  47. data/lib/mail/fields/to_field.rb +2 -2
  48. data/lib/mail/fields/unstructured_field.rb +34 -27
  49. data/lib/mail/fields.rb +32 -32
  50. data/lib/mail/header.rb +37 -14
  51. data/lib/mail/message.rb +140 -45
  52. data/lib/mail/multibyte/chars.rb +4 -4
  53. data/lib/mail/multibyte/unicode.rb +8 -0
  54. data/lib/mail/network/delivery_methods/exim.rb +6 -11
  55. data/lib/mail/network/delivery_methods/file_delivery.rb +7 -6
  56. data/lib/mail/network/delivery_methods/sendmail.rb +40 -11
  57. data/lib/mail/network/delivery_methods/smtp.rb +33 -47
  58. data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -24
  59. data/lib/mail/network/delivery_methods/test_mailer.rb +9 -8
  60. data/lib/mail/network/retriever_methods/imap.rb +14 -6
  61. data/lib/mail/network/retriever_methods/pop3.rb +2 -2
  62. data/lib/mail/network/retriever_methods/test_retriever.rb +11 -15
  63. data/lib/mail/network.rb +9 -9
  64. data/lib/mail/parsers/content_transfer_encoding.rb +81 -42
  65. data/lib/mail/parsers/content_transfer_encoding.treetop +4 -6
  66. data/lib/mail/parsers/content_type.rb +16 -12
  67. data/lib/mail/parsers/content_type.treetop +2 -2
  68. data/lib/mail/parsers/rfc2045.rb +12 -55
  69. data/lib/mail/parsers/rfc2045.treetop +1 -2
  70. data/lib/mail/parsers/rfc2822.rb +127 -71
  71. data/lib/mail/parsers/rfc2822.treetop +22 -24
  72. data/lib/mail/part.rb +6 -2
  73. data/lib/mail/parts_list.rb +1 -1
  74. data/lib/mail/patterns.rb +1 -1
  75. data/lib/mail/utilities.rb +25 -17
  76. data/lib/mail/values/unicode_tables.dat +0 -0
  77. data/lib/mail/version_specific/ruby_1_8.rb +23 -2
  78. data/lib/mail/version_specific/ruby_1_9.rb +55 -21
  79. data/lib/mail.rb +18 -18
  80. metadata +89 -37
  81. data/Gemfile.lock +0 -36
  82. data/lib/mail/core_extensions/shell_escape.rb +0 -56
@@ -216,64 +216,21 @@ module Mail
216
216
  return cached
217
217
  end
218
218
 
219
- i0 = index
220
- if has_terminal?("7bit", false, index)
221
- r1 = instantiate_node(SyntaxNode,input, index...(index + 4))
222
- @index += 4
223
- else
224
- terminal_parse_failure("7bit")
225
- r1 = nil
226
- end
227
- if r1
228
- r0 = r1
229
- else
230
- if has_terminal?("8bit", false, index)
231
- r2 = instantiate_node(SyntaxNode,input, index...(index + 4))
232
- @index += 4
233
- else
234
- terminal_parse_failure("8bit")
235
- r2 = nil
236
- end
237
- if r2
238
- r0 = r2
219
+ s0, i0 = [], index
220
+ loop do
221
+ r1 = _nt_token
222
+ if r1
223
+ s0 << r1
239
224
  else
240
- if has_terminal?("binary", false, index)
241
- r3 = instantiate_node(SyntaxNode,input, index...(index + 6))
242
- @index += 6
243
- else
244
- terminal_parse_failure("binary")
245
- r3 = nil
246
- end
247
- if r3
248
- r0 = r3
249
- else
250
- if has_terminal?("quoted-printable", false, index)
251
- r4 = instantiate_node(SyntaxNode,input, index...(index + 16))
252
- @index += 16
253
- else
254
- terminal_parse_failure("quoted-printable")
255
- r4 = nil
256
- end
257
- if r4
258
- r0 = r4
259
- else
260
- if has_terminal?("base64", false, index)
261
- r5 = instantiate_node(SyntaxNode,input, index...(index + 6))
262
- @index += 6
263
- else
264
- terminal_parse_failure("base64")
265
- r5 = nil
266
- end
267
- if r5
268
- r0 = r5
269
- else
270
- @index = i0
271
- r0 = nil
272
- end
273
- end
274
- end
225
+ break
275
226
  end
276
227
  end
228
+ if s0.empty?
229
+ @index = i0
230
+ r0 = nil
231
+ else
232
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
233
+ end
277
234
 
278
235
  node_cache[:ietf_token][start_index] = r0
279
236
 
@@ -8,8 +8,7 @@ module Mail
8
8
  end
9
9
 
10
10
  rule ietf_token
11
- "7bit" / "8bit" / "binary" /
12
- "quoted-printable" / "base64"
11
+ token+
13
12
  end
14
13
 
15
14
  rule custom_x_token
@@ -1321,6 +1321,7 @@ module Mail
1321
1321
  def domain_text
1322
1322
  elements[1]
1323
1323
  end
1324
+
1324
1325
  end
1325
1326
 
1326
1327
  def _nt_local_dot_atom_text
@@ -1357,6 +1358,25 @@ module Mail
1357
1358
  if r2
1358
1359
  r4 = _nt_domain_text
1359
1360
  s1 << r4
1361
+ if r4
1362
+ s5, i5 = [], index
1363
+ loop do
1364
+ if has_terminal?(".", false, index)
1365
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
1366
+ @index += 1
1367
+ else
1368
+ terminal_parse_failure(".")
1369
+ r6 = nil
1370
+ end
1371
+ if r6
1372
+ s5 << r6
1373
+ else
1374
+ break
1375
+ end
1376
+ end
1377
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
1378
+ s1 << r5
1379
+ end
1360
1380
  end
1361
1381
  if s1.last
1362
1382
  r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
@@ -2369,12 +2389,7 @@ module Mail
2369
2389
  break
2370
2390
  end
2371
2391
  end
2372
- if s4.empty?
2373
- @index = i4
2374
- r4 = nil
2375
- else
2376
- r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
2377
- end
2392
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
2378
2393
  s0 << r4
2379
2394
  if r4
2380
2395
  r10 = _nt_FWS
@@ -2714,17 +2729,35 @@ module Mail
2714
2729
  s3, i3 = [], index
2715
2730
  loop do
2716
2731
  i4, s4 = index, []
2732
+ i5 = index
2717
2733
  if has_terminal?(",", false, index)
2718
- r5 = instantiate_node(SyntaxNode,input, index...(index + 1))
2734
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
2719
2735
  @index += 1
2720
2736
  else
2721
2737
  terminal_parse_failure(",")
2722
- r5 = nil
2738
+ r6 = nil
2739
+ end
2740
+ if r6
2741
+ r5 = r6
2742
+ else
2743
+ if has_terminal?(";", false, index)
2744
+ r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
2745
+ @index += 1
2746
+ else
2747
+ terminal_parse_failure(";")
2748
+ r7 = nil
2749
+ end
2750
+ if r7
2751
+ r5 = r7
2752
+ else
2753
+ @index = i5
2754
+ r5 = nil
2755
+ end
2723
2756
  end
2724
2757
  s4 << r5
2725
2758
  if r5
2726
- r6 = _nt_mailbox
2727
- s4 << r6
2759
+ r8 = _nt_mailbox
2760
+ s4 << r8
2728
2761
  end
2729
2762
  if s4.last
2730
2763
  r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
@@ -2752,9 +2785,9 @@ module Mail
2752
2785
  if r1
2753
2786
  r0 = r1
2754
2787
  else
2755
- r7 = _nt_obs_mbox_list
2756
- if r7
2757
- r0 = r7
2788
+ r9 = _nt_obs_mbox_list
2789
+ if r9
2790
+ r0 = r9
2758
2791
  else
2759
2792
  @index = i0
2760
2793
  r0 = nil
@@ -2766,6 +2799,23 @@ module Mail
2766
2799
  r0
2767
2800
  end
2768
2801
 
2802
+ module Mailbox0
2803
+ def dig_comments(comments, elements)
2804
+ elements.each { |elem|
2805
+ if elem.respond_to?(:comment)
2806
+ comments << elem.comment
2807
+ end
2808
+ dig_comments(comments, elem.elements) if elem.elements
2809
+ }
2810
+ end
2811
+
2812
+ def comments
2813
+ comments = []
2814
+ dig_comments(comments, elements)
2815
+ comments
2816
+ end
2817
+ end
2818
+
2769
2819
  def _nt_mailbox
2770
2820
  start_index = index
2771
2821
  if node_cache[:mailbox].has_key?(index)
@@ -2781,10 +2831,12 @@ module Mail
2781
2831
  r1 = _nt_name_addr
2782
2832
  if r1
2783
2833
  r0 = r1
2834
+ r0.extend(Mailbox0)
2784
2835
  else
2785
2836
  r2 = _nt_addr_spec
2786
2837
  if r2
2787
2838
  r0 = r2
2839
+ r0.extend(Mailbox0)
2788
2840
  else
2789
2841
  @index = i0
2790
2842
  r0 = nil
@@ -2814,24 +2866,6 @@ module Mail
2814
2866
  end
2815
2867
  end
2816
2868
 
2817
- module Address1
2818
-
2819
- def dig_comments(comments, elements)
2820
- elements.each { |elem|
2821
- if elem.respond_to?(:comment)
2822
- comments << elem.comment
2823
- end
2824
- dig_comments(comments, elem.elements) if elem.elements
2825
- }
2826
- end
2827
-
2828
- def comments
2829
- comments = []
2830
- dig_comments(comments, elements)
2831
- comments
2832
- end
2833
- end
2834
-
2835
2869
  def _nt_address
2836
2870
  start_index = index
2837
2871
  if node_cache[:address].has_key?(index)
@@ -2850,7 +2884,6 @@ module Mail
2850
2884
  r0 = r1
2851
2885
  else
2852
2886
  r2 = _nt_mailbox
2853
- r2.extend(Address1)
2854
2887
  if r2
2855
2888
  r0 = r2
2856
2889
  else
@@ -2915,34 +2948,52 @@ module Mail
2915
2948
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
2916
2949
  s4 << r5
2917
2950
  if r5
2951
+ i7 = index
2918
2952
  if has_terminal?(",", false, index)
2919
- r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
2953
+ r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
2920
2954
  @index += 1
2921
2955
  else
2922
2956
  terminal_parse_failure(",")
2923
- r7 = nil
2957
+ r8 = nil
2958
+ end
2959
+ if r8
2960
+ r7 = r8
2961
+ else
2962
+ if has_terminal?(";", false, index)
2963
+ r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
2964
+ @index += 1
2965
+ else
2966
+ terminal_parse_failure(";")
2967
+ r9 = nil
2968
+ end
2969
+ if r9
2970
+ r7 = r9
2971
+ else
2972
+ @index = i7
2973
+ r7 = nil
2974
+ end
2924
2975
  end
2925
2976
  s4 << r7
2926
2977
  if r7
2927
- s8, i8 = [], index
2978
+ s10, i10 = [], index
2928
2979
  loop do
2929
- r9 = _nt_FWS
2930
- if r9
2931
- s8 << r9
2980
+ r11 = _nt_FWS
2981
+ if r11
2982
+ s10 << r11
2932
2983
  else
2933
2984
  break
2934
2985
  end
2935
2986
  end
2936
- r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
2937
- s4 << r8
2938
- if r8
2939
- r11 = _nt_address
2940
- if r11
2941
- r10 = r11
2987
+ r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
2988
+ s4 << r10
2989
+ if r10
2990
+ r13 = _nt_address
2991
+ if r13
2992
+ r12 = r13
2942
2993
  else
2943
- r10 = instantiate_node(SyntaxNode,input, index...index)
2994
+ r12 = instantiate_node(SyntaxNode,input, index...index)
2944
2995
  end
2945
- s4 << r10
2996
+ s4 << r12
2946
2997
  end
2947
2998
  end
2948
2999
  end
@@ -4243,41 +4294,46 @@ module Mail
4243
4294
  end
4244
4295
  s0 << r1
4245
4296
  if r1
4246
- i3, s3 = index, []
4247
- r4 = _nt_name_val_pair
4248
- s3 << r4
4249
- if r4
4250
- s5, i5 = [], index
4297
+ i4, s4 = index, []
4298
+ r5 = _nt_name_val_pair
4299
+ s4 << r5
4300
+ if r5
4301
+ s6, i6 = [], index
4251
4302
  loop do
4252
- i6, s6 = index, []
4253
- r7 = _nt_CFWS
4254
- s6 << r7
4255
- if r7
4256
- r8 = _nt_name_val_pair
4257
- s6 << r8
4303
+ i7, s7 = index, []
4304
+ r8 = _nt_CFWS
4305
+ s7 << r8
4306
+ if r8
4307
+ r9 = _nt_name_val_pair
4308
+ s7 << r9
4258
4309
  end
4259
- if s6.last
4260
- r6 = instantiate_node(SyntaxNode,input, i6...index, s6)
4261
- r6.extend(NameValList0)
4310
+ if s7.last
4311
+ r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
4312
+ r7.extend(NameValList0)
4262
4313
  else
4263
- @index = i6
4264
- r6 = nil
4314
+ @index = i7
4315
+ r7 = nil
4265
4316
  end
4266
- if r6
4267
- s5 << r6
4317
+ if r7
4318
+ s6 << r7
4268
4319
  else
4269
4320
  break
4270
4321
  end
4271
4322
  end
4272
- r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
4273
- s3 << r5
4323
+ r6 = instantiate_node(SyntaxNode,input, i6...index, s6)
4324
+ s4 << r6
4274
4325
  end
4275
- if s3.last
4276
- r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
4277
- r3.extend(NameValList1)
4326
+ if s4.last
4327
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
4328
+ r4.extend(NameValList1)
4278
4329
  else
4279
- @index = i3
4280
- r3 = nil
4330
+ @index = i4
4331
+ r4 = nil
4332
+ end
4333
+ if r4
4334
+ r3 = r4
4335
+ else
4336
+ r3 = instantiate_node(SyntaxNode,input, index...index)
4281
4337
  end
4282
4338
  s0 << r3
4283
4339
  end
@@ -110,7 +110,7 @@ module Mail
110
110
  end
111
111
 
112
112
  rule local_dot_atom_text
113
- ("."? domain_text)+
113
+ ("."* domain_text "."*)+
114
114
  end
115
115
 
116
116
  rule domain_text
@@ -184,7 +184,7 @@ module Mail
184
184
  end
185
185
 
186
186
  rule quoted_string
187
- CFWS? DQUOTE quoted_content:(FWS? qcontent)+ FWS? DQUOTE CFWS?
187
+ CFWS? DQUOTE quoted_content:(FWS? qcontent)* FWS? DQUOTE CFWS?
188
188
  end
189
189
 
190
190
  rule qcontent
@@ -218,11 +218,26 @@ module Mail
218
218
  end
219
219
 
220
220
  rule mailbox_list
221
- (first_addr:mailbox other_addr:("," addr_value:mailbox)*) / obs_mbox_list
221
+ (first_addr:mailbox other_addr:(("," / ";") addr_value:mailbox)*) / obs_mbox_list
222
222
  end
223
223
 
224
224
  rule mailbox
225
- name_addr / addr_spec
225
+ (name_addr / addr_spec) {
226
+ def dig_comments(comments, elements)
227
+ elements.each { |elem|
228
+ if elem.respond_to?(:comment)
229
+ comments << elem.comment
230
+ end
231
+ dig_comments(comments, elem.elements) if elem.elements
232
+ }
233
+ end
234
+
235
+ def comments
236
+ comments = []
237
+ dig_comments(comments, elements)
238
+ comments
239
+ end
240
+ }
226
241
  end
227
242
 
228
243
  rule address
@@ -244,28 +259,11 @@ module Mail
244
259
  end
245
260
 
246
261
  } /
247
- mailbox {
248
-
249
- def dig_comments(comments, elements)
250
- elements.each { |elem|
251
- if elem.respond_to?(:comment)
252
- comments << elem.comment
253
- end
254
- dig_comments(comments, elem.elements) if elem.elements
255
- }
256
- end
257
-
258
- def comments
259
- comments = []
260
- dig_comments(comments, elements)
261
- comments
262
- end
263
-
264
- }
262
+ mailbox
265
263
  end
266
264
 
267
265
  rule address_list
268
- first_addr:address? other_addr:(FWS* "," FWS* addr_value:address?)*
266
+ first_addr:address? other_addr:(FWS* ("," / ";") FWS* addr_value:address?)*
269
267
  end
270
268
 
271
269
  rule date_time
@@ -340,7 +338,7 @@ module Mail
340
338
  end
341
339
 
342
340
  rule name_val_list
343
- (CFWS)? (name_val_pair (CFWS name_val_pair)*)
341
+ (CFWS)? (name_val_pair (CFWS name_val_pair)*)?
344
342
  end
345
343
 
346
344
  rule name_val_pair
data/lib/mail/part.rb CHANGED
@@ -38,8 +38,12 @@ module Mail
38
38
  end
39
39
 
40
40
  def add_required_fields
41
- add_content_id unless has_content_id?
42
41
  super
42
+ add_content_id if !has_content_id? && inline?
43
+ end
44
+
45
+ def add_required_message_fields
46
+ # Override so we don't add Date, MIME-Version, or Message-ID.
43
47
  end
44
48
 
45
49
  def delivery_status_report_part?
@@ -113,4 +117,4 @@ module Mail
113
117
 
114
118
  end
115
119
 
116
- end
120
+ end
@@ -44,7 +44,7 @@ module Mail
44
44
  private
45
45
 
46
46
  def get_order_value(part, order)
47
- if part.respond_to?(:content_type)
47
+ if part.respond_to?(:content_type) && !part[:content_type].nil?
48
48
  order.index(part[:content_type].string.downcase) || 10000
49
49
  else
50
50
  10000
data/lib/mail/patterns.rb CHANGED
@@ -8,7 +8,6 @@ module Mail
8
8
 
9
9
  aspecial = %Q|()<>[]:;@\\,."| # RFC5322
10
10
  tspecial = %Q|()<>@,;:\\"/[]?=| # RFC2045
11
- lwsp = %Q| \t\r\n|
12
11
  sp = %Q| |
13
12
  control = %Q|\x00-\x1f\x7f-\xff|
14
13
 
@@ -23,6 +22,7 @@ module Mail
23
22
  FIELD_NAME = /[#{field_name}]+/
24
23
  FIELD_BODY = /.+/
25
24
  FIELD_LINE = /^[#{field_name}]+:\s*.+$/
25
+ FIELD_SPLIT = /^(#{FIELD_NAME})\s*:\s*(#{FIELD_BODY})?$/
26
26
  HEADER_LINE = /^([#{field_name}]+:\s*.+)$/
27
27
 
28
28
  QP_UNSAFE = /[^#{qp_safe}]/
@@ -41,28 +41,36 @@ module Mail
41
41
  token_safe?( str ) ? str : dquote(str)
42
42
  end
43
43
 
44
- # Wraps supplied string in double quotes unless it is already wrapped.
45
- #
46
- # Additionally will escape any double quotation marks in the string with a single
47
- # backslash in front of the '"' character.
44
+ # Wraps supplied string in double quotes and applies \-escaping as necessary,
45
+ # unless it is already wrapped.
46
+ #
47
+ # Example:
48
+ #
49
+ # string = 'This is a string'
50
+ # dquote(string) #=> '"This is a string"'
51
+ #
52
+ # string = 'This is "a string"'
53
+ # dquote(string #=> '"This is \"a string\"'
48
54
  def dquote( str )
49
- match = str.match(/^"(.*)?"$/)
50
- str = match[1] if match
51
- # First remove all escaped double quotes:
52
- str = str.gsub(/\\"/, '"')
53
- # Then wrap and re-escape all double quotes
54
- '"' + str.gsub(/["]/n) {|s| '\\' + s } + '"'
55
+ '"' + unquote(str).gsub(/[\\"]/n) {|s| '\\' + s } + '"'
55
56
  end
56
-
57
- # Unwraps supplied string from inside double quotes.
58
- #
57
+
58
+ # Unwraps supplied string from inside double quotes and
59
+ # removes any \-escaping.
60
+ #
59
61
  # Example:
60
- #
62
+ #
61
63
  # string = '"This is a string"'
62
64
  # unquote(string) #=> 'This is a string'
65
+ #
66
+ # string = '"This is \"a string\""'
67
+ # unqoute(string) #=> 'This is "a string"'
63
68
  def unquote( str )
64
- match = str.match(/^"(.*?)"$/)
65
- match ? match[1] : str
69
+ if str =~ /^"(.*?)"$/
70
+ $1.gsub(/\\(.)/, '\1')
71
+ else
72
+ str
73
+ end
66
74
  end
67
75
 
68
76
  # Wraps a string in parenthesis and escapes any that are in the string itself.
@@ -135,7 +143,7 @@ module Mail
135
143
  # obj1 = :this_IS_an_object
136
144
  # match_to_s( obj1, obj2 ) #=> true
137
145
  def match_to_s( obj1, obj2 )
138
- obj1.to_s.downcase == obj2.to_s.downcase
146
+ obj1.to_s.casecmp(obj2.to_s) == 0
139
147
  end
140
148
 
141
149
  # Capitalizes a string that is joined by hyphens correctly.
Binary file
@@ -3,6 +3,7 @@
3
3
  module Mail
4
4
  class Ruby18
5
5
  require 'base64'
6
+ require 'iconv'
6
7
 
7
8
  # Escapes any parenthesis in a string that are unescaped. This can't
8
9
  # use the Ruby 1.9.1 regexp feature of negative look behind so we have
@@ -57,7 +58,7 @@ module Mail
57
58
  # Ruby 1.8 requires an encoding to work
58
59
  raise ArgumentError, "Must supply an encoding" if encoding.nil?
59
60
  encoding = encoding.to_s.upcase.gsub('_', '-')
60
- [Encodings::Base64.encode(str), encoding]
61
+ [Encodings::Base64.encode(str), fix_encoding(encoding)]
61
62
  end
62
63
 
63
64
  def Ruby18.b_value_decode(str)
@@ -65,6 +66,7 @@ module Mail
65
66
  if match
66
67
  encoding = match[1]
67
68
  str = Ruby18.decode_base64(match[2])
69
+ str = Iconv.conv('UTF-8//IGNORE', fix_encoding(encoding), str)
68
70
  end
69
71
  str
70
72
  end
@@ -80,7 +82,11 @@ module Mail
80
82
  match = str.match(/\=\?(.+)?\?[Qq]\?(.+)?\?\=/m)
81
83
  if match
82
84
  encoding = match[1]
83
- str = Encodings::QuotedPrintable.decode(match[2].gsub(/_/, '=20'))
85
+ string = match[2].gsub(/_/, '=20')
86
+ # Remove trailing = if it exists in a Q encoding
87
+ string = string.sub(/\=$/, '')
88
+ str = Encodings::QuotedPrintable.decode(string)
89
+ str = Iconv.conv('UTF-8//IGNORE', fix_encoding(encoding), str)
84
90
  end
85
91
  str
86
92
  end
@@ -94,5 +100,20 @@ module Mail
94
100
  language = Configuration.instance.param_encode_language
95
101
  "#{encoding}'#{language}'#{URI.escape(str)}"
96
102
  end
103
+
104
+ private
105
+
106
+ def Ruby18.fix_encoding(encoding)
107
+ case encoding.upcase
108
+ when 'UTF8'
109
+ 'UTF-8'
110
+ when 'UTF16', 'UTF-16'
111
+ 'UTF-16BE'
112
+ when 'UTF32', 'UTF-32'
113
+ 'UTF-32BE'
114
+ else
115
+ encoding
116
+ end
117
+ end
97
118
  end
98
119
  end