lonbaker-tmail 1.2.3.1

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 (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