lonbaker-tmail 1.2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/CHANGES +74 -0
  2. data/LICENSE +21 -0
  3. data/NOTES +7 -0
  4. data/README +169 -0
  5. data/ext/Makefile +20 -0
  6. data/ext/tmailscanner/tmail/MANIFEST +4 -0
  7. data/ext/tmailscanner/tmail/depend +1 -0
  8. data/ext/tmailscanner/tmail/extconf.rb +33 -0
  9. data/ext/tmailscanner/tmail/tmailscanner.c +583 -0
  10. data/lib/tmail.rb +5 -0
  11. data/lib/tmail/Makefile +18 -0
  12. data/lib/tmail/address.rb +426 -0
  13. data/lib/tmail/attachments.rb +46 -0
  14. data/lib/tmail/base64.rb +46 -0
  15. data/lib/tmail/compat.rb +41 -0
  16. data/lib/tmail/config.rb +67 -0
  17. data/lib/tmail/core_extensions.rb +63 -0
  18. data/lib/tmail/encode.rb +590 -0
  19. data/lib/tmail/header.rb +962 -0
  20. data/lib/tmail/index.rb +9 -0
  21. data/lib/tmail/interface.rb +1130 -0
  22. data/lib/tmail/loader.rb +3 -0
  23. data/lib/tmail/mail.rb +580 -0
  24. data/lib/tmail/mailbox.rb +496 -0
  25. data/lib/tmail/main.rb +6 -0
  26. data/lib/tmail/mbox.rb +3 -0
  27. data/lib/tmail/net.rb +248 -0
  28. data/lib/tmail/obsolete.rb +132 -0
  29. data/lib/tmail/parser.rb +1476 -0
  30. data/lib/tmail/parser.y +381 -0
  31. data/lib/tmail/port.rb +379 -0
  32. data/lib/tmail/quoting.rb +118 -0
  33. data/lib/tmail/require_arch.rb +58 -0
  34. data/lib/tmail/scanner.rb +49 -0
  35. data/lib/tmail/scanner_r.rb +261 -0
  36. data/lib/tmail/stringio.rb +280 -0
  37. data/lib/tmail/utils.rb +351 -0
  38. data/lib/tmail/version.rb +39 -0
  39. data/meta/MANIFEST +128 -0
  40. data/meta/project.yaml +30 -0
  41. data/meta/unixname +1 -0
  42. data/sample/bench_base64.rb +48 -0
  43. data/sample/data/multipart +23 -0
  44. data/sample/data/normal +29 -0
  45. data/sample/data/sendtest +5 -0
  46. data/sample/data/simple +14 -0
  47. data/sample/data/test +27 -0
  48. data/sample/extract-attachements.rb +33 -0
  49. data/sample/from-check.rb +26 -0
  50. data/sample/multipart.rb +26 -0
  51. data/sample/parse-bench.rb +68 -0
  52. data/sample/parse-test.rb +19 -0
  53. data/sample/sendmail.rb +94 -0
  54. data/test/extctrl.rb +6 -0
  55. data/test/fixtures/mailbox +414 -0
  56. data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
  57. data/test/fixtures/mailbox_without_from +11 -0
  58. data/test/fixtures/mailbox_without_return_path +12 -0
  59. data/test/fixtures/raw_base64_decoded_string +0 -0
  60. data/test/fixtures/raw_base64_email +83 -0
  61. data/test/fixtures/raw_base64_encoded_string +1 -0
  62. data/test/fixtures/raw_email +14 -0
  63. data/test/fixtures/raw_email10 +20 -0
  64. data/test/fixtures/raw_email11 +34 -0
  65. data/test/fixtures/raw_email12 +32 -0
  66. data/test/fixtures/raw_email13 +29 -0
  67. data/test/fixtures/raw_email2 +114 -0
  68. data/test/fixtures/raw_email3 +70 -0
  69. data/test/fixtures/raw_email4 +59 -0
  70. data/test/fixtures/raw_email5 +19 -0
  71. data/test/fixtures/raw_email6 +20 -0
  72. data/test/fixtures/raw_email7 +66 -0
  73. data/test/fixtures/raw_email8 +47 -0
  74. data/test/fixtures/raw_email9 +28 -0
  75. data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
  76. data/test/fixtures/raw_email_reply +32 -0
  77. data/test/fixtures/raw_email_simple +11 -0
  78. data/test/fixtures/raw_email_with_bad_date +48 -0
  79. data/test/fixtures/raw_email_with_illegal_boundary +58 -0
  80. data/test/fixtures/raw_email_with_multipart_mixed_quoted_boundary +50 -0
  81. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  82. data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
  83. data/test/fixtures/raw_email_with_quoted_illegal_boundary +58 -0
  84. data/test/kcode.rb +14 -0
  85. data/test/test_address.rb +1211 -0
  86. data/test/test_attachments.rb +60 -0
  87. data/test/test_base64.rb +64 -0
  88. data/test/test_encode.rb +85 -0
  89. data/test/test_header.rb +969 -0
  90. data/test/test_helper.rb +9 -0
  91. data/test/test_mail.rb +753 -0
  92. data/test/test_mbox.rb +184 -0
  93. data/test/test_port.rb +436 -0
  94. data/test/test_quote.rb +98 -0
  95. data/test/test_scanner.rb +209 -0
  96. data/test/test_utils.rb +36 -0
  97. metadata +159 -0
