rmail-sup 1.0.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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/NEWS +323 -0
  3. data/NOTES +14 -0
  4. data/README +83 -0
  5. data/Rakefile +184 -0
  6. data/THANKS +25 -0
  7. data/TODO +115 -0
  8. data/guide/Intro.txt +122 -0
  9. data/guide/MIME.txt +6 -0
  10. data/guide/TableOfContents.txt +13 -0
  11. data/install.rb +1023 -0
  12. data/lib/rmail.rb +50 -0
  13. data/lib/rmail/address.rb +841 -0
  14. data/lib/rmail/header.rb +981 -0
  15. data/lib/rmail/mailbox.rb +62 -0
  16. data/lib/rmail/mailbox/mboxreader.rb +182 -0
  17. data/lib/rmail/message.rb +201 -0
  18. data/lib/rmail/parser.rb +412 -0
  19. data/lib/rmail/parser/multipart.rb +217 -0
  20. data/lib/rmail/parser/pushbackreader.rb +173 -0
  21. data/lib/rmail/serialize.rb +190 -0
  22. data/lib/rmail/utils.rb +59 -0
  23. data/test/addrgrammar.txt +113 -0
  24. data/test/data/mbox.odd +4 -0
  25. data/test/data/mbox.simple +8 -0
  26. data/test/data/multipart/data.1 +5 -0
  27. data/test/data/multipart/data.10 +1 -0
  28. data/test/data/multipart/data.11 +9 -0
  29. data/test/data/multipart/data.12 +9 -0
  30. data/test/data/multipart/data.13 +3 -0
  31. data/test/data/multipart/data.14 +3 -0
  32. data/test/data/multipart/data.15 +3 -0
  33. data/test/data/multipart/data.16 +3 -0
  34. data/test/data/multipart/data.17 +0 -0
  35. data/test/data/multipart/data.2 +5 -0
  36. data/test/data/multipart/data.3 +2 -0
  37. data/test/data/multipart/data.4 +3 -0
  38. data/test/data/multipart/data.5 +1 -0
  39. data/test/data/multipart/data.6 +2 -0
  40. data/test/data/multipart/data.7 +3 -0
  41. data/test/data/multipart/data.8 +5 -0
  42. data/test/data/multipart/data.9 +4 -0
  43. data/test/data/parser.badmime1 +4 -0
  44. data/test/data/parser.badmime2 +6 -0
  45. data/test/data/parser.nested-multipart +75 -0
  46. data/test/data/parser.nested-simple +12 -0
  47. data/test/data/parser.nested-simple2 +16 -0
  48. data/test/data/parser.nested-simple3 +21 -0
  49. data/test/data/parser.rfc822 +65 -0
  50. data/test/data/parser.simple-mime +24 -0
  51. data/test/data/parser/multipart.1 +8 -0
  52. data/test/data/parser/multipart.10 +4 -0
  53. data/test/data/parser/multipart.11 +12 -0
  54. data/test/data/parser/multipart.12 +12 -0
  55. data/test/data/parser/multipart.13 +6 -0
  56. data/test/data/parser/multipart.14 +6 -0
  57. data/test/data/parser/multipart.15 +6 -0
  58. data/test/data/parser/multipart.16 +6 -0
  59. data/test/data/parser/multipart.2 +8 -0
  60. data/test/data/parser/multipart.3 +5 -0
  61. data/test/data/parser/multipart.4 +6 -0
  62. data/test/data/parser/multipart.5 +4 -0
  63. data/test/data/parser/multipart.6 +5 -0
  64. data/test/data/parser/multipart.7 +6 -0
  65. data/test/data/parser/multipart.8 +8 -0
  66. data/test/data/parser/multipart.9 +7 -0
  67. data/test/data/transparency/absolute.1 +5 -0
  68. data/test/data/transparency/absolute.2 +1 -0
  69. data/test/data/transparency/absolute.3 +2 -0
  70. data/test/data/transparency/absolute.4 +3 -0
  71. data/test/data/transparency/absolute.5 +4 -0
  72. data/test/data/transparency/absolute.6 +49 -0
  73. data/test/data/transparency/message.1 +73 -0
  74. data/test/data/transparency/message.2 +34 -0
  75. data/test/data/transparency/message.3 +63 -0
  76. data/test/data/transparency/message.4 +5 -0
  77. data/test/data/transparency/message.5 +15 -0
  78. data/test/data/transparency/message.6 +1185 -0
  79. data/test/runtests.rb +35 -0
  80. data/test/testaddress.rb +1204 -0
  81. data/test/testbase.rb +204 -0
  82. data/test/testheader.rb +1225 -0
  83. data/test/testmailbox.rb +47 -0
  84. data/test/testmboxreader.rb +161 -0
  85. data/test/testmessage.rb +257 -0
  86. data/test/testparser.rb +634 -0
  87. data/test/testparsermultipart.rb +205 -0
  88. data/test/testpushbackreader.rb +40 -0
  89. data/test/testserialize.rb +264 -0
  90. data/test/testtestbase.rb +116 -0
  91. data/test/testtranspparency.rb +105 -0
  92. data/version +1 -0
  93. metadata +149 -0
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright (C) 2001, 2002, 2003, 2007 Matt Armstrong. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # 2. Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote products
14
+ # derived from this software without specific prior written permission.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19
+ # NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ #
27
+
28
+ # Base for all the test cases, providing a default setup and teardown
29
+
30
+ require 'test/unit'
31
+ require 'rbconfig.rb'
32
+ require 'tempfile'
33
+ require 'find'
34
+ require 'fileutils'
35
+
36
+ begin
37
+ require 'pp'
38
+ rescue LoadError
39
+ end
40
+
41
+ class TestBase < Test::Unit::TestCase
42
+ include Config
43
+
44
+ attr_reader :scratch_dir
45
+
46
+ def test_nothing
47
+ assert(true) # Appease Test::Unit
48
+ end
49
+
50
+ # Print a string to a temporary file and return the file opened.
51
+ # This lets you have some test data in a string, but access it with
52
+ # a file.
53
+ def string_as_file(string, strip_whitespace = true)
54
+ if strip_whitespace
55
+ temp = ""
56
+ string.each_line { |line|
57
+ temp += line.sub(/^[ \t]+/, '')
58
+ }
59
+ string = temp
60
+ end
61
+ file = Tempfile.new("ruby.string_as_file.")
62
+ begin
63
+ file.print(string)
64
+ file.close()
65
+ file.open()
66
+ yield file
67
+ ensure
68
+ file.close(true)
69
+ end
70
+ end
71
+
72
+ # Return true if the given file contains a line matching regexp
73
+ def file_contains(filename, regexp)
74
+ unless regexp.kind_of?(Regexp)
75
+ regexp = Regexp.new(regexp)
76
+ end
77
+ detected = nil
78
+ File.open(filename) { |f|
79
+ detected = f.detect { |line|
80
+ line =~ regexp
81
+ }
82
+ }
83
+ ! detected.nil?
84
+ end
85
+
86
+ # Deletes everything in directory +dir+, including any
87
+ # subdirectories
88
+ def cleandir(dir)
89
+ if FileTest.directory?(dir)
90
+ files = []
91
+ Find.find(dir) { |f|
92
+ files.push(f)
93
+ }
94
+ files.shift # get rid of 'dir'
95
+ files.reverse_each { |f|
96
+ if FileTest.directory?(f)
97
+ Dir.delete(f)
98
+ else
99
+ File.delete(f)
100
+ end
101
+ }
102
+ end
103
+ end
104
+
105
+ def setup
106
+ @scratch_dir = File.join(Dir.getwd, "_scratch_" + name)
107
+ @data_dir = File.join(Dir.getwd, "test", "data")
108
+ @scratch_hash = {}
109
+
110
+ cleandir(@scratch_dir)
111
+ Dir.rmdir(@scratch_dir) if FileTest.directory?(@scratch_dir)
112
+ Dir.mkdir(@scratch_dir) unless FileTest.directory?(@scratch_dir)
113
+ end
114
+
115
+ def ruby_program
116
+ File.join(CONFIG['bindir'], CONFIG['ruby_install_name'])
117
+ end
118
+
119
+ def data_filename(name)
120
+ File.join(@data_dir, name)
121
+ end
122
+
123
+ def data_as_file(name)
124
+ unless name =~ %r{^/}
125
+ name = data_filename(name)
126
+ end
127
+ File.open(name) { |f|
128
+ yield f
129
+ }
130
+ rescue Errno::ENOENT
131
+ flunk("data file #{name.inspect} does not exist")
132
+ end
133
+
134
+ def data_as_string(name)
135
+ data_as_file(name) { |f|
136
+ f.read
137
+ }
138
+ end
139
+
140
+ def scratch_filename(name)
141
+ if @scratch_hash.key?(name)
142
+ temp = @scratch_hash[name]
143
+ temp = temp.succ
144
+ @scratch_hash[name] = name = temp
145
+ else
146
+ temp = name.dup
147
+ temp << '.0' unless temp =~ /\.\d+$/
148
+ @scratch_hash[name] = temp
149
+ end
150
+ File.join(@scratch_dir, name)
151
+ end
152
+
153
+ def scratch_file_write(name)
154
+ name = scratch_filename(name)
155
+ File.open(name, 'w') { |f|
156
+ yield f
157
+ }
158
+ end
159
+
160
+ def teardown
161
+ unless $! || ((defined? passed?) && !passed?)
162
+ cleandir(@scratch_dir)
163
+ Dir.rmdir(@scratch_dir) if FileTest.directory?(@scratch_dir)
164
+ end
165
+ end
166
+
167
+ def call_fails(arg, &block)
168
+ begin
169
+ yield arg
170
+ rescue Exception
171
+ return true
172
+ end
173
+ return false
174
+ end
175
+
176
+ # if a random string failes, run it through this function to find the
177
+ # shortest fail case
178
+ def find_shortest_failure(str, &block)
179
+ unless call_fails(str, &block)
180
+ raise "hey, the input didn't fail!"
181
+ else
182
+ # Chop off stuff from the beginning and then the end
183
+ # until it stops failing
184
+ bad = str
185
+ 0.upto(bad.length) {|index|
186
+ bad.length.downto(1) {|length|
187
+ begin
188
+ loop {
189
+ s = bad.dup
190
+ s[index,length] = ''
191
+ break if bad == s
192
+ break unless call_fails(s, &block)
193
+ bad = s
194
+ }
195
+ rescue IndexError
196
+ break
197
+ end
198
+ }
199
+ }
200
+ raise "shortest failure is #{bad.inspect}"
201
+ end
202
+ end
203
+
204
+ end
@@ -0,0 +1,1225 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright (C) 2001, 2002, 2003, 2004, 2007 Matt Armstrong. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # 2. Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote products
14
+ # derived from this software without specific prior written permission.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19
+ # NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ #
27
+
28
+ require 'test/testbase'
29
+ require 'rmail/header'
30
+
31
+ class TestRMailHeader < TestBase
32
+
33
+ def test_AREF # '[]'
34
+ h = RMail::Header.new
35
+ h['From'] = 'setting1'
36
+ h['From'] = 'setting2'
37
+ h['From'] = 'setting3'
38
+
39
+ assert_equal('setting1', h[0])
40
+ assert_equal('setting2', h[1])
41
+ assert_equal('setting3', h[2])
42
+ assert_equal('setting1', h['From'])
43
+ assert_equal('setting1', h['from'])
44
+ assert_equal('setting1', h['FROM'])
45
+ assert_equal('setting1', h['From:'])
46
+ assert_equal('setting1', h['From : '])
47
+ assert_nil(h['From '])
48
+ assert_nil(h[' From '])
49
+ assert_nil(h[' From : '])
50
+ end
51
+
52
+ def test_ASET # '[]='
53
+
54
+ #
55
+ # Test that the object stores the exact objects we pass it in (at
56
+ # least, when they are strings) and that it freezes them.
57
+ #
58
+ bob = "Bob"
59
+ bob_value = "bobvalue"
60
+ sally = "Sally"
61
+ sally_value = "sallyvalue"
62
+ h = RMail::Header.new
63
+
64
+ assert_same(bob_value, h[bob] = bob_value)
65
+ assert_same(sally_value, h[sally] = sally_value)
66
+
67
+ h.each_with_index do |pair, index|
68
+ case index
69
+ when 0
70
+ assert_equal(bob, pair[0])
71
+ assert_equal(bob_value, pair[1])
72
+ assert(pair[0].frozen?)
73
+ assert(pair[1].frozen?)
74
+ when 1
75
+ assert_equal(sally, pair[0])
76
+ assert_equal(sally_value, pair[1])
77
+ assert(pair[0].frozen?)
78
+ assert(pair[1].frozen?)
79
+ else
80
+ raise
81
+ end
82
+ end
83
+
84
+ # Test that passing in symbols will not get converted into strings
85
+ # strings
86
+ h = RMail::Header.new
87
+ assert_raise(NoMethodError) {
88
+ h[:Kelly] = :the_value
89
+ }
90
+
91
+ # Test that the : will be stripped
92
+ h = RMail::Header.new
93
+ h["bob:"] = "bob"
94
+ h["sally : "] = "sally"
95
+ h.each_with_index do |pair, index|
96
+ case index
97
+ when 0
98
+ assert_equal("bob", pair[0])
99
+ assert_equal("bob", pair[1])
100
+ when 1
101
+ assert_equal("sally", pair[0])
102
+ assert_equal("sally", pair[1])
103
+ else
104
+ raise
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_EQUAL # '=='
110
+ h1 = RMail::Header.new
111
+ h2 = RMail::Header.new
112
+ assert_equal(h1, h2)
113
+ assert_equal(h2, h1)
114
+
115
+ h1['foo'] = 'a'
116
+ h2['FOO'] = 'a'
117
+ h1['bar'] = 'b'
118
+ h2['bar'] = 'b'
119
+ assert_equal(h1, h2)
120
+ assert_equal(h2, h1)
121
+
122
+ h1 = RMail::Header.new
123
+ h2 = RMail::Header.new
124
+ h1['foo'] = 'a'
125
+ h2['foo'] = 'b'
126
+ assert(! (h1 == h2))
127
+ assert(! (h2 == h1))
128
+
129
+ h1 = RMail::Header.new
130
+ h2 = RMail::Header.new
131
+ h1['foo'] = 'a'
132
+ h2['foo'] = 'a'
133
+ h1.mbox_from = "From bo diddly"
134
+ assert(! (h1 == h2))
135
+ assert(! (h2 == h1))
136
+
137
+ h1 = RMail::Header.new
138
+ assert(! (h1 == Object.new))
139
+ assert(! (h1 == Hash.new))
140
+ assert(! (h1 == Array.new))
141
+ end
142
+
143
+ def test_address_list_fetch
144
+ h = RMail::Header.new
145
+ assert_equal([], h.address_list_fetch("From"))
146
+ h.add("From", "bob@example.com")
147
+ assert_equal(["bob@example.com"], h.address_list_fetch("From"))
148
+ end
149
+
150
+ def test_add
151
+ #
152
+ # Test that the object stores the exact objects we pass it in (at
153
+ # least, when they are strings) and that it freezes them.
154
+ #
155
+ bob = "Bob"
156
+ bob_value = "bobvalue"
157
+ sally = "Sally"
158
+ sally_value = "sallyvalue"
159
+ h = RMail::Header.new
160
+
161
+ assert_same(h, h.add(bob, bob_value))
162
+ assert_same(h, h.add(sally, sally_value))
163
+
164
+ h.each_with_index do |pair, index|
165
+ case index
166
+ when 0
167
+ assert_equal(bob, pair[0])
168
+ assert_equal(bob_value, pair[1])
169
+ assert(pair[0].frozen?)
170
+ assert(pair[1].frozen?)
171
+ when 1
172
+ assert_equal(sally, pair[0])
173
+ assert_equal(sally_value, pair[1])
174
+ assert(pair[0].frozen?)
175
+ assert(pair[1].frozen?)
176
+ else
177
+ raise
178
+ end
179
+ end
180
+
181
+ # Test that passing in symbol values raises an exception
182
+ h = RMail::Header.new
183
+ assert_raise(NoMethodError) {
184
+ assert_same(h, h.add("bob", :the_value))
185
+ }
186
+
187
+ # Test that we can put stuff in arbitrary locations
188
+ h = RMail::Header.new
189
+ assert_same(h, h.add("last", "last value"))
190
+ assert_same(h, h.add("first", "first value", 0))
191
+ assert_same(h, h.add("middle", "middle value", 1))
192
+
193
+ h.each_with_index do |pair, index|
194
+ case index
195
+ when 0
196
+ assert_equal("first", pair[0])
197
+ assert_equal("first value", pair[1])
198
+ when 1
199
+ assert_equal("middle", pair[0])
200
+ assert_equal("middle value", pair[1])
201
+ when 2
202
+ assert_equal("last", pair[0])
203
+ assert_equal("last value", pair[1])
204
+ else
205
+ raise
206
+ end
207
+ end
208
+
209
+ # Test the params argument
210
+ h = RMail::Header.new
211
+ h.add("name", "value", nil, 'param1' => 'value1', 'param2' => '+value2')
212
+ assert_equal('value; param1=value1; param2="+value2"', h['name'])
213
+
214
+ h = RMail::Header.new
215
+ h.add_raw("MIME-Version: 1.0")
216
+ h.add_raw("Content-Type: multipart/alternative; boundary=X")
217
+ assert_match(/\b1\.0\b/, h['mime-version:'])
218
+ assert_not_nil(h.param('content-type', 'boundary'))
219
+ assert_equal("multipart", h.media_type)
220
+ end
221
+
222
+ def test_set
223
+ # Test that set works like delete+add
224
+
225
+ h = RMail::Header.new
226
+ h.add_raw("Foo: Bar")
227
+ h.set('foo', 'expected')
228
+ assert_equal('expected', h['foo'])
229
+ assert_equal(1, h.length)
230
+
231
+ h = RMail::Header.new
232
+ h.set('foo', 'expected')
233
+ assert_equal('expected', h['foo'])
234
+ assert_equal(1, h.length)
235
+
236
+ end
237
+
238
+ def test_clear
239
+ # Test that we can put stuff in arbitrary locations
240
+ h = RMail::Header.new
241
+ h.add("first", "first value", 0)
242
+ h.add("middle", "middle value", 1)
243
+ h.add("last", "last value")
244
+ h.mbox_from = "mbox from"
245
+ assert_equal(3, h.length)
246
+ assert_same(h, h.clear)
247
+ assert_equal(0, h.length)
248
+ assert_equal(nil, h['first'])
249
+ assert_equal(nil, h['middle'])
250
+ assert_equal(nil, h['last'])
251
+ assert_equal(nil, h[0])
252
+ assert_equal(nil, h[1])
253
+ assert_equal(nil, h[2])
254
+ assert_equal(nil, h.mbox_from)
255
+ end
256
+
257
+ def test_dup
258
+ h1 = RMail::Header.new
259
+ h1["field1"] = "field1 value"
260
+ h1.mbox_from = "mbox from"
261
+ h2 = h1.dup
262
+ assert(! h1.equal?(h2))
263
+ assert_equal(h1, h2)
264
+ assert_same(h1.mbox_from, h2.mbox_from)
265
+
266
+ h1.each_with_index do |pair, index|
267
+ assert_same(h1[index], h2[index])
268
+ case index
269
+ when 0
270
+ assert_equal("field1", pair[0])
271
+ assert_equal("field1 value", pair[1])
272
+ else
273
+ raise
274
+ end
275
+ end
276
+
277
+ h2.mbox_from = "bob"
278
+ assert_equal("mbox from", h1.mbox_from)
279
+
280
+ h1["field2"] = "field2 value"
281
+ assert_equal("field2 value", h1["field2"])
282
+ assert_nil(h2["field2"])
283
+
284
+ # Make sure singleton methods are not carried over through a dup
285
+ def h1.my_singleton_method
286
+ end
287
+ assert_respond_to(h1, :my_singleton_method)
288
+ h2 = h1.dup
289
+ assert(! h2.respond_to?(:my_singleton_method))
290
+ end
291
+
292
+ def test_clone
293
+ h1 = RMail::Header.new
294
+ h1["field1"] = "field1 value"
295
+ h1.mbox_from = "mbox from"
296
+ h2 = h1.clone
297
+ assert(! h1.equal?(h2))
298
+ assert_equal(h1, h2)
299
+ assert_equal(h1.mbox_from, h2.mbox_from)
300
+ assert(! h1.mbox_from.equal?(h2.mbox_from))
301
+
302
+ h1.each_with_index do |pair, index|
303
+ assert_equal(h1[index], h2[index])
304
+ assert(! h1[index].equal?(h2[index]))
305
+ case index
306
+ when 0
307
+ assert_equal("field1", pair[0])
308
+ assert_equal("field1 value", pair[1])
309
+ else
310
+ raise
311
+ end
312
+ end
313
+
314
+ h2.mbox_from = "bob"
315
+ assert_equal("mbox from", h1.mbox_from)
316
+
317
+ h1["field2"] = "field2 value"
318
+ assert_equal("field2 value", h1["field2"])
319
+ assert_nil(h2["field2"])
320
+
321
+ # Make sure singleton methods are carried over through a clone
322
+ h1 = RMail::Header.new
323
+ def h1.my_singleton_method
324
+ end
325
+ assert_respond_to(h1, :my_singleton_method)
326
+ h2 = h1.clone
327
+ assert(!h1.equal?(h2))
328
+ assert_respond_to(h2, :my_singleton_method)
329
+ end
330
+
331
+ def test_replace
332
+ h1 = RMail::Header.new
333
+ h1['From'] = "bob@example.net"
334
+ h1['To'] = "sam@example.net"
335
+ h1.mbox_from = "mbox from"
336
+
337
+ h2 = RMail::Header.new
338
+ h2['From'] = "sally@example.net"
339
+ h2.mbox_from = "h2 mbox from"
340
+
341
+ assert_same(h2, h2.replace(h1))
342
+ assert_equal(h1, h2)
343
+ assert_same(h1['From'], h2['From'])
344
+ assert_same(h1['To'], h2['To'])
345
+ assert_same(h1.mbox_from, h2.mbox_from)
346
+
347
+ e = assert_raise(TypeError) {
348
+ h2.replace("hi mom")
349
+ }
350
+ assert_equal('String is not of type RMail::Header', e.message)
351
+ end
352
+
353
+ def test_delete
354
+ h = RMail::Header.new
355
+ h['Foo'] = 'bar'
356
+ h['Bazo'] = 'bingo'
357
+ h['Foo'] = 'yo'
358
+ assert_same(h, h.delete('Foo'))
359
+ assert_nil(h['Foo'])
360
+ assert_equal('bingo', h[0])
361
+ assert_equal(1, h.length)
362
+ end
363
+
364
+ def test_delete_at
365
+ h = RMail::Header.new
366
+ h['Foo'] = 'bar'
367
+ h['Baz'] = 'bingo'
368
+ h['Foo'] = 'yo'
369
+ assert_same(h, h.delete_at(1))
370
+ assert_equal(2, h.length)
371
+ assert_nil(h['Baz'])
372
+ assert_equal('bar', h[0])
373
+ assert_equal('yo', h[1])
374
+
375
+ assert_raise(TypeError) {
376
+ h.delete_at("1")
377
+ }
378
+ end
379
+
380
+ def test_delete_if
381
+ h = RMail::Header.new
382
+ h['Foo'] = 'bar'
383
+ h['Baz'] = 'bingo'
384
+ h['Foo'] = 'yo'
385
+ assert_same(h, h.delete_if { |n, v| v =~ /^b/ })
386
+ assert_nil(h['Baz'])
387
+ assert_equal('yo', h['Foo'])
388
+ assert_equal(1, h.length)
389
+
390
+ assert_raise(LocalJumpError) {
391
+ h.delete_if
392
+ }
393
+ end
394
+
395
+ def each_helper(method)
396
+ h = RMail::Header.new
397
+ h['name1'] = 'value1'
398
+ h['name2'] = 'value2'
399
+
400
+ i = 1
401
+ h.send(method) { |n, v|
402
+ assert_equal("name#{i}", n)
403
+ assert_equal("value#{i}", v)
404
+ i += 1
405
+ }
406
+
407
+ assert_raise(LocalJumpError) {
408
+ h.send(method)
409
+ }
410
+ end
411
+
412
+ def test_each
413
+ each_helper(:each)
414
+ end
415
+
416
+ def test_each_pair
417
+ each_helper(:each_pair)
418
+ end
419
+
420
+ def each_name_helper(method)
421
+ h = RMail::Header.new
422
+ h['name1'] = 'value1'
423
+ h['name2'] = 'value2'
424
+
425
+ i = 1
426
+ h.send(method) { |n|
427
+ assert_equal("name#{i}", n)
428
+ i += 1
429
+ }
430
+
431
+ assert_raise(LocalJumpError) {
432
+ h.send(method)
433
+ }
434
+ end
435
+
436
+ def test_each_name
437
+ each_name_helper(:each_name)
438
+ end
439
+
440
+ def test_each_key
441
+ each_name_helper(:each_key)
442
+ end
443
+
444
+ def test_each_value
445
+ h = RMail::Header.new
446
+ h['name1'] = 'value1'
447
+ h['name2'] = 'value2'
448
+
449
+ i = 1
450
+ h.each_value { |v|
451
+ assert_equal("value#{i}", v)
452
+ i += 1
453
+ }
454
+
455
+ assert_raise(LocalJumpError) {
456
+ h.each_value
457
+ }
458
+ end
459
+
460
+ def test_empty?
461
+ h = RMail::Header.new
462
+ assert(h.empty?)
463
+ h['To'] = "president@example.com"
464
+ assert_equal(false, h.empty?)
465
+ end
466
+
467
+ def test_fetch
468
+ h = RMail::Header.new
469
+ h['To'] = "bob@example.net"
470
+ h['To'] = "sally@example.net"
471
+
472
+ assert_equal("bob@example.net", h.fetch('to'))
473
+ assert_equal(1, h.fetch('notthere', 1))
474
+ assert_equal(2, h.fetch('notthere', 1) { 2 })
475
+
476
+ e = assert_raise(ArgumentError) {
477
+ h.fetch(1,2,3)
478
+ }
479
+ assert_equal('wrong # of arguments(3 for 2)', e.message)
480
+ end
481
+
482
+ def test_fetch_all
483
+ h = RMail::Header.new
484
+ h['To'] = "bob@example.net"
485
+ h['To'] = "sally@example.net"
486
+
487
+ assert_equal([ "bob@example.net", "sally@example.net" ],
488
+ h.fetch_all('to'))
489
+ assert_equal(1, h.fetch('notthere', 1))
490
+ assert_equal(2, h.fetch('notthere', 1) { 2 })
491
+
492
+ e = assert_raise(ArgumentError) {
493
+ h.fetch_all(1,2,3)
494
+ }
495
+ assert_equal('wrong # of arguments(3 for 2)', e.message)
496
+ end
497
+
498
+ def field_helper(method)
499
+ h = RMail::Header.new
500
+ h['Subject'] = 'the sky is blue'
501
+ assert(h.send(method, 'Subject'))
502
+ assert_equal(false, h.send(method, 'Return-Path'))
503
+ end
504
+
505
+ def test_field?
506
+ field_helper(:field?)
507
+ end
508
+
509
+ def test_has_key?
510
+ field_helper(:has_key?)
511
+ end
512
+
513
+ def test_include?
514
+ field_helper(:include?)
515
+ end
516
+
517
+ def test_member?
518
+ field_helper(:member?)
519
+ end
520
+
521
+ def test_key?
522
+ field_helper(:key?)
523
+ end
524
+
525
+ def test_select_on_empty_header_returns_empty_array
526
+ h = RMail::Header.new
527
+ assert_equal([], h.select("From"))
528
+ end
529
+
530
+ def test_select
531
+ h = RMail::Header.new
532
+ h['To'] = 'matt@example.net'
533
+ h['From'] = 'bob@example.net'
534
+ h['Subject'] = 'test_select'
535
+ assert_equal([ [ 'To', 'matt@example.net' ] ],
536
+ h.select('To'))
537
+ assert_equal([ [ 'To', 'matt@example.net' ],
538
+ [ 'From', 'bob@example.net' ] ],
539
+ h.select('To', 'From'))
540
+ assert_equal([], h.select)
541
+ end
542
+
543
+ def names_helper(method)
544
+ h = RMail::Header.new
545
+ assert_equal([], h.send(method))
546
+ h['To'] = 'matt@example.net'
547
+ h['from'] = 'bob@example.net'
548
+ h['SUBJECT'] = 'test_select'
549
+ assert_equal([ 'To', 'from', 'SUBJECT' ], h.send(method))
550
+ end
551
+
552
+ def test_names
553
+ names_helper(:names)
554
+ end
555
+
556
+ def test_keys
557
+ names_helper(:keys)
558
+ end
559
+
560
+ def length_helper(method)
561
+ h = RMail::Header.new
562
+ assert_equal(0, h.send(method))
563
+ h['To'] = 'matt@example.net'
564
+ assert_equal(1, h.send(method))
565
+ h['from'] = 'bob@example.net'
566
+ assert_equal(2, h.send(method))
567
+ h['SUBJECT'] = 'test_select'
568
+ assert_equal(3, h.send(method))
569
+ h.mbox_from = "foo"
570
+ assert_equal(3, h.send(method))
571
+ h.delete('from')
572
+ assert_equal(2, h.send(method))
573
+ end
574
+
575
+ def test_length
576
+ length_helper(:length)
577
+ end
578
+
579
+ def test_size
580
+ length_helper(:size)
581
+ end
582
+
583
+ def test_to_a
584
+ h = RMail::Header.new
585
+ assert_equal([ ], h.to_a)
586
+ h['To'] = 'to value'
587
+ h['From'] = 'from value'
588
+ assert_equal([ [ 'To', 'to value' ],
589
+ [ 'From', 'from value' ] ], h.to_a)
590
+ end
591
+
592
+ def test_to_string
593
+ h = RMail::Header.new
594
+ assert_equal("", h.to_string(true))
595
+ assert_equal("", h.to_string(false))
596
+ assert_equal(h.to_s, h.to_string(true))
597
+
598
+ h['To'] = 'matt@example.net'
599
+ assert_equal("To: matt@example.net\n", h.to_string(true))
600
+ assert_equal("To: matt@example.net\n", h.to_string(false))
601
+ assert_equal(h.to_s, h.to_string(true))
602
+
603
+ h.mbox_from = "From matt@example.net blah blah"
604
+ assert_equal(<<EOF, h.to_string(true))
605
+ From matt@example.net blah blah
606
+ To: matt@example.net
607
+ EOF
608
+ assert_equal("To: matt@example.net\n", h.to_string(false))
609
+ assert_equal(h.to_s, h.to_string(true))
610
+ end
611
+
612
+ def test_s_new
613
+ h = RMail::Header.new
614
+ assert_instance_of(RMail::Header, h)
615
+ assert_equal(0, h.length)
616
+ assert_nil(h[0])
617
+ end
618
+
619
+ def test_mbox_from()
620
+ h = RMail::Header.new
621
+ assert_nil(h.mbox_from)
622
+
623
+ # FIXME: should do some basic sanity checks on its argument.
624
+
625
+ s = "foo bar baz"
626
+ assert_same(s, h.mbox_from = s)
627
+ assert_equal(s, h.mbox_from)
628
+
629
+ assert_equal(nil, h.mbox_from = nil)
630
+ assert_equal(nil, h.mbox_from)
631
+ end
632
+
633
+ # Compare header contents against an expected result. 'result'
634
+ # should be an array of arrays, with the first element being the
635
+ # required key name and the second element being the whole line.
636
+ def compare_header(header, expected)
637
+ testcase_desc = "TestCase header: #{header.inspect} " +
638
+ "expected result: #{expected.inspect}"
639
+ count = 0
640
+ header.each_with_index { |value, index|
641
+ count = count.succ
642
+ assert_operator(index, '<', expected.length,
643
+ "result has too few elements. #{testcase_desc}")
644
+ assert_operator(2, '<=', expected[index].length,
645
+ "Expected result item must have at last two elements. " +
646
+ testcase_desc)
647
+ assert_operator(3, '>=', expected[index].length,
648
+ "Expected result item must have no more than three " +
649
+ "elements. " + testcase_desc)
650
+ assert_equal(2, value.length, testcase_desc)
651
+
652
+ expected_tag, expected_header = expected[index]
653
+ got_tag, got_header = value
654
+
655
+ assert_equal(header[index], got_header, testcase_desc)
656
+
657
+ assert_equal(expected_tag, got_tag,
658
+ "field #{index} has incorrect name. " + testcase_desc)
659
+ assert_equal(expected_header, got_header,
660
+ "field #{index} has incorrect line, " +
661
+ "expected #{expected_header.inspect} got " +
662
+ "#{got_header.inspect}. " + testcase_desc)
663
+ assert_equal(header[expected_tag], expected_header, testcase_desc)
664
+ }
665
+ assert_equal(count, expected.length,
666
+ "result has too few elements " +
667
+ "(#{count} < #{expected.length}). " + testcase_desc)
668
+ end
669
+
670
+ def verify_match(header, name, value, expected_result)
671
+ h = header.match(name, value)
672
+ assert_kind_of(RMail::Header, h)
673
+ if h.length == 0
674
+ assert_equal(expected_result, nil)
675
+ else
676
+ assert_not_nil(expected_result)
677
+ compare_header(h, expected_result)
678
+ end
679
+ end
680
+
681
+ def test_match
682
+ h = RMail::Header.new
683
+ h['To'] = 'bob@example.net'
684
+ h['Cc'] = 'sammy@example.com'
685
+ h['Resent-To'] = 'president@example.com'
686
+ h['Subject'] = 'yoda lives!'
687
+
688
+ # First verify argument type checking
689
+ e = assert_raise(ArgumentError) {
690
+ h.match(12, "foo")
691
+ }
692
+ assert_match(/name not a Regexp or String/, e.message)
693
+ assert_nothing_raised {
694
+ h.match(/not_case_insensitive/, "foo")
695
+ }
696
+ e = assert_raise(ArgumentError) {
697
+ h.match(/this is okay/i, 12)
698
+ }
699
+ assert_match(/value not a Regexp or String/, e.message)
700
+ assert_nothing_raised {
701
+ h.match(/this is okay/i, /this_not_multiline_or_insensitive/)
702
+ }
703
+ assert_nothing_raised {
704
+ h.match(/this is okay/i, /this_not_multiline/i)
705
+ }
706
+ assert_nothing_raised {
707
+ h.match(/this is okay/i, /this_not_inesnsitive/m)
708
+ }
709
+
710
+ verify_match(h, /./i, /this will not match anything/im, nil)
711
+
712
+ verify_match(h, "to", /./im,
713
+ [ [ 'To', "bob@example.net" ] ])
714
+
715
+ verify_match(h, "tO", /./im,
716
+ [ [ 'To', "bob@example.net" ] ])
717
+
718
+ verify_match(h, "To", /./im,
719
+ [ [ 'To', "bob@example.net" ] ])
720
+
721
+ verify_match(h, "^to", /./im, nil)
722
+
723
+ verify_match(h, /^(to|cc|resent-to)/i, /.*/im,
724
+ [ [ 'To', "bob@example.net" ],
725
+ [ 'Cc', "sammy@example.com" ],
726
+ [ 'Resent-To', "president@example.com"] ])
727
+ end
728
+
729
+ def test_match?
730
+ h = RMail::Header.new
731
+ h['To'] = 'bob@example.net'
732
+ h['Cc'] = 'sammy@example.com'
733
+ h['Resent-To'] = 'president@example.com'
734
+ h['Subject'] = "yoda\n lives! [bob]\\s"
735
+
736
+ # First verify argument type checking
737
+ e = assert_raise(ArgumentError) {
738
+ h.match?(12, "foo")
739
+ }
740
+ assert_match(/name not a Regexp or String/, e.message)
741
+ assert_nothing_raised {
742
+ h.match?(/not_case_insensitive/, "foo")
743
+ }
744
+ e = assert_raise(ArgumentError) {
745
+ h.match?(/this is okay/i, 12)
746
+ }
747
+ assert_match(/value not a Regexp or String/, e.message)
748
+ assert_nothing_raised {
749
+ h.match?(/this is okay/i, /this_not_multiline_or_insensitive/)
750
+ }
751
+ assert_nothing_raised {
752
+ h.match?(/this is okay/i, /this_not_multiline/i)
753
+ }
754
+ assert_nothing_raised {
755
+ h.match?(/this is okay/i, /this_not_inesnsitive/m)
756
+ }
757
+
758
+ assert_equal(false, h.match?(/./i, /this will not match anything/im))
759
+ assert_equal(true, h.match?("to", /./im))
760
+ assert_equal(true, h.match?("To", /./im))
761
+ assert_equal(false, h.match?("^to", /./im))
762
+ assert_equal(true, h.match?(/^(to|cc|resent-to)/i, /.*/im))
763
+ assert_equal(true, h.match?('subject', 'yoda'))
764
+ assert_equal(true, h.match?('subject', /yoda\s+lives/))
765
+ assert_equal(true, h.match?('subject', '[bob]\s'))
766
+ assert_equal(true, h.match?('subject', '[BOB]\s'))
767
+ end
768
+
769
+ def test_content_type
770
+ h = RMail::Header.new
771
+ assert_equal(nil, h.content_type)
772
+
773
+ h['content-type'] = ' text/html; charset=ISO-8859-1'
774
+ assert_equal("text/html", h.content_type)
775
+
776
+ h.delete('content-type')
777
+ h['content-type'] = ' foo/html ; charset=ISO-8859-1'
778
+ assert_equal("foo/html", h.content_type)
779
+ end
780
+
781
+ def test_media_type
782
+ h = RMail::Header.new
783
+ assert_nil(h.media_type)
784
+ assert_equal("foo", h.media_type("foo"))
785
+ assert_equal("bar", h.media_type("foo") { "bar" })
786
+
787
+ h['content-type'] = ' text/html; charset=ISO-8859-1'
788
+ assert_equal("text", h.media_type)
789
+
790
+ h.delete('content-type')
791
+ h['content-type'] = 'foo/html ; charset=ISO-8859-1'
792
+ assert_equal("foo", h.media_type)
793
+ end
794
+
795
+ def test_subtype
796
+ h = RMail::Header.new
797
+ assert_nil(h.subtype)
798
+ assert_equal("foo", h.subtype("foo"))
799
+ assert_equal("bar", h.subtype("foo") { "bar" })
800
+
801
+ h['content-type'] = ' text/html; charset=ISO-8859-1'
802
+ assert_equal("html", h.subtype)
803
+
804
+ h.delete('content-type')
805
+ h['content-type'] = 'foo/yoda ; charset=ISO-8859-1'
806
+ assert_equal("yoda", h.subtype)
807
+ end
808
+
809
+ def test_params
810
+ begin
811
+ h = RMail::Header.new
812
+ assert_nil(h.params('foo'))
813
+ assert_nil(h.params('foo', nil))
814
+
815
+ default = "foo"
816
+ ignore = "ignore"
817
+ assert_same(default, h.params('foo', default))
818
+ assert_same(default, h.params('foo') { |field_name|
819
+ assert_equal('foo', field_name)
820
+ default
821
+ })
822
+ assert_same(default, h.params('foo', ignore) {
823
+ default
824
+ })
825
+ end
826
+
827
+ begin
828
+ h = RMail::Header.new
829
+ h['Content-Disposition'] = 'attachment;
830
+ filename="delete_product_recover_flag.cmd"'
831
+ assert_equal( { "filename" => "delete_product_recover_flag.cmd" },
832
+ h.params('content-disposition'))
833
+ end
834
+
835
+ begin
836
+ h = RMail::Header.new
837
+ h['Content-Disposition'] = 'attachment;
838
+ filename="delete=_product=_recover;_flag;.cmd"'
839
+ assert_equal( { "filename" => "delete=_product=_recover;_flag;.cmd" },
840
+ h.params('content-disposition'))
841
+ end
842
+
843
+ begin
844
+ h = RMail::Header.new
845
+ h['Content-Disposition'] = ' attachment ;
846
+ filename = "trailing_Whitespace.cmd" '
847
+ assert_equal( { "filename" => "trailing_Whitespace.cmd" },
848
+ h.params('content-disposition'))
849
+ end
850
+
851
+ begin
852
+ h = RMail::Header.new
853
+ h['Content-Disposition'] = ''
854
+ assert_equal({}, h.params('content-disposition'))
855
+ end
856
+
857
+ begin
858
+ h = RMail::Header.new
859
+ h['Content-Disposition'] = ' '
860
+ assert_equal({}, h.params('content-disposition'))
861
+ end
862
+
863
+ begin
864
+ h = RMail::Header.new
865
+ h['Content-Disposition'] = '='
866
+ assert_equal({}, h.params('content-disposition'))
867
+ end
868
+
869
+ begin
870
+ h = RMail::Header.new
871
+ h['Content-Disposition'] = 'ass; param1 = "p1"; param2 = "p2"'
872
+ assert_equal({ 'param1' => 'p1',
873
+ 'param2' => 'p2' }, h.params('content-disposition'))
874
+ end
875
+
876
+ begin
877
+ h = RMail::Header.new
878
+ h['Content-Disposition'] = 'ass; Foo = "" ; bar = "asdf"'
879
+ assert_equal({ "foo" => '""',
880
+ "bar" => "asdf" }, h.params('content-disposition'))
881
+ end
882
+ end
883
+
884
+ def test_set_boundary
885
+ begin
886
+ h = RMail::Header.new
887
+ h.set_boundary("b")
888
+ assert_equal("b", h.param('content-type', 'boundary'))
889
+ assert_equal("multipart/mixed", h.content_type)
890
+ assert_equal('multipart/mixed; boundary=b', h['content-type'])
891
+ end
892
+
893
+ begin
894
+ h = RMail::Header.new
895
+ h['content-type'] = "multipart/alternative"
896
+ h.set_boundary("b")
897
+ assert_equal("b", h.param('content-type', 'boundary'))
898
+ assert_equal("multipart/alternative", h.content_type)
899
+ assert_equal('multipart/alternative; boundary=b', h['content-type'])
900
+ end
901
+
902
+ begin
903
+ h = RMail::Header.new
904
+ h['content-type'] = 'multipart/alternative; boundary="a"'
905
+ h.set_boundary("b")
906
+ assert_equal("b", h.param('content-type', 'boundary'))
907
+ assert_equal("multipart/alternative", h.content_type)
908
+ assert_equal('multipart/alternative; boundary=b', h['content-type'])
909
+ end
910
+
911
+ end
912
+
913
+ def test_params_random_string
914
+ # find_shortest_failure("],C05w\010O\e]b\">%\023[1{:L1o>B\"|\024fDJ@u{)\\\021\t\036\034)ZJ\034&/+]owh=?{Yc)}vi\000\"=@b^(J'\\,O|4v=\"q,@p@;\037[\"{!Dg*(\010\017WQ]:Q;$\004x]\032\035\003a#\"=;\005@&\003:;({>`y{?<X\025vb\032\037\"\"K8\025u[cb}\001;k', k\a/?xm1$\n_?Z\025t?\001,_?O=\001\003U,Rk<\\\027w]j@?J(5ybTb\006\0032@@4\002JP W,]EH|]\\G\e\003>.p/\022jP\f/4U)\006+\022(<{|.<|]]\032.,N,\016\000\036T,;\\49C>C[{b[v") { |str|
915
+ # h = RMail::Header.new
916
+ # h['header'] = str
917
+ # h.params('header')
918
+ # }
919
+
920
+ 0.upto(25) {
921
+ specials = '()<>@,;:\\"/[]?='
922
+ strings = [(0..rand(255)).collect {rand(127).chr}.to_s,
923
+ (0..255).collect {rand(255).chr}.to_s,
924
+ (0..255).collect {
925
+ r = rand(specials.length * 5)
926
+ case r
927
+ when 0 .. specials.length - 1
928
+ specials[r].chr
929
+ else
930
+ rand(127).chr
931
+ end
932
+ }.to_s ]
933
+ strings.each {|string|
934
+ assert_nothing_raised("failed for string #{string.inspect}") {
935
+ h = RMail::Header.new
936
+ h['header'] = string
937
+ params = h.params('header')
938
+ params.each { |name, value|
939
+ assert_kind_of(String, name)
940
+ assert(! ("" == name) )
941
+ assert_kind_of(String, value)
942
+ }
943
+ }
944
+ }
945
+ }
946
+ end
947
+
948
+ def test_param
949
+ begin
950
+ h = RMail::Header.new
951
+ assert_nil(h.param('bar', 'foo'))
952
+ assert_nil(h.param('bar', 'foo', nil))
953
+
954
+ default = "foo"
955
+ ignore = "ignore"
956
+ assert_same(default, h.param('bar', 'foo', default))
957
+ assert_same(default, h.param('bar', 'foo') { |field_name, param_name|
958
+ assert_equal('bar', field_name)
959
+ assert_equal('foo', param_name)
960
+ default
961
+ })
962
+ assert_same(default, h.param('bar', 'foo', ignore) {
963
+ default
964
+ })
965
+ end
966
+
967
+ begin
968
+ h = RMail::Header.new
969
+ h['Content-Disposition'] = 'attachment;
970
+ filename="delete_product_recover_flag.cmd"'
971
+ assert_equal('delete_product_recover_flag.cmd',
972
+ h.param('content-disposition',
973
+ 'filename'))
974
+ assert_nil(h.param('content-disposition', 'notthere'))
975
+ end
976
+
977
+ begin
978
+ h = RMail::Header.new
979
+ h['Content-Disposition'] = 'attachment;
980
+ filename="delete=_product=_recover;_flag;.cmd"'
981
+ assert_equal("delete=_product=_recover;_flag;.cmd",
982
+ h.param('content-disposition', 'filename'))
983
+ end
984
+
985
+ begin
986
+ h = RMail::Header.new
987
+ h['Content-Disposition'] = ' attachment ;
988
+ filename = " trailing_Whitespace.cmd " '
989
+ assert_equal(" trailing_Whitespace.cmd ",
990
+ h.param('content-disposition', 'filename'))
991
+ end
992
+ end
993
+
994
+ def test_date
995
+
996
+ begin
997
+ h = RMail::Header.new
998
+ h.add_raw("Date: Sat, 18 Jan 2003 21:00:09 -0700")
999
+ t = h.date
1000
+ assert(!t.utc?)
1001
+ t.utc
1002
+ assert_equal([9, 0, 4, 19, 1, 2003, 0], t.to_a[0, 7])
1003
+ assert_match(/Sun, 19 Jan 2003 04:00:09 [+-]0000/, t.rfc2822)
1004
+ end
1005
+
1006
+ begin
1007
+ h = RMail::Header.new
1008
+ h.add_raw("Date: Sat,18 Jan 2003 02:04:27 +0100 (CET)")
1009
+ t = h.date
1010
+ assert(!t.utc?)
1011
+ t.utc
1012
+ assert_equal([27, 4, 1, 18, 1, 2003, 6, 18], t.to_a[0, 8])
1013
+ assert_match(/Sat, 18 Jan 2003 01:04:27 [+-]0000/, t.rfc2822)
1014
+ end
1015
+
1016
+ begin
1017
+ h = RMail::Header.new
1018
+ # This one is bogus and can't even be parsed.
1019
+ h.add_raw("Date: 21/01/2002 09:29:33 Pacific Daylight Time")
1020
+ t = assert_nothing_raised {
1021
+ h.date
1022
+ }
1023
+ assert_nil(t)
1024
+ end
1025
+
1026
+ begin
1027
+ h = RMail::Header.new
1028
+ # This time is out of the range that can be represented by a
1029
+ # Time object.
1030
+ h.add_raw("Date: Sun, 14 Jun 2065 05:51:55 +0200")
1031
+ t = assert_nothing_raised {
1032
+ h.date
1033
+ }
1034
+ assert_nil(t)
1035
+ end
1036
+
1037
+ end
1038
+
1039
+ def test_date_eq
1040
+ h = RMail::Header.new
1041
+ t = Time.at(1042949885).utc
1042
+ h.date = t
1043
+ assert_match(/Sun, 19 Jan 2003 04:18:05 [+-]0000/, h['date'])
1044
+ end
1045
+
1046
+ def test_from
1047
+ begin
1048
+ h = RMail::Header.new
1049
+ h.add_raw('From: matt@example.net')
1050
+ a = h.from
1051
+ assert_kind_of(Array, a)
1052
+ assert_kind_of(RMail::Address::List, a)
1053
+ assert_equal(1, a.length)
1054
+ assert_kind_of(RMail::Address, a.first)
1055
+ assert_equal(RMail::Address.new("matt@example.net"), a.first)
1056
+ end
1057
+
1058
+ begin
1059
+ h = RMail::Header.new
1060
+ h.add_raw('From: Matt Armstrong <matt@example.net>,
1061
+ Bob Smith <bob@example.com>')
1062
+ a = h.from
1063
+ assert_kind_of(Array, a)
1064
+ assert_kind_of(RMail::Address::List, a)
1065
+ assert_equal(2, a.length)
1066
+ assert_kind_of(RMail::Address, a[0])
1067
+ assert_equal("matt@example.net", a[0].address)
1068
+ assert_equal("Matt Armstrong", a[0].display_name)
1069
+ assert_kind_of(RMail::Address, a[1])
1070
+ assert_equal("bob@example.com", a[1].address)
1071
+ assert_equal("Bob Smith", a[1].display_name)
1072
+ end
1073
+
1074
+ begin
1075
+ h = RMail::Header.new
1076
+ a = h.from
1077
+ assert_kind_of(Array, a)
1078
+ assert_kind_of(RMail::Address::List, a)
1079
+ assert_equal(0, a.length)
1080
+ assert_nil(h.from.first)
1081
+ end
1082
+ end
1083
+
1084
+ def common_test_address_list_header_assign(field_name)
1085
+ h = RMail::Header.new
1086
+
1087
+ get = field_name.downcase.gsub(/-/, '_')
1088
+ assign = get + '='
1089
+
1090
+ h.__send__("#{assign}", "bob@example.net")
1091
+ assert_equal(1, h.length)
1092
+ assert_equal("bob@example.net", h[field_name])
1093
+
1094
+ h[field_name] = "bob2@example.net"
1095
+ assert_equal(2, h.length)
1096
+ assert_equal("bob@example.net", h[field_name])
1097
+ assert_equal(["bob@example.net", "bob2@example.net"],
1098
+ h.fetch_all(field_name))
1099
+ assert_equal(["bob@example.net", "bob2@example.net"],
1100
+ h.__send__("#{get}"))
1101
+
1102
+ h.__send__("#{assign}", "sally@example.net")
1103
+ assert_equal(1, h.length)
1104
+ assert_equal("sally@example.net", h[field_name])
1105
+
1106
+ h.__send__("#{assign}", "Sally <sally@example.net>, bob@example.invalid (Bob)")
1107
+ assert_equal(1, h.length)
1108
+ assert_equal(2, h.__send__(get).length)
1109
+ assert_equal(%w{ sally bob },
1110
+ h.__send__(get).locals)
1111
+ assert_equal([ 'Sally', nil ],
1112
+ h.__send__(get).display_names)
1113
+ assert_equal([ 'Sally', 'Bob' ],
1114
+ h.__send__(get).names,
1115
+ "got wrong result for #names")
1116
+ assert_equal(%w{ example.net example.invalid },
1117
+ h.__send__(get).domains)
1118
+ assert_equal(%w{ sally@example.net bob@example.invalid },
1119
+ h.__send__(get).addresses)
1120
+ assert_equal([ "Sally <sally@example.net>", "bob@example.invalid (Bob)" ],
1121
+ h.__send__(get).format)
1122
+
1123
+ h.__send__("#{assign}", RMail::Address.new('Bill <bill@example.net>'))
1124
+ assert_equal(1, h.length)
1125
+ assert_equal(1, h.__send__(get).length)
1126
+ assert_equal(%w{ bill@example.net }, h.__send__(get).addresses)
1127
+ assert_equal('bill@example.net', h.__send__(get)[0].address)
1128
+ assert_equal('Bill', h.__send__(get)[0].display_name)
1129
+
1130
+ h.__send__("#{assign}", RMail::Address.parse('Bob <bob@example.net>, ' +
1131
+ 'Sally <sally@example.net>'))
1132
+ assert_equal(1, h.length)
1133
+ assert_equal(2, h.__send__(get).length)
1134
+ assert_equal(%w{ bob@example.net sally@example.net },
1135
+ h.__send__(get).addresses)
1136
+ assert_equal('bob@example.net', h.__send__(get)[0].address)
1137
+ assert_equal('Bob', h.__send__(get)[0].display_name)
1138
+ assert_equal('sally@example.net', h.__send__(get)[1].address)
1139
+ assert_equal('Sally', h.__send__(get)[1].display_name)
1140
+ end
1141
+
1142
+ def test_from_assign
1143
+ common_test_address_list_header_assign('From')
1144
+ end
1145
+
1146
+ def test_to_assign
1147
+ common_test_address_list_header_assign('To')
1148
+ end
1149
+
1150
+ def test_reply_cc_assign
1151
+ common_test_address_list_header_assign('Cc')
1152
+ end
1153
+
1154
+ def test_reply_bcc_assign
1155
+ common_test_address_list_header_assign('Bcc')
1156
+ end
1157
+
1158
+ def test_reply_to_assign
1159
+ common_test_address_list_header_assign('Reply-To')
1160
+ end
1161
+
1162
+ def test_message_id
1163
+ h = RMail::Header.new
1164
+ h.set('Message-Id', '<foo@bar>')
1165
+ assert_equal('<foo@bar>', h.message_id)
1166
+ end
1167
+
1168
+ def test_add_message_id
1169
+ h = RMail::Header.new
1170
+ h.add_message_id
1171
+
1172
+ a = RMail::Address.parse(h.message_id).first
1173
+ require 'socket'
1174
+ assert_equal(Socket.gethostname + '.invalid', a.domain)
1175
+ assert_equal('rubymail', a.local.split('.')[3])
1176
+ assert_equal('0', a.local.split('.')[2],
1177
+ "md5 data present for empty header")
1178
+ assert_match(/[a-z0-9]{5,6}/, a.local.split('.')[0])
1179
+ assert_match(/[a-z0-9]{5,6}/, a.local.split('.')[1])
1180
+
1181
+ h.to = "matt@lickey.com"
1182
+ h.delete('message-id')
1183
+ h.add_message_id
1184
+ a = RMail::Address.parse(h.message_id).first
1185
+ assert_equal('70bmbq38pc5q462kl4ikv0mcq', a.local.split('.')[2],
1186
+ "md5 hash wrong for header")
1187
+ end
1188
+
1189
+ def test_subject
1190
+ h = RMail::Header.new
1191
+ h['subject'] = 'hi mom'
1192
+ assert_equal('hi mom', h.subject)
1193
+ assert_equal('hi mom', h['subject'])
1194
+ h.subject = 'hi dad'
1195
+ assert_equal(1, h.length)
1196
+ assert_equal('hi dad', h['subject'])
1197
+ assert_equal('hi dad', h['Subject'])
1198
+ assert_equal("Subject: hi dad\n", h.to_s)
1199
+ end
1200
+
1201
+ def test_recipients
1202
+ %w{ to cc bcc }.each { |field_name|
1203
+ h = RMail::Header.new
1204
+ h[field_name] = 'matt@lickey.com'
1205
+ assert_equal([ 'matt@lickey.com' ], h.recipients )
1206
+ h[field_name] = 'bob@lickey.com'
1207
+ assert_equal([ 'matt@lickey.com', 'bob@lickey.com' ], h.recipients )
1208
+ }
1209
+
1210
+ h = RMail::Header.new
1211
+ h.to = [ 'bob@example.net', 'sally@example.net' ]
1212
+ h.cc = 'bill@example.net'
1213
+ h.bcc = 'samuel@example.net'
1214
+ assert_kind_of(RMail::Address::List, h.recipients)
1215
+ assert_equal([ 'bill@example.net',
1216
+ 'bob@example.net',
1217
+ 'sally@example.net',
1218
+ 'samuel@example.net' ], h.recipients.sort)
1219
+
1220
+ h = RMail::Header.new
1221
+ assert_kind_of(RMail::Address::List, h.recipients)
1222
+ assert_equal(0, h.recipients.length)
1223
+ end
1224
+
1225
+ end