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,60 @@
1
+ require 'test_helper'
2
+ require 'tmail'
3
+
4
+ class TestAttachments < Test::Unit::TestCase
5
+
6
+ def test_attachment
7
+ mail = TMail::Mail.new
8
+ mail.mime_version = "1.0"
9
+ mail.set_content_type 'multipart', 'mixed', {'boundary' => 'Apple-Mail-13-196941151'}
10
+ mail.body =<<HERE
11
+ --Apple-Mail-13-196941151
12
+ Content-Transfer-Encoding: quoted-printable
13
+ Content-Type: text/plain;
14
+ charset=ISO-8859-1;
15
+ delsp=yes;
16
+ format=flowed
17
+
18
+ This is the first part.
19
+
20
+ --Apple-Mail-13-196941151
21
+ Content-Type: text/x-ruby-script; name="hello.rb"
22
+ Content-Transfer-Encoding: 7bit
23
+ Content-Disposition: attachment;
24
+ filename="api.rb"
25
+
26
+ puts "Hello, world!"
27
+ gets
28
+
29
+ --Apple-Mail-13-196941151--
30
+ HERE
31
+ assert_equal(true, mail.multipart?)
32
+ assert_equal(1, mail.attachments.length)
33
+ end
34
+
35
+ def test_recursive_multipart_processing
36
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email7")
37
+ mail = TMail::Mail.parse(fixture)
38
+ assert_equal "This is the first part.\n\nAttachment: test.rb\nAttachment: test.pdf\n\n\nAttachment: smime.p7s\n", mail.body
39
+ end
40
+
41
+ def test_decode_encoded_attachment_filename
42
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email8")
43
+ mail = TMail::Mail.parse(fixture)
44
+ attachment = mail.attachments.last
45
+ assert_equal "01 Quien Te Dij\212at. Pitbull.mp3", attachment.original_filename
46
+ end
47
+
48
+ def test_assigning_attachment_crashing_due_to_missing_boundary
49
+ mail = TMail::Mail.new
50
+ mail.mime_version = '1.0'
51
+ mail.set_content_type("multipart", "mixed")
52
+
53
+ mailpart=TMail::Mail.new
54
+ mailpart.set_content_type("application", "octet-stream")
55
+ mailpart['Content-Disposition'] = "attachment; filename=mailbox.zip"
56
+
57
+ assert_nothing_raised { mail.parts.push(mailpart) }
58
+ end
59
+
60
+ end
@@ -0,0 +1,64 @@
1
+ require 'test_helper'
2
+ require 'tmail/base64'
3
+ require 'test/unit'
4
+
5
+ class TestTMailBase64 < Test::Unit::TestCase
6
+ def try(orig)
7
+ ok = [orig].pack('m').delete("\r\n")
8
+ result = TMail::Base64.encode(orig)
9
+ assert_equal ok, result, "str=#{orig.inspect}"
10
+ assert_equal orig, TMail::Base64.decode(result), "str=#{orig.inspect}"
11
+ end
12
+
13
+ def test_normal
14
+ try ''
15
+ try 'a'
16
+ try 'ab'
17
+ try 'abc'
18
+ try 'abcd'
19
+ try 'abcde'
20
+ try 'abcdef'
21
+ try 'abcdefg'
22
+ try 'abcdefgh'
23
+ try 'abcdefghi'
24
+ try 'abcdefghij'
25
+ try 'abcdefghijk'
26
+ try 'abcdefghijkl'
27
+ try 'abcdefghijklm'
28
+ try 'abcdefghijklmn'
29
+ try 'abcdefghijklmno'
30
+ try 'abcdefghijklmnop'
31
+ try 'abcdefghijklmnopq'
32
+ try 'abcdefghijklmnopqr'
33
+ try 'abcdefghijklmnopqrs'
34
+ try 'abcdefghijklmnopqrst'
35
+ try 'abcdefghijklmnopqrstu'
36
+ try 'abcdefghijklmnopqrstuv'
37
+ try 'abcdefghijklmnopqrstuvw'
38
+ try 'abcdefghijklmnopqrstuvwx'
39
+ try 'abcdefghijklmnopqrstuvwxy'
40
+ try 'abcdefghijklmnopqrstuvwxyz'
41
+ end
42
+
43
+ def test_dangerous_chars
44
+ ["\0", "\001", "\002", "\003", "\0xfd", "\0xfe", "\0xff"].each do |ch|
45
+ 1.upto(96) do |len|
46
+ try ch * len
47
+ end
48
+ end
49
+ end
50
+
51
+ def test_random
52
+ 16.times do
53
+ try make_random_string(96)
54
+ end
55
+ end
56
+
57
+ def make_random_string(len)
58
+ buf = ''
59
+ len.times do
60
+ buf << rand(255)
61
+ end
62
+ buf
63
+ end
64
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+ require 'tmail/port'
4
+ require 'tmail/encode'
5
+ require 'nkf'
6
+ require 'test/unit'
7
+
8
+ class TestEncode < Test::Unit::TestCase
9
+
10
+ SRCS = [
11
+ "a cde あいうえおあいうえおあいうえおあいうえおあいうえお", #1
12
+ "a cde あいうえおあいうえおあいうえおあいうえおあいうえ", #2
13
+ "a cde あいうえおあいうえおあいうえおあいうえおあいう", #3
14
+ "a cde あいうえおあいうえおあいうえおあいうえおあい", #4
15
+ "a cde あいうえおあいうえおあいうえおあいうえおあ", #5
16
+ "a cde あいうえおあいうえおあいうえおあいうえお", #6 #
17
+ "a cde あいうえおあいうえおあいうえおあいうえ", #7
18
+ "a cde あいうえおあいうえおあいうえおあいう", #8
19
+ "a cde あいうえおあいうえおあいうえおあい", #9
20
+ "a cde あいうえおあいうえおあいうえおあ", #10
21
+ "a cde あいうえおあいうえおあいうえお", #11
22
+ "a cde あいうえおあいうえおあいうえ", #12
23
+ "a cde あいうえおあいうえおあいう", #13
24
+ "a cde あいうえおあいうえおあい", #14
25
+ "a cde あいうえおあいうえおあ", #15
26
+ "a cde あいうえおあいうえお", #16
27
+ "a cde あいうえおあいうえ", #17
28
+ "a cde あいうえおあいう", #18
29
+ "a cde あいうえおあい", #19
30
+ "a cde あいうえおあ", #20
31
+ "a cde あいうえお", #21
32
+ "a cde あいうえ", #22
33
+ "a cde あいう", #23
34
+ "a cde あい", #24
35
+ "a cde あ", #25
36
+ "aあa aあa aあa aあa aあa aあa" #26
37
+ ]
38
+
39
+ OK = [
40
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYkKCQqGyhC?=", #1
41
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYkKBsoQg==?=", #2
42
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYbKEI=?=", #3
43
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkGyhC?=", #4
44
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIhsoQg==?=", #5
45
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCobKEI=?=", #6
46
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoGyhC?=", #7
47
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJhsoQg==?=", #8
48
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQbKEI=?=", #9
49
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=", #10
50
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqGyhC?=", #11
51
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKBsoQg==?=", #12
52
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=', #13
53
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkGyhC?=', #14
54
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIhsoQg==?=', #15
55
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCobKEI=?=', #16
56
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoGyhC?=', #17
57
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJhsoQg==?=', #18
58
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQbKEI=?=', #19
59
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiGyhC?=', #20
60
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKhsoQg==?=', #21
61
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgbKEI=?=', #22
62
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmGyhC?=', #23
63
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJBsoQg==?=', #24
64
+ 'a cde =?iso-2022-jp?B?GyRCJCIbKEI=?=', #25
65
+ "=?iso-2022-jp?B?YRskQiQiGyhCYSBhGyRCJCIbKEJhIGEbJEIkIhsoQmEgYRskQiQiGyhCYSBh?=\r\n\t=?iso-2022-jp?B?GyRCJCIbKEJhIGEbJEIkIhsoQmE=?=" #26
66
+ ]
67
+
68
+ def test_s_encode
69
+ SRCS.each_index do |i|
70
+ assert_equal crlf(OK[i]),
71
+ TMail::Encoder.encode(NKF.nkf('-j', SRCS[i]))
72
+ end
73
+ end
74
+
75
+ def crlf( str )
76
+ str.gsub(/\n|\r\n|\r/) { "\r\n" }
77
+ end
78
+
79
+ def test_wrapping_an_email_with_whitespace_at_position_zero
80
+ # This email is a spam mail designed to break mailers... evil.
81
+ mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_attack_email_with_zero_length_whitespace")
82
+ assert_nothing_raised(Exception) { mail.encoded }
83
+ end
84
+
85
+ end
@@ -0,0 +1,969 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'test_helper'
3
+ require 'tmail'
4
+ require 'tmail/header'
5
+ require 'kcode'
6
+ require 'time'
7
+
8
+ class UnstructuredHeaderTester < Test::Unit::TestCase
9
+ def test_s_new
10
+ %w( Subject SUBJECT sUbJeCt
11
+ X-My-Header ).each do |name|
12
+ h = TMail::HeaderField.new(name, 'This is test header.')
13
+ assert_instance_of TMail::UnstructuredHeader, h,
14
+ 'Header.new: name=' + name.dump
15
+ end
16
+ end
17
+
18
+ def test_to_s
19
+ # I must write more and more test.
20
+ [
21
+ 'This is test header.',
22
+ # "This is \r\n\ttest header"
23
+ # "JAPANESE STRING"
24
+ ''
25
+ ]\
26
+ .each do |str|
27
+ h = TMail::HeaderField.new('Subject', str)
28
+ assert_equal str, h.decoded
29
+ assert_equal str, h.to_s
30
+ end
31
+ end
32
+ end
33
+
34
+ class DateTimeHeaderTester < Test::Unit::TestCase
35
+ def test_s_new
36
+ %w( Date Resent-Date ).each do |name|
37
+ h = TMail::HeaderField.new(name, 'Tue, 4 Dec 2001 10:49:32 +0900')
38
+ assert_instance_of TMail::DateTimeHeader, h, name
39
+ end
40
+ end
41
+
42
+ def test_date
43
+ h = TMail::HeaderField.new('Date', 'Tue, 4 Dec 2001 10:49:32 +0900')
44
+ assert_instance_of Time, h.date
45
+ assert_equal false, h.date.gmt?
46
+ assert_equal Time.parse('Tue, 4 Dec 2001 10:49:32 +0900'), h.date
47
+ end
48
+
49
+ def test_empty__illegal?
50
+ [ [false, 'Tue, 4 Dec 2001 10:49:32 +0900'],
51
+ [false, 'Sat, 15 Dec 2001 12:51:38 +0900'],
52
+ [true, 'Sat, 15 Dec 2001 12:51:38'],
53
+ [true, 'Sat, 15 Dec 2001 12:51'],
54
+ [true, 'Sat,'] ].each do |wrong, str|
55
+
56
+ h = TMail::HeaderField.new('Date', str)
57
+ assert_equal wrong, h.empty?, str
58
+ assert_equal wrong, h.illegal?, str
59
+ end
60
+ end
61
+
62
+ def test_to_s
63
+ h = TMail::HeaderField.new('Date', 'Tue, 4 Dec 2001 10:49:32 +0900')
64
+ time = Time.parse('Tue, 4 Dec 2001 10:49:32 +0900').strftime("%a,%e %b %Y %H:%M:%S %z")
65
+ assert_equal time, h.to_s
66
+ assert_equal h.to_s, h.decoded
67
+ ok = h.to_s
68
+
69
+ h = TMail::HeaderField.new('Date', 'Tue, 4 Dec 2001 01:49:32 +0000')
70
+ assert_equal ok, h.to_s
71
+
72
+ h = TMail::HeaderField.new('Date', 'Tue, 4 Dec 2001 01:49:32 GMT')
73
+ assert_equal ok, h.to_s
74
+ end
75
+ end
76
+
77
+ class AddressHeaderTester < Test::Unit::TestCase
78
+ def test_s_new
79
+ %w( To Cc Bcc From Reply-To
80
+ Resent-To Resent-Cc Resent-Bcc
81
+ Resent-From Resent-Reply-To ).each do |name|
82
+ h = TMail::HeaderField.new(name, 'aamine@loveruby.net')
83
+ assert_instance_of TMail::AddressHeader, h, name
84
+ end
85
+ end
86
+
87
+ def validate_case( str, isempty, to_s, comments, succ )
88
+ h = TMail::HeaderField.new('To', str)
89
+ assert_equal isempty, h.empty?, str.inspect + " (empty?)\n"
90
+ assert_instance_of Array, h.addrs, str.inspect + " (is a)\n"
91
+ assert_equal succ.size, h.addrs.size, str.inspect + " (size)\n"
92
+ h.addrs.each do |a|
93
+ ok = succ.shift
94
+ assert_equal ok[:phrase], a.phrase, str.inspect + " (phrase)\n"
95
+ assert_equal ok[:routes], a.routes, str.inspect + " (routes)\n"
96
+ assert_equal ok[:spec], a.spec, str.inspect + " (spec)\n"
97
+ end
98
+ if comments.first.respond_to? :force_encoding
99
+ encoding = h.comments.first.encoding
100
+ comments.each { |c| c.force_encoding encoding }
101
+ end
102
+ assert_equal comments, h.comments, str.inspect + " (comments)\n"
103
+ to_s.force_encoding(h.to_s.encoding) if to_s.respond_to? :force_encoding
104
+ assert_equal to_s, h.to_s, str.inspect + " (to_s)\n" if to_s
105
+ assert_equal to_s, h.decoded, str.inspect + " (decoded)\n" if to_s
106
+ end
107
+
108
+ def test_ATTRS
109
+ validate_case 'aamine@loveruby.net',
110
+ false,
111
+ 'aamine@loveruby.net',
112
+ [],
113
+ [{ :phrase => nil,
114
+ :routes => [],
115
+ :spec => 'aamine@loveruby.net' }]
116
+
117
+ validate_case 'Minero Aoki <aamine@loveruby.net> (comment)',
118
+ false,
119
+ 'Minero Aoki <aamine@loveruby.net> (comment)',
120
+ ['comment'],
121
+ [{ :phrase => 'Minero Aoki',
122
+ :routes => [],
123
+ :spec => 'aamine@loveruby.net' }]
124
+
125
+ validate_case 'aamine@loveruby.net, , taro@softica.org',
126
+ false,
127
+ 'aamine@loveruby.net, taro@softica.org',
128
+ [],
129
+ [{ :phrase => nil,
130
+ :routes => [],
131
+ :spec => 'aamine@loveruby.net' },
132
+ { :phrase => nil,
133
+ :routes => [],
134
+ :spec => 'taro@softica.org' }]
135
+
136
+ validate_case '',
137
+ true,
138
+ nil,
139
+ [],
140
+ []
141
+
142
+ validate_case '(comment only)',
143
+ true,
144
+ nil,
145
+ ['comment only'],
146
+ []
147
+
148
+ kcode('EUC') {
149
+ validate_case 'hoge@example.jp (=?ISO-2022-JP?B?GyRCJUYlOSVIGyhC?=)',
150
+ false,
151
+ "hoge@example.jp (\245\306\245\271\245\310)",
152
+ ["\245\306\245\271\245\310"],
153
+ [{ :phrase => nil,
154
+ :routes => [],
155
+ :spec => 'hoge@example.jp'}]
156
+ }
157
+ end
158
+ end
159
+
160
+ class SingleAddressHeaderTester < Test::Unit::TestCase
161
+ def test_s_new
162
+ h = TMail::HeaderField.new('Sender', 'aamine@loveruby.net')
163
+ assert_instance_of TMail::SingleAddressHeader, h
164
+ end
165
+
166
+ def test_addr
167
+ h = TMail::HeaderField.new('Sender', 'aamine@loveruby.net')
168
+ assert_not_nil h.addr
169
+ assert_instance_of TMail::Address, h.addr
170
+ assert_equal 'aamine@loveruby.net', h.addr.spec
171
+ assert_equal nil, h.addr.phrase
172
+ assert_equal [], h.addr.routes
173
+ end
174
+
175
+ def test_to_s
176
+ str = 'Minero Aoki <aamine@loveruby.net>, "AOKI, Minero" <aamine@softica.org>'
177
+ h = TMail::HeaderField.new('Sender', str)
178
+ assert_equal 'Minero Aoki <aamine@loveruby.net>', h.to_s
179
+ end
180
+ end
181
+
182
+ class ReturnPathHeaderTester < Test::Unit::TestCase
183
+ def test_s_new
184
+ %w( Return-Path ).each do |name|
185
+ h = TMail::HeaderField.new(name, '<aamine@loveruby.net>')
186
+ assert_instance_of TMail::ReturnPathHeader, h, name
187
+ assert_equal false, h.empty?
188
+ assert_equal false, h.illegal?
189
+ end
190
+ end
191
+
192
+ def test_ATTRS
193
+ h = TMail::HeaderField.new('Return-Path', '<@a,@b,@c:aamine@loveruby.net>')
194
+ assert_not_nil h.addr
195
+ assert_instance_of TMail::Address, h.addr
196
+ assert_equal 'aamine@loveruby.net', h.addr.spec
197
+ assert_equal nil, h.addr.phrase
198
+ assert_equal ['a', 'b', 'c'], h.addr.routes
199
+
200
+ assert_not_nil h.routes
201
+ assert_instance_of Array, h.routes
202
+ assert_equal ['a', 'b', 'c'], h.routes
203
+ assert_equal h.addr.routes, h.routes
204
+
205
+ assert_not_nil h.spec
206
+ assert_instance_of String, h.spec
207
+ assert_equal 'aamine@loveruby.net', h.spec
208
+
209
+ # missing '<' '>'
210
+ h = TMail::HeaderField.new('Return-Path', 'xxxx@yyyy')
211
+ assert_equal 'xxxx@yyyy', h.spec
212
+
213
+ h = TMail::HeaderField.new('Return-Path', '<>')
214
+ assert_instance_of TMail::Address, h.addr
215
+ assert_nil h.addr.local
216
+ assert_nil h.addr.domain
217
+ assert_nil h.addr.spec
218
+ assert_nil h.spec
219
+ end
220
+
221
+ def test_to_s
222
+ body = 'Minero Aoki <@a,@b,@c:aamine@loveruby.net>'
223
+ h = TMail::HeaderField.new('Return-Path', body)
224
+ assert_equal '<@a,@b,@c:aamine@loveruby.net>', h.to_s
225
+ assert_equal h.to_s, h.decoded
226
+
227
+ body = 'aamine@loveruby.net'
228
+ h = TMail::HeaderField.new('Return-Path', body)
229
+ assert_equal '<aamine@loveruby.net>', h.to_s
230
+ assert_equal h.to_s, h.decoded
231
+
232
+ body = '<>'
233
+ h = TMail::HeaderField.new('Return-Path', body)
234
+ assert_equal '<>', h.to_s
235
+ end
236
+ end
237
+
238
+ class MessageIdHeaderTester < Test::Unit::TestCase
239
+ def test_s_new
240
+ %w( Message-Id MESSAGE-ID Message-ID
241
+ Resent-Message-Id Content-Id ).each do |name|
242
+ h = TMail::HeaderField.new(name, '<20020103xg88.k0@mail.loveruby.net>')
243
+ assert_instance_of TMail::MessageIdHeader, h
244
+ end
245
+ end
246
+
247
+ def test_id
248
+ str = '<20020103xg88.k0@mail.loveruby.net>'
249
+ h = TMail::HeaderField.new('Message-Id', str)
250
+ assert_not_nil h.id
251
+ assert_equal str, h.id
252
+
253
+ id = '<20020103xg88.k0@mail.loveruby.net>'
254
+ str = id + ' (comm(ent))'
255
+ h = TMail::HeaderField.new('Message-Id', str)
256
+ assert_not_nil h.id
257
+ assert_equal id, h.id
258
+ end
259
+
260
+ def test_id=
261
+ h = TMail::HeaderField.new('Message-Id', '')
262
+ h.id = str = '<20020103xg88.k0@mail.loveruby.net>'
263
+ assert_not_nil h.id
264
+ assert_equal str, h.id
265
+ end
266
+ end
267
+
268
+ class ReferencesHeaderTester < Test::Unit::TestCase
269
+ def test_s_new
270
+ str = '<20020103xg88.k0@mail.loveruby.net>'
271
+ %w( References REFERENCES ReFeReNcEs
272
+ In-Reply-To ).each do |name|
273
+ h = TMail::HeaderField.new(name, str)
274
+ assert_instance_of TMail::ReferencesHeader, h, name
275
+ end
276
+ end
277
+
278
+ def test_ATTRS
279
+ id1 = '<20020103xg88.k0@mail.loveruby.net>'
280
+ id2 = '<20011204103415.64DB.GGB03124@nifty.ne.jp>'
281
+ phr = 'message of "Wed, 17 Mar 1999 18:42:07 +0900"'
282
+ str = id1 + ' ' + phr + ' ' + id2
283
+
284
+ h = TMail::HeaderField.new('References', str)
285
+
286
+ ok = [id1, id2]
287
+ h.each_id do |i|
288
+ assert_equal ok.shift, i
289
+ end
290
+ ok = [id1, id2]
291
+ assert_equal ok, h.ids
292
+ h.each_id do |i|
293
+ assert_equal ok.shift, i
294
+ end
295
+
296
+ ok = [phr]
297
+ assert_equal ok, h.phrases
298
+ h.each_phrase do |i|
299
+ assert_equal ok.shift, i
300
+ end
301
+ ok = [phr]
302
+ h.each_phrase do |i|
303
+ assert_equal ok.shift, i
304
+ end
305
+
306
+
307
+ # test 2
308
+ # 'In-Reply-To'
309
+ # 'aamine@dp.u-netsurf.ne.jp's message of "Fri, 8 Jan 1999 03:49:37 +0900"'
310
+ end
311
+
312
+ def test_to_s
313
+ id1 = '<20020103xg88.k0@mail.loveruby.net>'
314
+ id2 = '<20011204103415.64DB.GGB03124@nifty.ne.jp>'
315
+ phr = 'message of "Wed, 17 Mar 1999 18:42:07 +0900"'
316
+ str = id1 + ' ' + phr + ' ' + id2
317
+
318
+ h = TMail::HeaderField.new('References', str)
319
+ assert_equal id1 + ' ' + id2, h.to_s
320
+ end
321
+ end
322
+
323
+ class ReceivedHeaderTester < Test::Unit::TestCase
324
+ HEADER1 = <<EOS
325
+ from helium.ruby-lang.org (helium.ruby-lang.org [210.251.121.214])
326
+ by doraemon.edit.ne.jp (8.12.1/8.12.0) via TCP with ESMTP
327
+ id fB41nwEj007438 for <aamine@mx.edit.ne.jp>;
328
+ Tue, 4 Dec 2001 10:49:58 +0900 (JST)
329
+ EOS
330
+ HEADER2 = <<EOS
331
+ from helium.ruby-lang.org (localhost [127.0.0.1])
332
+ by helium.ruby-lang.org (Postfix) with ESMTP
333
+ id 8F8951AF3F; Tue, 4 Dec 2001 10:49:32 +0900 (JST)
334
+ EOS
335
+ HEADER3 = <<EOS
336
+ from smtp1.dti.ne.jp (smtp1.dti.ne.jp [202.216.228.36])
337
+ by helium.ruby-lang.org (Postfix) with ESMTP id CE3A1C3
338
+ for <ruby-list@ruby-lang.org>; Tue, 4 Dec 2001 10:49:31 +0900 (JST)
339
+ EOS
340
+
341
+ =begin dangerous headers
342
+ # 2-word WITH (this header is also wrong in semantic)
343
+ # I cannot support this.
344
+ Received: by mebius with Microsoft Mail
345
+ id <01BE2B9D.9051EAA0@mebius>; Sat, 19 Dec 1998 22:18:54 -0800
346
+ =end
347
+
348
+ def test_s_new
349
+ %w( Received ).each do |name|
350
+ h = TMail::HeaderField.new(name, HEADER1)
351
+ assert_instance_of TMail::ReceivedHeader, h, name
352
+ end
353
+ end
354
+
355
+ def test_ATTRS
356
+ h = TMail::HeaderField.new('Received', HEADER1)
357
+ assert_instance_of String, h.from
358
+ assert_equal 'helium.ruby-lang.org', h.from
359
+
360
+ assert_instance_of String, h.by
361
+ assert_equal 'doraemon.edit.ne.jp', h.by
362
+
363
+ assert_instance_of String, h.via
364
+ assert_equal 'TCP', h.via
365
+
366
+ assert_instance_of Array, h.with
367
+ assert_equal %w(ESMTP), h.with
368
+
369
+ assert_instance_of String, h.id
370
+ assert_equal 'fB41nwEj007438', h.id
371
+
372
+ assert_instance_of String, h._for
373
+ assert_equal 'aamine@mx.edit.ne.jp', h._for # must be <a> ?
374
+
375
+ assert_instance_of Time, h.date
376
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900')
377
+ assert_equal time, h.date
378
+
379
+ h = TMail::HeaderField.new('Received', '; Tue, 4 Dec 2001 10:49:58 +0900')
380
+ assert_nil h.from
381
+ assert_nil h.by
382
+ assert_nil h.via
383
+ assert_equal [], h.with
384
+ assert_nil h.id
385
+ assert_nil h._for
386
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900')
387
+ assert_equal time, h.date
388
+
389
+ # without date
390
+ h = TMail::HeaderField.new('Received', 'by NeXT.Mailer (1.144.2)')
391
+ assert_nil h.from
392
+ assert_equal 'NeXT.Mailer', h.by
393
+ assert_nil h.via
394
+ assert_equal [], h.with
395
+ assert_nil h.id
396
+ assert_nil h._for
397
+ assert_nil h.date
398
+
399
+ # FROM is not a domain
400
+ h = TMail::HeaderField.new('Received',
401
+ 'from someuser@example.com; Tue, 24 Nov 1998 07:59:39 -0500')
402
+ assert_equal 'example.com', h.from
403
+ assert_nil h.by
404
+ assert_nil h.via
405
+ assert_equal [], h.with
406
+ assert_nil h.id
407
+ assert_nil h._for
408
+ time = Time.parse('Tue, 24 Nov 1998 07:59:39 -0500')
409
+ assert_equal time, h.date
410
+
411
+ =begin
412
+ # FOR is not route-addr.
413
+ # item order is wrong.
414
+ h = TMail::HeaderField.new('Received',
415
+ 'from aamine by mail.softica.org with local for list@softica.org id 12Vm3N-00044L-01; Fri, 17 Mar 2000 10:59:53 +0900')
416
+ assert_equal 'aamine', h.from
417
+ assert_equal 'mail.softica.org', h.by
418
+ assert_nil h.via
419
+ assert_equal ['local'], h.with
420
+ assert_equal '12Vm3N-00044L-01', h.id
421
+ assert_equal 'list@softica.org', h._for
422
+ assert_equal Time.local(2000,4,17, 10,59,53), h.date
423
+ =end
424
+
425
+ # word + domain-literal in FROM
426
+
427
+ h = TMail::HeaderField.new('Received',
428
+ 'from localhost [192.168.1.1]; Sat, 19 Dec 1998 22:19:50 PST')
429
+ assert_equal 'localhost', h.from
430
+ assert_nil h.by
431
+ assert_nil h.via
432
+ assert_equal [], h.with
433
+ assert_nil h.id
434
+ assert_nil h._for
435
+ time = Time.parse('Sat, 19 Dec 1998 22:19:50 PST')
436
+ assert_equal time, h.date
437
+
438
+ # addr-spec in BY (must be a domain)
439
+ h = TMail::HeaderField.new('Received',
440
+ 'by aamine@loveruby.net; Wed, 24 Feb 1999 14:34:20 +0900')
441
+ assert_equal 'loveruby.net', h.by
442
+ end
443
+
444
+ def test_to_s
445
+ h = TMail::HeaderField.new('Received', HEADER1)
446
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900').strftime("%a,%e %b %Y %H:%M:%S %z")
447
+ assert_equal "from helium.ruby-lang.org by doraemon.edit.ne.jp via TCP with ESMTP id fB41nwEj007438 for <aamine@mx.edit.ne.jp>; #{time}", h.to_s
448
+
449
+ [
450
+ 'from harmony.loveruby.net',
451
+ 'by mail.loveruby.net',
452
+ 'via TCP',
453
+ 'with ESMTP',
454
+ 'id LKJHSDFG',
455
+ 'for <aamine@loveruby.net>',
456
+ "; #{time}"
457
+ ]\
458
+ .each do |str|
459
+ h = TMail::HeaderField.new('Received', str)
460
+ assert_equal str, h.to_s, 'ReceivedHeader#to_s: data=' + str.dump
461
+ end
462
+ end
463
+ end
464
+
465
+ class KeywordsHeaderTester < Test::Unit::TestCase
466
+ def test_s_new
467
+ %w( Keywords KEYWORDS KeYwOrDs ).each do |name|
468
+ h = TMail::HeaderField.new(name, 'key, word, is, keyword')
469
+ assert_instance_of TMail::KeywordsHeader, h
470
+ end
471
+ end
472
+
473
+ def test_keys
474
+ h = TMail::HeaderField.new('Keywords', 'key, word, is, keyword')
475
+ assert_instance_of Array, h.keys
476
+ assert_equal %w(key word is keyword), h.keys
477
+ end
478
+ end
479
+
480
+ class EncryptedHeaderTester < Test::Unit::TestCase
481
+ def test_s_new
482
+ %w( Encrypted ).each do |name|
483
+ h = TMail::HeaderField.new(name, 'lot17 solt')
484
+ assert_instance_of TMail::EncryptedHeader, h
485
+ end
486
+ end
487
+
488
+ def test_encrypter
489
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
490
+ assert_equal 'lot17', h.encrypter
491
+ end
492
+
493
+ def test_encrypter=
494
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
495
+ h.encrypter = 'newscheme'
496
+ assert_equal 'newscheme', h.encrypter
497
+ end
498
+
499
+ def test_keyword
500
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
501
+ assert_equal 'solt', h.keyword
502
+ h = TMail::HeaderField.new('Encrypted', 'lot17')
503
+ assert_equal nil, h.keyword
504
+ end
505
+
506
+ def test_keyword=
507
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
508
+ h.keyword = 'newscheme'
509
+ assert_equal 'newscheme', h.keyword
510
+ end
511
+ end
512
+
513
+ class MimeVersionHeaderTester < Test::Unit::TestCase
514
+ def test_s_new
515
+ %w( Mime-Version MIME-VERSION MiMe-VeRsIoN ).each do |name|
516
+ h = TMail::HeaderField.new(name, '1.0')
517
+ assert_instance_of TMail::MimeVersionHeader, h
518
+ end
519
+ end
520
+
521
+ def test_ATTRS
522
+ h = TMail::HeaderField.new('Mime-Version', '1.0')
523
+ assert_equal 1, h.major
524
+ assert_equal 0, h.minor
525
+ assert_equal '1.0', h.version
526
+
527
+ h = TMail::HeaderField.new('Mime-Version', '99.77 (is ok)')
528
+ assert_equal 99, h.major
529
+ assert_equal 77, h.minor
530
+ assert_equal '99.77', h.version
531
+ end
532
+
533
+ def test_major=
534
+ h = TMail::HeaderField.new('Mime-Version', '1.1')
535
+ h.major = 2
536
+ assert_equal 2, h.major
537
+ assert_equal 1, h.minor
538
+ assert_equal 2, h.major
539
+ h.major = 3
540
+ assert_equal 3, h.major
541
+ end
542
+
543
+ def test_minor=
544
+ h = TMail::HeaderField.new('Mime-Version', '2.3')
545
+ assert_equal 3, h.minor
546
+ h.minor = 5
547
+ assert_equal 5, h.minor
548
+ assert_equal 2, h.major
549
+ end
550
+
551
+ def test_to_s
552
+ h = TMail::HeaderField.new('Mime-Version', '1.0 (first version)')
553
+ assert_equal '1.0', h.to_s
554
+ end
555
+
556
+ def test_empty?
557
+ h = TMail::HeaderField.new('Mime-Version', '')
558
+ assert_equal true, h.empty?
559
+ end
560
+ end
561
+
562
+ class ContentTypeHeaderTester < Test::Unit::TestCase
563
+ def test_s_new
564
+ %w( Content-Type CONTENT-TYPE CoNtEnT-TyPe ).each do |name|
565
+ h = TMail::HeaderField.new(name, 'text/plain; charset=iso-2022-jp')
566
+ assert_instance_of TMail::ContentTypeHeader, h, name
567
+ end
568
+ end
569
+
570
+ def test_ATTRS
571
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
572
+ assert_equal 'text', h.main_type
573
+ assert_equal 'plain', h.sub_type
574
+ assert_equal 1, h.params.size
575
+ assert_equal 'iso-2022-jp', h.params['charset']
576
+
577
+ h = TMail::HeaderField.new('Content-Type', 'Text/Plain; Charset=shift_jis')
578
+ assert_equal 'text', h.main_type
579
+ assert_equal 'plain', h.sub_type
580
+ assert_equal 1, h.params.size
581
+ assert_equal 'shift_jis', h.params['charset']
582
+ end
583
+
584
+ def test_multipart_with_legal_unquoted_boundary
585
+ h = TMail::HeaderField.new('Content-Type', 'multipart/mixed; boundary=dDRMvlgZJXvWKvBx')
586
+ assert_equal 'multipart', h.main_type
587
+ assert_equal 'mixed', h.sub_type
588
+ assert_equal 1, h.params.size
589
+ assert_equal 'dDRMvlgZJXvWKvBx', h.params['boundary']
590
+ end
591
+
592
+ def test_multipart_with_legal_quoted_boundary_should_retain_quotations
593
+ h = TMail::HeaderField.new('Content-Type', 'multipart/mixed; boundary="dDRMvlgZJXvWKvBx"')
594
+ assert_equal 'multipart', h.main_type
595
+ assert_equal 'mixed', h.sub_type
596
+ assert_equal 1, h.params.size
597
+ assert_equal 'dDRMvlgZJXvWKvBx', h.params['boundary']
598
+ end
599
+
600
+ def test_multipart_with_illegal_unquoted_boundary_should_add_quotations
601
+ h = TMail::HeaderField.new('Content-Type', 'multipart/alternative; boundary=----=_=NextPart_000_0093_01C81419.EB75E850')
602
+ assert_equal 'multipart', h.main_type
603
+ assert_equal 'alternative', h.sub_type
604
+ assert_equal 1, h.params.size
605
+ assert_equal '----=_=NextPart_000_0093_01C81419.EB75E850', h.params['boundary']
606
+ end
607
+
608
+ def test_multipart_with_illegal_quoted_boundary_should_retain_quotations
609
+ h = TMail::HeaderField.new('Content-Type', 'multipart/alternative; boundary="----=_=NextPart_000_0093_01C81419.EB75E850"')
610
+ assert_equal 'multipart', h.main_type
611
+ assert_equal 'alternative', h.sub_type
612
+ assert_equal 1, h.params.size
613
+ assert_equal '----=_=NextPart_000_0093_01C81419.EB75E850', h.params['boundary']
614
+ end
615
+
616
+ def test_multipart_with_extra_with_multiple_params
617
+ h = TMail::HeaderField.new('Content-Type', 'multipart/related;boundary=1_4626B816_9F1690;Type="application/smil";Start="<mms.smil.txt>"')
618
+ assert_equal 'multipart', h.main_type
619
+ assert_equal 'related', h.sub_type
620
+ assert_equal 3, h.params.size
621
+ assert_equal '1_4626B816_9F1690', h.params['boundary']
622
+ end
623
+
624
+ def test_main_type=
625
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
626
+ assert_equal 'text', h.main_type
627
+ h.main_type = 'multipart'
628
+ assert_equal 'multipart', h.main_type
629
+ assert_equal 'multipart', h.main_type
630
+ h.main_type = 'TEXT'
631
+ assert_equal 'text', h.main_type
632
+ end
633
+
634
+ def test_sub_type=
635
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
636
+ assert_equal 'plain', h.sub_type
637
+ h.sub_type = 'html'
638
+ assert_equal 'html', h.sub_type
639
+ h.sub_type = 'PLAIN'
640
+ assert_equal 'plain', h.sub_type
641
+ end
642
+ end
643
+
644
+ class ContentEncodingHeaderTester < Test::Unit::TestCase
645
+ def test_s_new
646
+ %w( Content-Transfer-Encoding CONTENT-TRANSFER-ENCODING
647
+ COnteNT-TraNSFer-ENCodiNG ).each do |name|
648
+ h = TMail::HeaderField.new(name, 'Base64')
649
+ assert_instance_of TMail::ContentTransferEncodingHeader, h
650
+ end
651
+ end
652
+
653
+ def test_encoding
654
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
655
+ assert_equal 'base64', h.encoding
656
+
657
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', '7bit')
658
+ assert_equal '7bit', h.encoding
659
+ end
660
+
661
+ def test_encoding=
662
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
663
+ assert_equal 'base64', h.encoding
664
+ h.encoding = '7bit'
665
+ assert_equal '7bit', h.encoding
666
+ end
667
+
668
+ def test_to_s
669
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
670
+ assert_equal 'Base64', h.to_s
671
+ assert_equal h.to_s, h.decoded
672
+ assert_equal h.to_s, h.encoded
673
+ end
674
+
675
+ def test_insertion_of_headers_and_encoding_them_short
676
+ mail = TMail::Mail.new
677
+ mail['X-Mail-Header'] = "short bit of data"
678
+ assert_equal("X-Mail-Header: short bit of data\r\n\r\n", mail.encoded)
679
+ end
680
+
681
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_with_whitespace
682
+ mail = TMail::Mail.new
683
+ mail['X-Ruby-Talk'] = "<11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA 4614-95FD-9071A4BDF4A1@grayproductions.net>"
684
+ assert_equal("X-Ruby-Talk: <11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA\r\n\t4614-95FD-9071A4BDF4A1@grayproductions.net>\r\n\r\n", mail.encoded)
685
+ result = TMail::Mail.parse(mail.encoded)
686
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
687
+ end
688
+
689
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_with_whitespace
690
+ mail = TMail::Mail.new
691
+ mail['X-Ruby-Talk'] = "<11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA 4614-95FD-9071A4BDF4A1@grayproductions.net11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA 4614-95FD-9071A4BDF4A1@grayproductions.net>"
692
+ assert_equal("X-Ruby-Talk: <11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA\r\n\t4614-95FD-9071A4BDF4A1@grayproductions.net11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA\r\n\t4614-95FD-9071A4BDF4A1@grayproductions.net>\r\n\r\n", mail.encoded)
693
+ result = TMail::Mail.parse(mail.encoded)
694
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
695
+ end
696
+
697
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_without_whitespace
698
+ mail = TMail::Mail.new
699
+ mail['X-Ruby-Talk'] = "<11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA-4614-95FD-9071A4BDF4A1@grayproductions.net>"
700
+ assert_equal("X-Ruby-Talk: <11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA-4614-95FD-9071A4BDF4A1@grayproductions.net>\r\n\r\n", mail.encoded)
701
+ result = TMail::Mail.parse(mail.encoded)
702
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
703
+ end
704
+
705
+ def test_insertion_of_headers_and_encoding_them_less_than_998_char_total_without_whitespace
706
+ mail = TMail::Mail.new
707
+ text_with_whitespace = ""; 985.times{text_with_whitespace << "a"}
708
+ mail['Reply-To'] = "#{text_with_whitespace}"
709
+ assert_equal("Reply-To: #{text_with_whitespace}\r\n\r\n", mail.encoded)
710
+ result = TMail::Mail.parse(mail.encoded)
711
+ assert_equal(mail['Reply-To'].to_s, result['Reply-To'].to_s)
712
+ end
713
+
714
+ def test_insertion_of_headers_and_encoding_them_more_than_998_char_total_without_whitespace
715
+ mail = TMail::Mail.new
716
+ text_with_whitespace = ""; 1200.times{text_with_whitespace << "a"}
717
+ before_text = ""; 985.times{before_text << "a"}
718
+ after_text = ""; 215.times{after_text << "a"}
719
+ mail['X-Ruby-Talk'] = "#{text_with_whitespace}"
720
+ assert_equal("X-Ruby-Talk: #{before_text}\r\n\t#{after_text}\r\n\r\n", mail.encoded)
721
+ end
722
+
723
+ def test_insertion_of_headers_and_encoding_with_1_more_than_998_char_total_without_whitespace
724
+ mail = TMail::Mail.new
725
+ text_with_whitespace = ""; 996.times{text_with_whitespace << "a"}
726
+ before_text = ""; 995.times{before_text << "a"}
727
+ after_text = ""; 1.times{after_text << "a"}
728
+ mail['X'] = "#{text_with_whitespace}"
729
+ assert_equal("X: #{before_text}\r\n\t#{after_text}\r\n\r\n", mail.encoded)
730
+ end
731
+
732
+ def test_insertion_of_headers_and_encoding_with_exactly_998_char_total_without_whitespace
733
+ mail = TMail::Mail.new
734
+ text_with_whitespace = ""; 995.times{text_with_whitespace << "a"}
735
+ before_text = ""; 995.times{before_text << "a"}
736
+ mail['X'] = "#{text_with_whitespace}"
737
+ assert_equal("X: #{before_text}\r\n\r\n", mail.encoded)
738
+ end
739
+ end
740
+
741
+ class ContentDispositionHeaderTester < Test::Unit::TestCase
742
+ def test_s_new
743
+ %w( Content-Disposition CONTENT-DISPOSITION
744
+ ConTENt-DIsPOsition ).each do |name|
745
+ h = TMail::HeaderField.new(name, 'attachment; filename="README.txt.pif"')
746
+ assert_instance_of TMail::ContentDispositionHeader, h
747
+ end
748
+ end
749
+
750
+ def test_ATTRS
751
+ begin
752
+ _test_ATTRS
753
+ _test_tspecials
754
+ _test_rfc2231_decode
755
+ #_test_rfc2231_encode
756
+ _test_raw_iso2022jp
757
+ _test_raw_eucjp
758
+ _test_raw_sjis
759
+ _test_code_conversion
760
+ ensure
761
+ TMail.KCODE = 'NONE'
762
+ end
763
+ end
764
+
765
+ def _test_ATTRS
766
+ TMail.KCODE = 'NONE'
767
+
768
+ h = TMail::HeaderField.new('Content-Disposition',
769
+ 'attachment; filename="README.txt.pif"')
770
+ assert_equal 'attachment', h.disposition
771
+ assert_equal 1, h.params.size
772
+ assert_equal 'README.txt.pif', h.params['filename']
773
+
774
+ h = TMail::HeaderField.new('Content-Disposition',
775
+ 'attachment; Filename="README.txt.pif"')
776
+ assert_equal 'attachment', h.disposition
777
+ assert_equal 1, h.params.size
778
+ assert_equal 'README.txt.pif', h.params['filename']
779
+
780
+ h = TMail::HeaderField.new('Content-Disposition',
781
+ 'attachment; filename=')
782
+ assert_equal true, h.empty?
783
+ assert_nil h.params
784
+ assert_nil h['filename']
785
+ end
786
+
787
+ def _test_tspecials
788
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
789
+ h['n'] = %q|()<>[];:@\\,"/?=|
790
+ assert_equal 'a; n="()<>[];:@\\\\,\"/?="', h.encoded
791
+ end
792
+
793
+ def _test_rfc2231_decode
794
+ TMail.KCODE = 'EUC'
795
+
796
+ h = TMail::HeaderField.new('Content-Disposition',
797
+ "attachment; filename*=iso-2022-jp'ja'%1b$B$Q$i$`%1b%28B")
798
+ assert_equal 'attachment', h.disposition
799
+ assert_equal 1, h.params.size
800
+ expected = "\244\321\244\351\244\340"
801
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
802
+ assert_equal expected, h.params['filename']
803
+ end
804
+
805
+ def _test_rfc2231_encode
806
+ TMail.KCODE = 'EUC'
807
+
808
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
809
+ h['n'] = "\245\265\245\363\245\327\245\353.txt"
810
+ assert_equal "a; n*=iso-2022-jp'ja'%1B$B%255%25s%25W%25k%1B%28B.txt",
811
+ h.encoded
812
+
813
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
814
+ h['n'] = "\245\265()<>[];:@\\,\"/?=%*'"
815
+ assert_equal "a;\r\n\tn*=iso-2022-jp'ja'%1B$B%255%1B%28B%28%29%3C%3E%5B%5D%3B%3A%40%5C%2C%22%2F%3F%3D%25%2A%27",
816
+ h.encoded
817
+ end
818
+
819
+ def _test_raw_iso2022jp
820
+ TMail.KCODE = 'EUC'
821
+ # raw iso2022jp string in value (token)
822
+ h = TMail::HeaderField.new('Content-Disposition',
823
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
824
+ assert_equal 'attachment', h.disposition
825
+ assert_equal 1, h.params.size
826
+ # assert_equal "\e$BF|K\\8l\e(B.doc", h.params['filename']
827
+
828
+ expected = "\306\374\313\334\270\354.doc"
829
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
830
+
831
+ assert_equal expected, h.params['filename']
832
+
833
+ # raw iso2022jp string in value (quoted string)
834
+ h = TMail::HeaderField.new('Content-Disposition',
835
+ %Q<attachment; filename="\e$BF|K\\8l\e(B.doc">)
836
+ assert_equal 'attachment', h.disposition
837
+ assert_equal 1, h.params.size
838
+ # assert_equal "\e$BF|K\\8l\e(B.doc", h.params['filename']
839
+ assert_equal expected, h.params['filename']
840
+ end
841
+
842
+ def _test_raw_eucjp
843
+ TMail.KCODE = 'EUC'
844
+ # raw EUC-JP string in value (token)
845
+ h = TMail::HeaderField.new('Content-Disposition',
846
+ %Q<attachment; filename=\306\374\313\334\270\354.doc>)
847
+ assert_equal 'attachment', h.disposition
848
+ assert_equal 1, h.params.size
849
+ expected = "\306\374\313\334\270\354.doc"
850
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
851
+ assert_equal expected, h.params['filename']
852
+
853
+ # raw EUC-JP string in value (quoted-string)
854
+ h = TMail::HeaderField.new('Content-Disposition',
855
+ %Q<attachment; filename="\306\374\313\334\270\354.doc">)
856
+ assert_equal 'attachment', h.disposition
857
+ assert_equal 1, h.params.size
858
+ assert_equal expected, h.params['filename']
859
+ end
860
+
861
+ def _test_raw_sjis
862
+ TMail.KCODE = 'SJIS'
863
+ # raw SJIS string in value (token)
864
+ h = TMail::HeaderField.new('Content-Disposition',
865
+ %Q<attachment; filename=\223\372\226{\214\352.doc>)
866
+ assert_equal 'attachment', h.disposition
867
+ assert_equal 1, h.params.size
868
+ expected = "\223\372\226{\214\352.doc"
869
+ expected.force_encoding 'Windows-31J' if expected.respond_to? :force_encoding
870
+ assert_equal expected, h.params['filename']
871
+
872
+ # raw SJIS string in value (quoted-string)
873
+ h = TMail::HeaderField.new('Content-Disposition',
874
+ %Q<attachment; filename="\223\372\226{\214\352.doc">)
875
+ assert_equal 'attachment', h.disposition
876
+ assert_equal 1, h.params.size
877
+ assert_equal expected, h.params['filename']
878
+ end
879
+
880
+ def _test_code_conversion
881
+ # JIS -> TMail.KCODE auto conversion
882
+ TMail.KCODE = 'EUC'
883
+ h = TMail::HeaderField.new('Content-Disposition',
884
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
885
+ assert_equal 'attachment', h.disposition
886
+ assert_equal 1, h.params.size
887
+ expected = "\306\374\313\334\270\354.doc"
888
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
889
+ assert_equal expected, h.params['filename']
890
+
891
+ TMail.KCODE = 'SJIS'
892
+ h = TMail::HeaderField.new('Content-Disposition',
893
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
894
+ assert_equal 'attachment', h.disposition
895
+ assert_equal 1, h.params.size
896
+ expected = "\223\372\226{\214\352.doc"
897
+ expected.force_encoding 'Windows-31J' if expected.respond_to? :force_encoding
898
+ assert_equal expected, h.params['filename']
899
+ end
900
+
901
+ def test_disposition=
902
+ h = TMail::HeaderField.new('Content-Disposition',
903
+ 'attachment; filename="README.txt.pif"')
904
+ assert_equal 'attachment', h.disposition
905
+ h.disposition = 'virus'
906
+ assert_equal 'virus', h.disposition
907
+ h.disposition = 'AtTaChMeNt'
908
+ assert_equal 'attachment', h.disposition
909
+ end
910
+
911
+ def test_wrong_mail_header
912
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email9")
913
+ assert_raise(TMail::SyntaxError) { TMail::Mail.parse(fixture) }
914
+ end
915
+
916
+ def test_decode_message_with_unknown_charset
917
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email10")
918
+ mail = TMail::Mail.parse(fixture)
919
+ assert_nothing_raised { mail.body }
920
+ end
921
+
922
+ def test_decode_message_with_unquoted_atchar_in_header
923
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email11")
924
+ mail = TMail::Mail.parse(fixture)
925
+ assert_not_nil mail.from
926
+ end
927
+
928
+ def test_new_from_port_should_produce_a_header_object_of_the_correct_class
929
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
930
+ h = TMail::HeaderField.new_from_port(p, 'Message-Id')
931
+ assert_equal(TMail::MessageIdHeader, h.class)
932
+ end
933
+
934
+ def test_should_return_the_evelope_sender_when_given_from_without_a_colon
935
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
936
+ h = TMail::HeaderField.new_from_port(p, 'EnvelopeSender')
937
+ assert_equal("mike@envelope_sender.com.au", h.addrs.join)
938
+ end
939
+
940
+ def test_new_from_port_should_produce_a_header_object_that_contains_the_right_data
941
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
942
+ h = TMail::HeaderField.new_from_port(p, 'From')
943
+ assert_equal("Mikel Lindsaar <mikel@from_address.com>", h.addrs.join)
944
+ end
945
+
946
+ def test_unwrapping_a_long_header_field_using_new_from_port
947
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
948
+ h = TMail::HeaderField.new_from_port(p, 'Content-Type')
949
+ line = 'multipart/signed; protocol="application/pkcs7-signature"; boundary=Apple-Mail-42-587703407; micalg=sha1'
950
+ assert(line =~ /multipart\/signed/)
951
+ assert(line =~ /protocol="application\/pkcs7-signature"/)
952
+ assert(line =~ /boundary=Apple-Mail-42-587703407/)
953
+ assert(line =~ /micalg=sha1/)
954
+ assert_equal(line.length, 103)
955
+ end
956
+
957
+ def test_returning_nil_if_there_is_no_match
958
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
959
+ h = TMail::HeaderField.new_from_port(p, 'Received-Long-Header')
960
+ assert_equal(h, nil)
961
+ end
962
+
963
+ def test_multi_address_header_in_tmail
964
+ h = TMail::Mail.new
965
+ h.to = "Mikel@me.com, mikel@you.com"
966
+ assert_equal("To: Mikel@me.com,\r\n\t mikel@you.com\r\n\r\n", h.encoded)
967
+ end
968
+
969
+ end