@@ -0,0 +1,9 @@
1
+ # Add in the local library for the load path so we get that before any possible
2
+ # gem that is already installed.
3
+ require 'stringio'
4
+ $:.unshift File.dirname(__FILE__) + "/../lib"
5
+ $:.unshift File.dirname(__FILE__) + "/../lib/tmail"
6
+ require 'test/unit'
7
+ require 'extctrl'
8
+ require 'test/unit'
9
+ require 'tmail'
@@ -0,0 +1,753 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'test_helper'
3
+ require 'tmail'
4
+ require 'kcode'
5
+ require 'time'
6
+
7
+ class TestMail < Test::Unit::TestCase
8
+ include TMail::TextUtils
9
+
10
+ def setup
11
+ @mail = TMail::Mail.new
12
+ end
13
+
14
+ def lf( str )
15
+ str.gsub(/\n|\r\n|\r/) { "\n" }
16
+ end
17
+
18
+ def crlf( str )
19
+ str.gsub(/\n|\r\n|\r/) { "\r\n" }
20
+ end
21
+
22
+ def test_MIME
23
+ # FIXME: test more.
24
+
25
+ kcode('EUC') {
26
+ mail = TMail::Mail.parse('From: hoge@example.jp (=?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=)')
27
+ assert_not_nil mail['From']
28
+
29
+ expected = "\245\306\245\271\245\310"
30
+ if expected.respond_to? :force_encoding
31
+ expected.force_encoding(mail['From'].comments.first.encoding)
32
+ end
33
+ assert_equal [expected], mail['From'].comments
34
+
35
+ expected = "From: hoge@example.jp (\245\306\245\271\245\310)\n\n"
36
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
37
+ assert_equal expected, mail.to_s
38
+ assert_equal expected, mail.decoded
39
+
40
+ expected = "From: hoge@example.jp (=?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=)\r\n\r\n"
41
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
42
+ assert_equal expected, mail.encoded
43
+ }
44
+ end
45
+
46
+ def test_to_s
47
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900').strftime("%a,%e %b %Y %H:%M:%S %z")
48
+ str =<<EOS
49
+ Date: #{time}
50
+ To: Minero Aoki <aamine@loveruby.net>
51
+ Subject: This is test message.
52
+
53
+ This is body.
54
+ EOS
55
+ str = crlf(str)
56
+ m = TMail::Mail.parse(str)
57
+ # strip to avoid error by body's line terminator.
58
+ assert_equal lf(str).strip, m.decoded.strip
59
+ assert_equal crlf(str).strip, m.encoded.strip
60
+ end
61
+
62
+ def test__empty_return_path
63
+ str = "Return-Path: <>\r\n\r\n"
64
+ assert_equal str, TMail::Mail.parse(str).encoded
65
+ end
66
+
67
+ def test_date
68
+ t = Time.now
69
+ @mail.date = t
70
+ assert_equal t.to_i, @mail.date.to_i # avoid usec comparison
71
+ assert_equal time2str(t), @mail['date'].to_s
72
+
73
+ str = "Date: #{time2str(t)}\n\n"
74
+ assert_equal str, TMail::Mail.parse(str).to_s
75
+ end
76
+
77
+ def test_strftime
78
+ t = Time.now
79
+ fmt = '%A%a%B%b%c%d%H%I%j%M%m%p%S%U%W%w%X%x%Y%y%Z%%'
80
+ @mail.date = t
81
+ assert_equal t.strftime(fmt), @mail.strftime(fmt)
82
+ end
83
+
84
+ def test_to
85
+ addr = 'Minero Aoki <aamine@loveruby.net>'
86
+ @mail.to = addr
87
+ assert_equal 1, @mail['to'].addrs.size
88
+ assert_equal 'aamine@loveruby.net', @mail['to'].addrs[0].spec
89
+ assert_equal 'Minero Aoki', @mail['to'].addrs[0].phrase
90
+
91
+ a = @mail.to_addrs
92
+ assert_equal 1, a.size
93
+ assert_equal 'aamine@loveruby.net', a[0].spec
94
+ assert_equal 'Minero Aoki', a[0].phrase
95
+
96
+ a = @mail.to
97
+ assert_equal 1, a.size
98
+ assert_equal 'aamine@loveruby.net', a[0]
99
+
100
+ addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
101
+ @mail.to_addrs = addr
102
+ assert_equal 1, @mail['to'].addrs.size
103
+ assert_equal 'aamine@loveruby.net', @mail['to'].addrs[0].spec
104
+ assert_equal 'Minero Aoki', @mail['to'].addrs[0].phrase
105
+
106
+ a = @mail.to_addrs
107
+ assert_equal 1, a.size
108
+ assert_equal 'aamine@loveruby.net', a[0].spec
109
+ assert_equal 'Minero Aoki', a[0].phrase
110
+
111
+ a = @mail.to
112
+ assert_equal 1, a.size
113
+ assert_equal 'aamine@loveruby.net', a[0]
114
+
115
+
116
+ @mail.to = ''
117
+ assert_equal nil, @mail.to
118
+ assert_equal 'DEFAULT VALUE', @mail.to('DEFAULT VALUE')
119
+
120
+ @mail.to = 'undisclosed-recipients: ;'
121
+ a = @mail.to
122
+ assert_equal nil, @mail.to
123
+ assert_equal 'DEFAULT VALUE', @mail.to('DEFAULT VALUE')
124
+
125
+
126
+ str = "\"Aoki, Minero\" <aamine@loveruby.net>\n\n"
127
+ @mail.to_addrs = a = TMail::Address.parse(str)
128
+ assert_equal ['aamine@loveruby.net'], @mail.to
129
+ assert_equal [a], @mail.to_addrs
130
+ assert_equal '"Aoki, Minero" <aamine@loveruby.net>', @mail.to_addrs[0].to_s
131
+ assert_equal '"Aoki, Minero" <aamine@loveruby.net>', @mail['to'].to_s
132
+ end
133
+
134
+ def test_cc
135
+ addr = 'Minero Aoki <aamine@loveruby.net>'
136
+ @mail.cc = addr
137
+ assert_equal 1, @mail['cc'].addrs.size
138
+ assert_equal 'aamine@loveruby.net', @mail['cc'].addrs[0].spec
139
+ assert_equal 'Minero Aoki', @mail['cc'].addrs[0].phrase
140
+
141
+ a = @mail.cc_addrs
142
+ assert_equal 1, a.size
143
+ assert_equal 'aamine@loveruby.net', a[0].spec
144
+ assert_equal 'Minero Aoki', a[0].phrase
145
+
146
+ a = @mail.cc
147
+ assert_equal 1, a.size
148
+ assert_equal 'aamine@loveruby.net', a[0]
149
+
150
+ addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
151
+ @mail.cc_addrs = addr
152
+ assert_equal 1, @mail['cc'].addrs.size
153
+ assert_equal 'aamine@loveruby.net', @mail['cc'].addrs[0].spec
154
+ assert_equal 'Minero Aoki', @mail['cc'].addrs[0].phrase
155
+
156
+ a = @mail.cc_addrs
157
+ assert_equal 1, a.size
158
+ assert_equal 'aamine@loveruby.net', a[0].spec
159
+ assert_equal 'Minero Aoki', a[0].phrase
160
+
161
+ a = @mail.cc
162
+ assert_equal 1, a.size
163
+ assert_equal 'aamine@loveruby.net', a[0]
164
+
165
+
166
+ @mail.cc = ''
167
+ assert_equal nil, @mail.cc
168
+ assert_equal 'DEFAULT VALUE', @mail.cc('DEFAULT VALUE')
169
+
170
+ @mail.cc = 'undisclosed-recipients: ;'
171
+ a = @mail.cc
172
+ assert_equal nil, @mail.cc
173
+ assert_equal 'DEFAULT VALUE', @mail.cc('DEFAULT VALUE')
174
+ end
175
+
176
+ def test_bcc
177
+ addr = 'Minero Aoki <aamine@loveruby.net>'
178
+ @mail.bcc = addr
179
+ assert_equal 1, @mail['bcc'].addrs.size
180
+ assert_equal 'aamine@loveruby.net', @mail['bcc'].addrs[0].spec
181
+ assert_equal 'Minero Aoki', @mail['bcc'].addrs[0].phrase
182
+
183
+ a = @mail.bcc_addrs
184
+ assert_equal 1, a.size
185
+ assert_equal 'aamine@loveruby.net', a[0].spec
186
+ assert_equal 'Minero Aoki', a[0].phrase
187
+
188
+ a = @mail.bcc
189
+ assert_equal 1, a.size
190
+ assert_equal 'aamine@loveruby.net', a[0]
191
+
192
+ addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
193
+ @mail.bcc_addrs = addr
194
+ assert_equal 1, @mail['bcc'].addrs.size
195
+ assert_equal 'aamine@loveruby.net', @mail['bcc'].addrs[0].spec
196
+ assert_equal 'Minero Aoki', @mail['bcc'].addrs[0].phrase
197
+
198
+ a = @mail.bcc_addrs
199
+ assert_equal 1, a.size
200
+ assert_equal 'aamine@loveruby.net', a[0].spec
201
+ assert_equal 'Minero Aoki', a[0].phrase
202
+
203
+ a = @mail.bcc
204
+ assert_equal 1, a.size
205
+ assert_equal 'aamine@loveruby.net', a[0]
206
+
207
+
208
+ @mail.bcc = ''
209
+ assert_equal nil, @mail.bcc
210
+ assert_equal 'DEFAULT VALUE', @mail.bcc('DEFAULT VALUE')
211
+
212
+ @mail.bcc = 'undisclosed-recipients: ;'
213
+ a = @mail.bcc
214
+ assert_equal nil, @mail.bcc
215
+ assert_equal 'DEFAULT VALUE', @mail.bcc('DEFAULT VALUE')
216
+ end
217
+
218
+ def test_from
219
+ addr = 'Minero Aoki <aamine@loveruby.net>'
220
+ @mail.from = addr
221
+ assert_equal 1, @mail['from'].addrs.size
222
+ assert_equal 'aamine@loveruby.net', @mail['from'].addrs[0].spec
223
+ assert_equal 'Minero Aoki', @mail['from'].addrs[0].phrase
224
+
225
+ a = @mail.from_addrs
226
+ assert_equal 1, a.size
227
+ assert_equal 'aamine@loveruby.net', a[0].spec
228
+ assert_equal 'Minero Aoki', a[0].phrase
229
+
230
+ a = @mail.from
231
+ assert_equal 1, a.size
232
+ assert_equal 'aamine@loveruby.net', a[0]
233
+
234
+ addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
235
+ @mail.from_addrs = addr
236
+ assert_equal 1, @mail['from'].addrs.size
237
+ assert_equal 'aamine@loveruby.net', @mail['from'].addrs[0].spec
238
+ assert_equal 'Minero Aoki', @mail['from'].addrs[0].phrase
239
+
240
+ a = @mail.from_addrs
241
+ assert_equal 1, a.size
242
+ assert_equal 'aamine@loveruby.net', a[0].spec
243
+ assert_equal 'Minero Aoki', a[0].phrase
244
+
245
+ a = @mail.from
246
+ assert_equal 1, a.size
247
+ assert_equal 'aamine@loveruby.net', a[0]
248
+
249
+
250
+ @mail.from = ''
251
+ assert_equal nil, @mail.from
252
+ assert_equal 'DEFAULT VALUE', @mail.from('DEFAULT VALUE')
253
+
254
+ @mail.from = 'undisclosed-recipients: ;'
255
+ a = @mail.from
256
+ assert_equal nil, @mail.from
257
+ assert_equal 'DEFAULT VALUE', @mail.from('DEFAULT VALUE')
258
+
259
+ @mail.from = "raasdnil@gmail.com, mikel@me.com"
260
+ assert_equal 2, @mail['from'].addrs.size
261
+ assert_equal 'raasdnil@gmail.com', @mail['from'].addrs[0].spec
262
+ assert_equal 'mikel@me.com', @mail['from'].addrs[1].spec
263
+ end
264
+
265
+ def test_reply_to
266
+ addr = 'Minero Aoki <aamine@loveruby.net>'
267
+ @mail.reply_to = addr
268
+ assert_equal 1, @mail['reply-to'].addrs.size
269
+ assert_equal 'aamine@loveruby.net', @mail['reply-to'].addrs[0].spec
270
+ assert_equal 'Minero Aoki', @mail['reply-to'].addrs[0].phrase
271
+
272
+ a = @mail.reply_to_addrs
273
+ assert_equal 1, a.size
274
+ assert_equal 'aamine@loveruby.net', a[0].spec
275
+ assert_equal 'Minero Aoki', a[0].phrase
276
+
277
+ a = @mail.reply_to
278
+ assert_equal 1, a.size
279
+ assert_equal 'aamine@loveruby.net', a[0]
280
+
281
+ addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
282
+ @mail.reply_to_addrs = addr
283
+ assert_equal 1, @mail['reply-to'].addrs.size
284
+ assert_equal 'aamine@loveruby.net', @mail['reply-to'].addrs[0].spec
285
+ assert_equal 'Minero Aoki', @mail['reply-to'].addrs[0].phrase
286
+
287
+ a = @mail.reply_to_addrs
288
+ assert_equal 1, a.size
289
+ assert_equal 'aamine@loveruby.net', a[0].spec
290
+ assert_equal 'Minero Aoki', a[0].phrase
291
+
292
+ a = @mail.reply_to
293
+ assert_equal 1, a.size
294
+ assert_equal 'aamine@loveruby.net', a[0]
295
+
296
+
297
+ @mail.reply_to = ''
298
+ assert_equal nil, @mail.reply_to
299
+ assert_equal 'DEFAULT VALUE', @mail.reply_to('DEFAULT VALUE')
300
+
301
+ @mail.reply_to = 'undisclosed-recipients: ;'
302
+ a = @mail.reply_to
303
+ assert_equal nil, @mail.reply_to
304
+ assert_equal 'DEFAULT VALUE', @mail.reply_to('DEFAULT VALUE')
305
+ end
306
+
307
+ def test_reply_to_with_blank_reply_to
308
+ @mail = TMail::Mail.new
309
+ from_addr = TMail::Address.parse("Mikel Lindsaar <mikel@lindsaar.net>")
310
+ @mail.from = from_addr
311
+
312
+ # No reply_to set, should return from address
313
+ assert_equal([from_addr], @mail.reply_addresses)
314
+
315
+ # reply_to and from set, should return reply_to
316
+ reply_addr = TMail::Address.parse("Bob <bob@you.net>")
317
+ @mail.reply_to = reply_addr
318
+ assert_equal([reply_addr], @mail.reply_addresses)
319
+
320
+ # reply_to set but nil, should return from address
321
+ @mail.reply_to = nil
322
+ assert_equal([from_addr], @mail.reply_addresses)
323
+
324
+ # from and reply_to set, but nil, should return empty array
325
+ @mail.from = nil
326
+ assert_equal([], @mail.reply_addresses)
327
+ end
328
+
329
+ def do_test_address_attr( name )
330
+ addr = 'Minero Aoki <aamine@loveruby.net>'
331
+ @mail.__send__( name + '=', addr )
332
+ a = @mail.__send__( name + '_addrs' )
333
+ assert_equal 1, a.size
334
+ assert_equal 'aamine@loveruby.net', a[0].spec
335
+ assert_equal 'Minero Aoki', a[0].phrase
336
+
337
+ a = @mail.__send__( name )
338
+ assert_equal 1, a.size
339
+ assert_equal 'aamine@loveruby.net', a[0]
340
+ end
341
+
342
+ def test_subject
343
+ s = 'This is test subject!'
344
+ @mail.subject = s
345
+ assert_equal s, @mail.subject
346
+ assert_equal s, @mail['subject'].to_s
347
+ end
348
+
349
+ def test_unquote_quoted_printable_subject
350
+ msg = <<EOF
351
+ From: me@example.com
352
+ Subject: =?utf-8?Q?testing_testing_=D6=A4?=
353
+ Content-Type: text/plain; charset=iso-8859-1
354
+
355
+ The body
356
+ EOF
357
+ mail = TMail::Mail.parse(msg)
358
+ expected = "testing testing \326\244"
359
+ expected.force_encoding 'utf-8' if expected.respond_to? :force_encoding
360
+ assert_equal expected, mail.subject
361
+ assert_equal "=?utf-8?Q?testing_testing_=D6=A4?=", mail.quoted_subject
362
+ end
363
+
364
+ def test_unquote_7bit_subject
365
+ msg = <<EOF
366
+ From: me@example.com
367
+ Subject: this == working?
368
+ Content-Type: text/plain; charset=iso-8859-1
369
+
370
+ The body
371
+ EOF
372
+ mail = TMail::Mail.parse(msg)
373
+ assert_equal "this == working?", mail.subject
374
+ assert_equal "this == working?", mail.quoted_subject
375
+ end
376
+
377
+ def test_unquote_7bit_body
378
+ msg = <<EOF
379
+ From: me@example.com
380
+ Subject: subject
381
+ Content-Type: text/plain; charset=iso-8859-1
382
+ Content-Transfer-Encoding: 7bit
383
+
384
+ The=3Dbody
385
+ EOF
386
+ mail = TMail::Mail.parse(msg)
387
+ assert_equal "The=3Dbody", mail.body.strip
388
+ assert_equal "The=3Dbody", mail.quoted_body.strip
389
+ end
390
+
391
+ def test_unquote_quoted_printable_body
392
+ msg = <<EOF
393
+ From: me@example.com
394
+ Subject: subject
395
+ Content-Type: text/plain; charset=iso-8859-1
396
+ Content-Transfer-Encoding: quoted-printable
397
+
398
+ The=3Dbody
399
+ EOF
400
+ mail = TMail::Mail.parse(msg)
401
+ assert_equal "The=body", mail.body.strip
402
+ assert_equal "The=3Dbody", mail.quoted_body.strip
403
+ end
404
+
405
+ def test_unquote_base64_body
406
+ msg = <<EOF
407
+ From: me@example.com
408
+ Subject: subject
409
+ Content-Type: text/plain; charset=iso-8859-1
410
+ Content-Transfer-Encoding: base64
411
+
412
+ VGhlIGJvZHk=
413
+ EOF
414
+ mail = TMail::Mail.parse(msg)
415
+ assert_equal "The body", mail.body.strip
416
+ assert_equal "VGhlIGJvZHk=", mail.quoted_body.strip
417
+ end
418
+
419
+ def test_message_id
420
+ assert_nil @mail.message_id
421
+ assert_equal 1, @mail.message_id(1)
422
+
423
+ m = '<very.unique.identity@fully.quorified.domain.name>'
424
+ @mail.message_id = m
425
+ assert_equal m, @mail.message_id
426
+
427
+ @mail.message_id = 'this_is_my_badly_formatted_message_id'
428
+ assert_equal nil, @mail.message_id
429
+ end
430
+
431
+ def test_in_reply_to
432
+ i = '<very.unique.identity@fully.quorified.domain.name>'
433
+ @mail.in_reply_to = i
434
+ a = @mail.in_reply_to
435
+ assert_equal a.size, 1
436
+ assert_equal i, a[0]
437
+
438
+ @mail.in_reply_to = [i]
439
+ a = @mail.in_reply_to
440
+ assert_equal a.size, 1
441
+ assert_equal i, a[0]
442
+ end
443
+
444
+ def test_references
445
+ i = '<very.unique.identity@fully.quorified.domain.name>'
446
+ @mail.references = i
447
+ a = @mail.references
448
+ assert_equal a.size, 1
449
+ assert_equal i, a[0]
450
+
451
+ @mail.references = [i]
452
+ a = @mail.references
453
+ assert_equal a.size, 1
454
+ assert_equal i, a[0]
455
+ end
456
+
457
+ def test_mime_version
458
+ assert_nil @mail.mime_version
459
+ assert_equal 1, @mail.mime_version(1)
460
+
461
+ %w( 1.0 999.999 ).each do |v|
462
+ @mail.mime_version = v
463
+ assert_equal v, @mail.mime_version
464
+ end
465
+ end
466
+
467
+ def test_content_type
468
+ [ 'text/plain', 'application/binary', 'multipart/mixed' ].each do |t|
469
+ @mail.content_type = t
470
+ assert_equal t, @mail.content_type
471
+ assert_equal t.split('/',2)[0], @mail.main_type
472
+ assert_equal t.split('/',2)[1], @mail.sub_type
473
+ end
474
+
475
+ @mail.content_type = 'text/plain; charset=iso-2022-jp'
476
+ @mail.content_type = 'application/postscript'
477
+
478
+ assert_raises(ArgumentError) {
479
+ @mail.content_type = 'text'
480
+ }
481
+ end
482
+
483
+ def test_email_with_part_without_content_type
484
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email_with_mimepart_without_content_type")
485
+ mail = TMail::Mail.parse(fixture)
486
+ assert_equal(3, mail.parts.length)
487
+ end
488
+
489
+ def test_mail_to_s_with_illegal_content_type_boundary_preserves_quotes
490
+ msg = <<EOF
491
+ From: mikel@example.com
492
+ Subject: Hello
493
+ Content-Type: multipart/signed;
494
+ micalg=sha1;
495
+ boundary=Apple-Mail-42-587703407;
496
+ protocol="application/pkcs7-signature"
497
+
498
+ The body
499
+ EOF
500
+
501
+ output = <<EOF
502
+ From: mikel@example.com
503
+ Subject: Hello
504
+ #{if RUBY_VERSION < '1.9'
505
+ 'Content-Type: multipart/signed; protocol="application/pkcs7-signature"; boundary=Apple-Mail-42-587703407; micalg=sha1'
506
+ else
507
+ 'Content-Type: multipart/signed; micalg=sha1; boundary=Apple-Mail-42-587703407; protocol="application/pkcs7-signature"'
508
+ end}
509
+
510
+ The body
511
+ EOF
512
+
513
+ mail = TMail::Mail.parse(msg)
514
+ assert_equal(output, mail.to_s)
515
+ end
516
+
517
+ def test_mail_to_s_with_filename_discards_quotes_as_needed
518
+ msg = <<EOF
519
+ From: mikel@example.com
520
+ Subject: =?utf-8?Q?testing_testing_=D6=A4?=
521
+ Content-Disposition: attachment; filename="README.txt.pif"
522
+
523
+ The body
524
+ EOF
525
+ mail = TMail::Mail.parse(msg)
526
+ result =<<EOF
527
+ From: mikel@example.com
528
+ Subject: =?utf-8?Q?testing_testing_=D6=A4?=
529
+ Content-Disposition: attachment; filename=README.txt.pif
530
+
531
+ The body
532
+ EOF
533
+ assert_equal(result, mail.to_s)
534
+
535
+
536
+ msg = <<EOF
537
+ From: mikel@example.com
538
+ Subject: =?utf-8?Q?testing_testing_=D6=A4?=
539
+ Content-Disposition: attachment; filename="READ-=ME.t=xt./pi?f"
540
+
541
+ The body
542
+ EOF
543
+ mail = TMail::Mail.parse(msg)
544
+ result =<<EOF
545
+ From: mikel@example.com
546
+ Subject: =?utf-8?Q?testing_testing_=D6=A4?=
547
+ Content-Disposition: attachment; filename="READ-=ME.t=xt./pi?f"
548
+
549
+ The body
550
+ EOF
551
+ assert_equal(result, mail.to_s)
552
+
553
+ end
554
+
555
+ def test_charset
556
+ c = 'iso-2022-jp'
557
+ @mail.charset = c
558
+ assert_equal c, @mail.charset
559
+ assert_equal 'text', @mail.main_type
560
+ assert_equal 'plain', @mail.sub_type
561
+
562
+ @mail.content_type = 'application/binary'
563
+ @mail.charset = c
564
+ assert_equal c, @mail.charset
565
+ end
566
+
567
+ def test_transfer_encoding
568
+ @mail.transfer_encoding = 'base64'
569
+ assert_equal 'base64', @mail.transfer_encoding
570
+ @mail.transfer_encoding = 'BASE64'
571
+ assert_equal 'base64', @mail.transfer_encoding
572
+ @mail.content_transfer_encoding = '7bit'
573
+ assert_equal '7bit', @mail.content_transfer_encoding
574
+ @mail.encoding = 'binary'
575
+ assert_equal 'binary', @mail.encoding
576
+ end
577
+
578
+ def test_disposition
579
+ @mail['content-disposition'] = 'attachment; filename="test.rb"'
580
+ assert_equal 'attachment', @mail.disposition
581
+ assert_equal 'attachment', @mail.content_disposition
582
+ assert_equal 'test.rb', @mail.disposition_param('filename')
583
+
584
+ @mail.disposition = 'none'
585
+ assert_equal 'none', @mail.disposition
586
+ assert_nil @mail.disposition_param('filename')
587
+ assert_equal 1, @mail.disposition_param('filename', 1)
588
+
589
+ src = '=?iso-2022-jp?B?GyRCRnxLXDhsGyhCLnR4dA==?='
590
+ @mail['content-disposition'] = %Q(attachment; filename="#{src}")
591
+ ok = NKF.nkf('-m -e', src)
592
+ kcode('EUC') {
593
+ assert_equal ok, @mail.disposition_param('filename')
594
+ }
595
+ end
596
+
597
+ def test_set_disposition
598
+ @mail.set_disposition 'attachment', 'filename'=>'sample.rb'
599
+ assert_equal 'attachment', @mail.disposition
600
+ assert_equal 'sample.rb', @mail.disposition_param('filename')
601
+ end
602
+
603
+ def test_receive_attachments
604
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email2")
605
+ mail = TMail::Mail.parse(fixture)
606
+ attachment = mail.attachments.last
607
+ assert_equal "smime.p7s", attachment.original_filename
608
+ assert_equal "application/pkcs7-signature", attachment.content_type
609
+ end
610
+
611
+ def test_body_with_underscores
612
+ m = TMail::Mail.new
613
+ expected = 'something_with_underscores'
614
+ m.encoding = 'quoted-printable'
615
+ quoted_body = [expected].pack('*M')
616
+ m.body = quoted_body
617
+ assert_equal "something_with_underscores=\n", m.quoted_body
618
+ assert_equal expected, m.body
619
+ end
620
+
621
+ def test_nested_attachments_are_recognized_correctly
622
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_nested_attachment")
623
+ assert_equal 2, mail.attachments.length
624
+ assert_equal "image/png", mail.attachments.first.content_type
625
+ assert_equal 1902, mail.attachments.first.length
626
+ assert_equal "application/pkcs7-signature", mail.attachments.last.content_type
627
+ end
628
+
629
+ def test_decode_attachment_without_charset
630
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email3")
631
+ attachment = mail.attachments.last
632
+ assert_equal 1026, attachment.read.length
633
+ end
634
+
635
+ def test_attachment_using_content_location
636
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email12")
637
+ mail = TMail::Mail.parse(fixture)
638
+ assert_equal 1, mail.attachments.length
639
+ assert_equal "Photo25.jpg", mail.attachments.first.original_filename
640
+ end
641
+
642
+ def test_attachment_with_text_type
643
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email13")
644
+ mail = TMail::Mail.parse(fixture)
645
+ assert mail.has_attachments?
646
+ assert_equal 1, mail.attachments.length
647
+ assert_equal "hello.rb", mail.attachments.first.original_filename
648
+ end
649
+
650
+ def test_decode_part_without_content_type
651
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4")
652
+ mail = TMail::Mail.parse(fixture)
653
+ assert_nothing_raised { mail.body }
654
+ end
655
+
656
+ def test_decode_message_without_content_type
657
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email4")
658
+ assert_nothing_raised { mail.body }
659
+ end
660
+
661
+ def test_decode_message_with_incorrect_charset
662
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email6")
663
+ mail = TMail::Mail.parse(fixture)
664
+ assert_nothing_raised { mail.body }
665
+ end
666
+
667
+ def test_quoting_of_illegal_boundary_when_doing_mail_to_s
668
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_illegal_boundary")
669
+ assert_equal(true, mail.multipart?)
670
+ assert_equal('multipart/alternative; boundary="----=_NextPart_000_0093_01C81419.EB75E850"', mail['content-type'].to_s)
671
+ end
672
+
673
+ def test_quoted_illegal_boundary_when_doing_mail_to_s
674
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_quoted_illegal_boundary")
675
+ assert_equal(true, mail.multipart?)
676
+ assert_equal('multipart/alternative; boundary="----=_NextPart_000_0093_01C81419.EB75E850"', mail['content-type'].to_s)
677
+ end
678
+
679
+ def test_quoted_illegal_boundary_with_multipart_mixed_when_doing_mail_to_s
680
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_multipart_mixed_quoted_boundary")
681
+ assert_equal(true, mail.multipart?)
682
+ assert_equal('multipart/mixed; boundary="----=_Part_2192_32400445.1115745999735"', mail['content-type'].to_s)
683
+ end
684
+
685
+ def test_when_opening_a_base64_encoded_email_and_re_parsing_it_keeps_the_transfer_encoding_correct
686
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_base64_email")
687
+ assert_equal("Base64", mail['Content-Transfer-Encoding'].to_s)
688
+ decoded_mail = TMail::Mail.parse(mail.to_s)
689
+ assert_equal("Base64", decoded_mail['Content-Transfer-Encoding'].to_s)
690
+ end
691
+
692
+ def test_create_reply
693
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email")
694
+ reply = mail.create_reply
695
+ assert_equal(["<d3b8cf8e49f04480850c28713a1f473e@37signals.com>"], reply.in_reply_to)
696
+ assert_equal(["<d3b8cf8e49f04480850c28713a1f473e@37signals.com>"], reply.references)
697
+ assert_equal(TMail::Mail, mail.create_reply.class)
698
+ end
699
+
700
+ def test_create_forward
701
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email")
702
+ forward = mail.create_forward
703
+ assert_equal(true, forward.multipart?)
704
+ assert_equal(TMail::Mail, forward.class)
705
+ end
706
+
707
+ def test_body
708
+ m = TMail::Mail.new
709
+ expected = 'something_with_underscores'
710
+ m.encoding = 'quoted-printable'
711
+ quoted_body = [expected].pack('*M')
712
+ m.body = quoted_body
713
+ assert_equal "something_with_underscores=\n", m.quoted_body
714
+ assert_equal expected, m.body
715
+ end
716
+
717
+ def test_nested_attachments_are_recognized_correctly
718
+ fixture = File.read("#{File.dirname(__FILE__)}/fixtures/raw_email_with_nested_attachment")
719
+ mail = TMail::Mail.parse(fixture)
720
+ assert_equal 2, mail.attachments.length
721
+ assert_equal "image/png", mail.attachments.first.content_type
722
+ assert_equal 1902, mail.attachments.first.length
723
+ assert_equal "application/pkcs7-signature", mail.attachments.last.content_type
724
+ end
725
+
726
+ def test_preamble_read
727
+ fixture = File.read("#{File.dirname(__FILE__)}/fixtures/raw_email4")
728
+ mail = TMail::Mail.parse(fixture)
729
+ assert_equal 'This is a multi-part message in MIME format.', mail.preamble.strip
730
+ end
731
+
732
+ def test_preamble_write
733
+ mail = TMail::Mail.new
734
+ part = TMail::Mail.parse("Content-Type: text/plain\n\nBlah")
735
+ mail.parts << part
736
+ mail.preamble = 'This is the preamble'
737
+ # normalize the boundary to something non-random to assert against
738
+ str = mail.encoded
739
+ result = str.gsub(str[/boundary="(.*?)"/, 1], 'this-is-the-boundary').gsub(/\r\n\t/, ' ')
740
+ expected =<<EOF
741
+ Content-Type: multipart/mixed; boundary="this-is-the-boundary"
742
+
743
+ This is the preamble
744
+ --this-is-the-boundary
745
+ Content-Type: text/plain
746
+
747
+ Blah
748
+ --this-is-the-boundary--
749
+ EOF
750
+ assert_equal(crlf(expected), result)
751
+ end
752
+
753
+ end