japetheape-tmail 1.2.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. data/CHANGES +74 -0
  2. data/LICENSE +21 -0
  3. data/NOTES +7 -0
  4. data/README +169 -0
  5. data/Rakefile +2 -0
  6. data/ext/Makefile +20 -0
  7. data/ext/tmailscanner/tmail/MANIFEST +4 -0
  8. data/ext/tmailscanner/tmail/depend +1 -0
  9. data/ext/tmailscanner/tmail/extconf.rb +33 -0
  10. data/ext/tmailscanner/tmail/tmailscanner.c +607 -0
  11. data/lib/tmail.rb +5 -0
  12. data/lib/tmail/Makefile +18 -0
  13. data/lib/tmail/address.rb +392 -0
  14. data/lib/tmail/attachments.rb +46 -0
  15. data/lib/tmail/base64.rb +46 -0
  16. data/lib/tmail/compat.rb +41 -0
  17. data/lib/tmail/config.rb +67 -0
  18. data/lib/tmail/core_extensions.rb +63 -0
  19. data/lib/tmail/encode.rb +591 -0
  20. data/lib/tmail/header.rb +960 -0
  21. data/lib/tmail/index.rb +9 -0
  22. data/lib/tmail/interface.rb +1152 -0
  23. data/lib/tmail/loader.rb +3 -0
  24. data/lib/tmail/mail.rb +591 -0
  25. data/lib/tmail/mailbox.rb +496 -0
  26. data/lib/tmail/main.rb +6 -0
  27. data/lib/tmail/mbox.rb +3 -0
  28. data/lib/tmail/net.rb +250 -0
  29. data/lib/tmail/obsolete.rb +132 -0
  30. data/lib/tmail/parser.rb +1060 -0
  31. data/lib/tmail/parser.y +416 -0
  32. data/lib/tmail/port.rb +379 -0
  33. data/lib/tmail/quoting.rb +125 -0
  34. data/lib/tmail/require_arch.rb +58 -0
  35. data/lib/tmail/scanner.rb +49 -0
  36. data/lib/tmail/scanner_r.rb +261 -0
  37. data/lib/tmail/stringio.rb +280 -0
  38. data/lib/tmail/utils.rb +337 -0
  39. data/lib/tmail/version.rb +39 -0
  40. data/log/BugTrackingLog.txt +1245 -0
  41. data/log/Changelog.txt +534 -0
  42. data/log/Testlog.txt +2340 -0
  43. data/log/Todo.txt +30 -0
  44. data/meta/MANIFEST +128 -0
  45. data/meta/VERSION +1 -0
  46. data/meta/project.yaml +30 -0
  47. data/meta/unixname +1 -0
  48. data/sample/bench_base64.rb +48 -0
  49. data/sample/data/multipart +23 -0
  50. data/sample/data/normal +29 -0
  51. data/sample/data/sendtest +5 -0
  52. data/sample/data/simple +14 -0
  53. data/sample/data/test +27 -0
  54. data/sample/extract-attachements.rb +33 -0
  55. data/sample/from-check.rb +26 -0
  56. data/sample/multipart.rb +26 -0
  57. data/sample/parse-bench.rb +68 -0
  58. data/sample/parse-test.rb +19 -0
  59. data/sample/sendmail.rb +94 -0
  60. data/setup.rb +1482 -0
  61. data/site/contributing/index.html +183 -0
  62. data/site/css/clean.css +27 -0
  63. data/site/css/layout.css +31 -0
  64. data/site/css/style.css +60 -0
  65. data/site/download/index.html +61 -0
  66. data/site/img/envelope.jpg +0 -0
  67. data/site/img/mailman.gif +0 -0
  68. data/site/img/stamp-sm.jpg +0 -0
  69. data/site/img/stamp.jpg +0 -0
  70. data/site/img/stampborder.jpg +0 -0
  71. data/site/img/tfire.jpg +0 -0
  72. data/site/img/tmail.png +0 -0
  73. data/site/index.html +270 -0
  74. data/site/js/jquery.js +31 -0
  75. data/site/log/Changelog.xsl +33 -0
  76. data/site/log/changelog.xml +1677 -0
  77. data/site/outdated/BUGS +3 -0
  78. data/site/outdated/DEPENDS +1 -0
  79. data/site/outdated/Incompatibilities +89 -0
  80. data/site/outdated/Incompatibilities.ja +102 -0
  81. data/site/outdated/NEWS +9 -0
  82. data/site/outdated/README.ja +73 -0
  83. data/site/outdated/doc.ja/address.html +275 -0
  84. data/site/outdated/doc.ja/basics.html +405 -0
  85. data/site/outdated/doc.ja/config.html +49 -0
  86. data/site/outdated/doc.ja/details.html +146 -0
  87. data/site/outdated/doc.ja/index.html +39 -0
  88. data/site/outdated/doc.ja/mail.html +793 -0
  89. data/site/outdated/doc.ja/mailbox.html +265 -0
  90. data/site/outdated/doc.ja/port.html +95 -0
  91. data/site/outdated/doc.ja/tmail.html +58 -0
  92. data/site/outdated/doc.ja/usage.html +202 -0
  93. data/site/outdated/rdd/address.rrd.m +229 -0
  94. data/site/outdated/rdd/basics.rd.m +275 -0
  95. data/site/outdated/rdd/config.rrd.m +26 -0
  96. data/site/outdated/rdd/details.rd.m +117 -0
  97. data/site/outdated/rdd/index.rhtml.m +54 -0
  98. data/site/outdated/rdd/mail.rrd.m +701 -0
  99. data/site/outdated/rdd/mailbox.rrd.m +228 -0
  100. data/site/outdated/rdd/port.rrd.m +69 -0
  101. data/site/outdated/rdd/tmail.rrd.m +33 -0
  102. data/site/outdated/rdd/usage.rd.m +247 -0
  103. data/site/quickstart/index.html +69 -0
  104. data/site/quickstart/quickstart.html +52 -0
  105. data/site/quickstart/usage.html +193 -0
  106. data/site/reference/address.html +247 -0
  107. data/site/reference/config.html +30 -0
  108. data/site/reference/index.html +101 -0
  109. data/site/reference/mail.html +726 -0
  110. data/site/reference/mailbox.html +245 -0
  111. data/site/reference/port.html +75 -0
  112. data/site/reference/tmail.html +35 -0
  113. data/test/extctrl.rb +6 -0
  114. data/test/fixtures/mailbox +414 -0
  115. data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
  116. data/test/fixtures/mailbox_without_from +11 -0
  117. data/test/fixtures/mailbox_without_return_path +12 -0
  118. data/test/fixtures/raw_attack_email_with_zero_length_whitespace +29 -0
  119. data/test/fixtures/raw_base64_decoded_string +0 -0
  120. data/test/fixtures/raw_base64_email +83 -0
  121. data/test/fixtures/raw_base64_encoded_string +1 -0
  122. data/test/fixtures/raw_email +14 -0
  123. data/test/fixtures/raw_email10 +20 -0
  124. data/test/fixtures/raw_email11 +34 -0
  125. data/test/fixtures/raw_email12 +32 -0
  126. data/test/fixtures/raw_email13 +29 -0
  127. data/test/fixtures/raw_email2 +114 -0
  128. data/test/fixtures/raw_email3 +70 -0
  129. data/test/fixtures/raw_email4 +59 -0
  130. data/test/fixtures/raw_email5 +19 -0
  131. data/test/fixtures/raw_email6 +20 -0
  132. data/test/fixtures/raw_email7 +66 -0
  133. data/test/fixtures/raw_email8 +47 -0
  134. data/test/fixtures/raw_email9 +28 -0
  135. data/test/fixtures/raw_email_multiple_from +30 -0
  136. data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
  137. data/test/fixtures/raw_email_reply +32 -0
  138. data/test/fixtures/raw_email_simple +11 -0
  139. data/test/fixtures/raw_email_with_bad_date +48 -0
  140. data/test/fixtures/raw_email_with_double_carriage_return +179 -0
  141. data/test/fixtures/raw_email_with_illegal_boundary +58 -0
  142. data/test/fixtures/raw_email_with_mimepart_without_content_type +94 -0
  143. data/test/fixtures/raw_email_with_multipart_mixed_quoted_boundary +50 -0
  144. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  145. data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
  146. data/test/fixtures/raw_email_with_quoted_illegal_boundary +58 -0
  147. data/test/kcode.rb +14 -0
  148. data/test/temp_test_one.rb +46 -0
  149. data/test/test_address.rb +1219 -0
  150. data/test/test_attachments.rb +76 -0
  151. data/test/test_base64.rb +64 -0
  152. data/test/test_encode.rb +85 -0
  153. data/test/test_header.rb +1002 -0
  154. data/test/test_helper.rb +9 -0
  155. data/test/test_mail.rb +768 -0
  156. data/test/test_mbox.rb +184 -0
  157. data/test/test_port.rb +436 -0
  158. data/test/test_quote.rb +107 -0
  159. data/test/test_scanner.rb +209 -0
  160. data/test/test_utils.rb +36 -0
  161. data/work/script/make +26 -0
  162. data/work/script/rdoc +39 -0
  163. data/work/script/setup +1616 -0
  164. data/work/script/test +30 -0
  165. metadata +298 -0
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+ require 'tmail'
4
+
5
+ class TestAttachments < Test::Unit::TestCase
6
+
7
+ def test_attachment
8
+ mail = TMail::Mail.new
9
+ mail.mime_version = "1.0"
10
+ mail.set_content_type 'multipart', 'mixed', {'boundary' => 'Apple-Mail-13-196941151'}
11
+ mail.body =<<HERE
12
+ --Apple-Mail-13-196941151
13
+ Content-Transfer-Encoding: quoted-printable
14
+ Content-Type: text/plain;
15
+ charset=ISO-8859-1;
16
+ delsp=yes;
17
+ format=flowed
18
+
19
+ This is the first part.
20
+
21
+ --Apple-Mail-13-196941151
22
+ Content-Type: text/x-ruby-script; name="hello.rb"
23
+ Content-Transfer-Encoding: 7bit
24
+ Content-Disposition: attachment;
25
+ filename="api.rb"
26
+
27
+ puts "Hello, world!"
28
+ gets
29
+
30
+ --Apple-Mail-13-196941151--
31
+ HERE
32
+ assert_equal(true, mail.multipart?)
33
+ assert_equal(1, mail.attachments.length)
34
+ end
35
+
36
+ def test_recursive_multipart_processing
37
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email7")
38
+ mail = TMail::Mail.parse(fixture)
39
+ assert_equal "This is the first part.\n\nAttachment: test.rb\nAttachment: test.pdf\n\n\nAttachment: smime.p7s\n", mail.body
40
+ end
41
+
42
+ def test_decode_encoded_attachment_filename
43
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email8")
44
+ mail = TMail::Mail.parse(fixture)
45
+ attachment = mail.attachments.last
46
+ expected = "01 Quien Te Dij\212at. Pitbull.mp3"
47
+ expected.force_encoding "BINARY" if expected.respond_to? :force_encoding
48
+ assert_equal expected, attachment.original_filename
49
+ end
50
+
51
+ def test_attachment_with_quoted_filename
52
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email_with_quoted_attachment_filename")
53
+ mail = TMail::Mail.parse(fixture)
54
+ attachment = mail.attachments.last
55
+ assert_equal "Eelanalüüsi päring.jpg", attachment.original_filename
56
+ end
57
+
58
+ def test_assigning_attachment_crashing_due_to_missing_boundary
59
+ mail = TMail::Mail.new
60
+ mail.mime_version = '1.0'
61
+ mail.set_content_type("multipart", "mixed")
62
+
63
+ mailpart=TMail::Mail.new
64
+ mailpart.set_content_type("application", "octet-stream")
65
+ mailpart['Content-Disposition'] = "attachment; filename=mailbox.zip"
66
+
67
+ assert_nothing_raised { mail.parts.push(mailpart) }
68
+ end
69
+
70
+ def test_only_has_attachment
71
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email_only_attachment")
72
+ mail = TMail::Mail.parse(fixture)
73
+ assert_equal(1, mail.attachments.length)
74
+ end
75
+
76
+ 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,1002 @@
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_message_id_double_at
248
+ %w( Message-Id MESSAGE-ID Message-ID
249
+ Resent-Message-Id Content-Id ).each do |name|
250
+ h = TMail::HeaderField.new(name, '<20020103xg88.k0@mail@me.loveruby.net>')
251
+ assert_instance_of TMail::MessageIdHeader, h
252
+ end
253
+ end
254
+
255
+ def test_id
256
+ str = '<20020103xg88.k0@mail.loveruby.net>'
257
+ h = TMail::HeaderField.new('Message-Id', str)
258
+ assert_not_nil h.id
259
+ assert_equal str, h.id
260
+
261
+ id = '<20020103xg88.k0@mail.loveruby.net>'
262
+ str = id + ' (comm(ent))'
263
+ h = TMail::HeaderField.new('Message-Id', str)
264
+ assert_not_nil h.id
265
+ assert_equal id, h.id
266
+ end
267
+
268
+ def test_id=
269
+ h = TMail::HeaderField.new('Message-Id', '')
270
+ h.id = str = '<20020103xg88.k0@mail.loveruby.net>'
271
+ assert_not_nil h.id
272
+ assert_equal str, h.id
273
+ end
274
+
275
+ def test_double_at_in_header
276
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email_double_at_in_header")
277
+ str = '<d3b8cf8e49f0448085@0c28713a1@f473e@37signals.com>'
278
+ mail = TMail::Mail.parse(fixture)
279
+ assert_equal str, mail.message_id
280
+ end
281
+ end
282
+
283
+ class ReferencesHeaderTester < Test::Unit::TestCase
284
+ def test_s_new
285
+ str = '<20020103xg88.k0@mail.loveruby.net>'
286
+ %w( References REFERENCES ReFeReNcEs
287
+ In-Reply-To ).each do |name|
288
+ h = TMail::HeaderField.new(name, str)
289
+ assert_instance_of TMail::ReferencesHeader, h, name
290
+ end
291
+ end
292
+
293
+ def test_ATTRS
294
+ id1 = '<20020103xg88.k0@mail.loveruby.net>'
295
+ id2 = '<20011204103415.64DB.GGB03124@nifty.ne.jp>'
296
+ phr = 'message of "Wed, 17 Mar 1999 18:42:07 +0900"'
297
+ str = id1 + ' ' + phr + ' ' + id2
298
+
299
+ h = TMail::HeaderField.new('References', str)
300
+
301
+ ok = [id1, id2]
302
+ h.each_id do |i|
303
+ assert_equal ok.shift, i
304
+ end
305
+ ok = [id1, id2]
306
+ assert_equal ok, h.ids
307
+ h.each_id do |i|
308
+ assert_equal ok.shift, i
309
+ end
310
+
311
+ ok = [phr]
312
+ assert_equal ok, h.phrases
313
+ h.each_phrase do |i|
314
+ assert_equal ok.shift, i
315
+ end
316
+ ok = [phr]
317
+ h.each_phrase do |i|
318
+ assert_equal ok.shift, i
319
+ end
320
+
321
+
322
+ # test 2
323
+ # 'In-Reply-To'
324
+ # 'aamine@dp.u-netsurf.ne.jp's message of "Fri, 8 Jan 1999 03:49:37 +0900"'
325
+ end
326
+
327
+ def test_to_s
328
+ id1 = '<20020103xg88.k0@mail.loveruby.net>'
329
+ id2 = '<20011204103415.64DB.GGB03124@nifty.ne.jp>'
330
+ phr = 'message of "Wed, 17 Mar 1999 18:42:07 +0900"'
331
+ str = id1 + ' ' + phr + ' ' + id2
332
+
333
+ h = TMail::HeaderField.new('References', str)
334
+ assert_equal id1 + ' ' + id2, h.to_s
335
+ end
336
+ end
337
+
338
+ class ReceivedHeaderTester < Test::Unit::TestCase
339
+ HEADER1 = <<EOS
340
+ from helium.ruby-lang.org (helium.ruby-lang.org [210.251.121.214])
341
+ by doraemon.edit.ne.jp (8.12.1/8.12.0) via TCP with ESMTP
342
+ id fB41nwEj007438 for <aamine@mx.edit.ne.jp>;
343
+ Tue, 4 Dec 2001 10:49:58 +0900 (JST)
344
+ EOS
345
+ HEADER2 = <<EOS
346
+ from helium.ruby-lang.org (localhost [127.0.0.1])
347
+ by helium.ruby-lang.org (Postfix) with ESMTP
348
+ id 8F8951AF3F; Tue, 4 Dec 2001 10:49:32 +0900 (JST)
349
+ EOS
350
+ HEADER3 = <<EOS
351
+ from smtp1.dti.ne.jp (smtp1.dti.ne.jp [202.216.228.36])
352
+ by helium.ruby-lang.org (Postfix) with ESMTP id CE3A1C3
353
+ for <ruby-list@ruby-lang.org>; Tue, 4 Dec 2001 10:49:31 +0900 (JST)
354
+ EOS
355
+
356
+ =begin dangerous headers
357
+ # 2-word WITH (this header is also wrong in semantic)
358
+ # I cannot support this.
359
+ Received: by mebius with Microsoft Mail
360
+ id <01BE2B9D.9051EAA0@mebius>; Sat, 19 Dec 1998 22:18:54 -0800
361
+ =end
362
+
363
+ def test_s_new
364
+ %w( Received ).each do |name|
365
+ h = TMail::HeaderField.new(name, HEADER1)
366
+ assert_instance_of TMail::ReceivedHeader, h, name
367
+ end
368
+ end
369
+
370
+ def test_ATTRS
371
+ h = TMail::HeaderField.new('Received', HEADER1)
372
+ assert_instance_of String, h.from
373
+ assert_equal 'helium.ruby-lang.org', h.from
374
+
375
+ assert_instance_of String, h.by
376
+ assert_equal 'doraemon.edit.ne.jp', h.by
377
+
378
+ assert_instance_of String, h.via
379
+ assert_equal 'TCP', h.via
380
+
381
+ assert_instance_of Array, h.with
382
+ assert_equal %w(ESMTP), h.with
383
+
384
+ assert_instance_of String, h.id
385
+ assert_equal 'fB41nwEj007438', h.id
386
+
387
+ assert_instance_of String, h._for
388
+ assert_equal 'aamine@mx.edit.ne.jp', h._for # must be <a> ?
389
+
390
+ assert_instance_of Time, h.date
391
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900')
392
+ assert_equal time, h.date
393
+
394
+ h = TMail::HeaderField.new('Received', '; Tue, 4 Dec 2001 10:49:58 +0900')
395
+ assert_nil h.from
396
+ assert_nil h.by
397
+ assert_nil h.via
398
+ assert_equal [], h.with
399
+ assert_nil h.id
400
+ assert_nil h._for
401
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900')
402
+ assert_equal time, h.date
403
+
404
+ # without date
405
+ h = TMail::HeaderField.new('Received', 'by NeXT.Mailer (1.144.2)')
406
+ assert_nil h.from
407
+ assert_equal 'NeXT.Mailer', h.by
408
+ assert_nil h.via
409
+ assert_equal [], h.with
410
+ assert_nil h.id
411
+ assert_nil h._for
412
+ assert_nil h.date
413
+
414
+ # FROM is not a domain
415
+ h = TMail::HeaderField.new('Received',
416
+ 'from someuser@example.com; Tue, 24 Nov 1998 07:59:39 -0500')
417
+ assert_equal 'example.com', h.from
418
+ assert_nil h.by
419
+ assert_nil h.via
420
+ assert_equal [], h.with
421
+ assert_nil h.id
422
+ assert_nil h._for
423
+ time = Time.parse('Tue, 24 Nov 1998 07:59:39 -0500')
424
+ assert_equal time, h.date
425
+
426
+ =begin
427
+ # FOR is not route-addr.
428
+ # item order is wrong.
429
+ h = TMail::HeaderField.new('Received',
430
+ 'from aamine by mail.softica.org with local for list@softica.org id 12Vm3N-00044L-01; Fri, 17 Mar 2000 10:59:53 +0900')
431
+ assert_equal 'aamine', h.from
432
+ assert_equal 'mail.softica.org', h.by
433
+ assert_nil h.via
434
+ assert_equal ['local'], h.with
435
+ assert_equal '12Vm3N-00044L-01', h.id
436
+ assert_equal 'list@softica.org', h._for
437
+ assert_equal Time.local(2000,4,17, 10,59,53), h.date
438
+ =end
439
+
440
+ # word + domain-literal in FROM
441
+
442
+ h = TMail::HeaderField.new('Received',
443
+ 'from localhost [192.168.1.1]; Sat, 19 Dec 1998 22:19:50 PST')
444
+ assert_equal 'localhost', h.from
445
+ assert_nil h.by
446
+ assert_nil h.via
447
+ assert_equal [], h.with
448
+ assert_nil h.id
449
+ assert_nil h._for
450
+ time = Time.parse('Sat, 19 Dec 1998 22:19:50 PST')
451
+ assert_equal time, h.date
452
+
453
+ # addr-spec in BY (must be a domain)
454
+ h = TMail::HeaderField.new('Received',
455
+ 'by aamine@loveruby.net; Wed, 24 Feb 1999 14:34:20 +0900')
456
+ assert_equal 'loveruby.net', h.by
457
+ end
458
+
459
+ def test_to_s
460
+ h = TMail::HeaderField.new('Received', HEADER1)
461
+ time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900').strftime("%a,%e %b %Y %H:%M:%S %z")
462
+ 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
463
+
464
+ [
465
+ 'from harmony.loveruby.net',
466
+ 'by mail.loveruby.net',
467
+ 'via TCP',
468
+ 'with ESMTP',
469
+ 'id LKJHSDFG',
470
+ 'for <aamine@loveruby.net>',
471
+ "; #{time}"
472
+ ]\
473
+ .each do |str|
474
+ h = TMail::HeaderField.new('Received', str)
475
+ assert_equal str, h.to_s, 'ReceivedHeader#to_s: data=' + str.dump
476
+ end
477
+ end
478
+ end
479
+
480
+ class KeywordsHeaderTester < Test::Unit::TestCase
481
+ def test_s_new
482
+ %w( Keywords KEYWORDS KeYwOrDs ).each do |name|
483
+ h = TMail::HeaderField.new(name, 'key, word, is, keyword')
484
+ assert_instance_of TMail::KeywordsHeader, h
485
+ end
486
+ end
487
+
488
+ def test_keys
489
+ h = TMail::HeaderField.new('Keywords', 'key, word, is, keyword')
490
+ assert_instance_of Array, h.keys
491
+ assert_equal %w(key word is keyword), h.keys
492
+ end
493
+ end
494
+
495
+ class EncryptedHeaderTester < Test::Unit::TestCase
496
+ def test_s_new
497
+ %w( Encrypted ).each do |name|
498
+ h = TMail::HeaderField.new(name, 'lot17 solt')
499
+ assert_instance_of TMail::EncryptedHeader, h
500
+ end
501
+ end
502
+
503
+ def test_encrypter
504
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
505
+ assert_equal 'lot17', h.encrypter
506
+ end
507
+
508
+ def test_encrypter=
509
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
510
+ h.encrypter = 'newscheme'
511
+ assert_equal 'newscheme', h.encrypter
512
+ end
513
+
514
+ def test_keyword
515
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
516
+ assert_equal 'solt', h.keyword
517
+ h = TMail::HeaderField.new('Encrypted', 'lot17')
518
+ assert_equal nil, h.keyword
519
+ end
520
+
521
+ def test_keyword=
522
+ h = TMail::HeaderField.new('Encrypted', 'lot17 solt')
523
+ h.keyword = 'newscheme'
524
+ assert_equal 'newscheme', h.keyword
525
+ end
526
+ end
527
+
528
+ class MimeVersionHeaderTester < Test::Unit::TestCase
529
+ def test_s_new
530
+ %w( Mime-Version MIME-VERSION MiMe-VeRsIoN ).each do |name|
531
+ h = TMail::HeaderField.new(name, '1.0')
532
+ assert_instance_of TMail::MimeVersionHeader, h
533
+ end
534
+ end
535
+
536
+ def test_ATTRS
537
+ h = TMail::HeaderField.new('Mime-Version', '1.0')
538
+ assert_equal 1, h.major
539
+ assert_equal 0, h.minor
540
+ assert_equal '1.0', h.version
541
+
542
+ h = TMail::HeaderField.new('Mime-Version', '99.77 (is ok)')
543
+ assert_equal 99, h.major
544
+ assert_equal 77, h.minor
545
+ assert_equal '99.77', h.version
546
+ end
547
+
548
+ def test_major=
549
+ h = TMail::HeaderField.new('Mime-Version', '1.1')
550
+ h.major = 2
551
+ assert_equal 2, h.major
552
+ assert_equal 1, h.minor
553
+ assert_equal 2, h.major
554
+ h.major = 3
555
+ assert_equal 3, h.major
556
+ end
557
+
558
+ def test_minor=
559
+ h = TMail::HeaderField.new('Mime-Version', '2.3')
560
+ assert_equal 3, h.minor
561
+ h.minor = 5
562
+ assert_equal 5, h.minor
563
+ assert_equal 2, h.major
564
+ end
565
+
566
+ def test_to_s
567
+ h = TMail::HeaderField.new('Mime-Version', '1.0 (first version)')
568
+ assert_equal '1.0', h.to_s
569
+ end
570
+
571
+ def test_empty?
572
+ h = TMail::HeaderField.new('Mime-Version', '')
573
+ assert_equal true, h.empty?
574
+ end
575
+ end
576
+
577
+ class ContentTypeHeaderTester < Test::Unit::TestCase
578
+ def test_s_new
579
+ %w( Content-Type CONTENT-TYPE CoNtEnT-TyPe ).each do |name|
580
+ h = TMail::HeaderField.new(name, 'text/plain; charset=iso-2022-jp')
581
+ assert_instance_of TMail::ContentTypeHeader, h, name
582
+ end
583
+ end
584
+
585
+ def test_ATTRS
586
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
587
+ assert_equal 'text', h.main_type
588
+ assert_equal 'plain', h.sub_type
589
+ assert_equal 1, h.params.size
590
+ assert_equal 'iso-2022-jp', h.params['charset']
591
+
592
+ h = TMail::HeaderField.new('Content-Type', 'Text/Plain; Charset=shift_jis')
593
+ assert_equal 'text', h.main_type
594
+ assert_equal 'plain', h.sub_type
595
+ assert_equal 1, h.params.size
596
+ assert_equal 'shift_jis', h.params['charset']
597
+ end
598
+
599
+ def test_multipart_with_legal_unquoted_boundary
600
+ h = TMail::HeaderField.new('Content-Type', 'multipart/mixed; boundary=dDRMvlgZJXvWKvBx')
601
+ assert_equal 'multipart', h.main_type
602
+ assert_equal 'mixed', h.sub_type
603
+ assert_equal 1, h.params.size
604
+ assert_equal 'dDRMvlgZJXvWKvBx', h.params['boundary']
605
+ end
606
+
607
+ def test_multipart_with_legal_quoted_boundary_should_retain_quotations
608
+ h = TMail::HeaderField.new('Content-Type', 'multipart/mixed; boundary="dDRMvlgZJXvWKvBx"')
609
+ assert_equal 'multipart', h.main_type
610
+ assert_equal 'mixed', h.sub_type
611
+ assert_equal 1, h.params.size
612
+ assert_equal 'dDRMvlgZJXvWKvBx', h.params['boundary']
613
+ end
614
+
615
+ def test_multipart_with_illegal_unquoted_boundary_should_add_quotations
616
+ h = TMail::HeaderField.new('Content-Type', 'multipart/alternative; boundary=----=_=NextPart_000_0093_01C81419.EB75E850')
617
+ assert_equal 'multipart', h.main_type
618
+ assert_equal 'alternative', h.sub_type
619
+ assert_equal 1, h.params.size
620
+ assert_equal '----=_=NextPart_000_0093_01C81419.EB75E850', h.params['boundary']
621
+ end
622
+
623
+ def test_multipart_with_illegal_quoted_boundary_should_retain_quotations
624
+ h = TMail::HeaderField.new('Content-Type', 'multipart/alternative; boundary="----=_=NextPart_000_0093_01C81419.EB75E850"')
625
+ assert_equal 'multipart', h.main_type
626
+ assert_equal 'alternative', h.sub_type
627
+ assert_equal 1, h.params.size
628
+ assert_equal '----=_=NextPart_000_0093_01C81419.EB75E850', h.params['boundary']
629
+ end
630
+
631
+ def test_multipart_with_extra_with_multiple_params
632
+ h = TMail::HeaderField.new('Content-Type', 'multipart/related;boundary=1_4626B816_9F1690;Type="application/smil";Start="<mms.smil.txt>"')
633
+ assert_equal 'multipart', h.main_type
634
+ assert_equal 'related', h.sub_type
635
+ assert_equal 3, h.params.size
636
+ assert_equal '1_4626B816_9F1690', h.params['boundary']
637
+ end
638
+
639
+ def test_main_type=
640
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
641
+ assert_equal 'text', h.main_type
642
+ h.main_type = 'multipart'
643
+ assert_equal 'multipart', h.main_type
644
+ assert_equal 'multipart', h.main_type
645
+ h.main_type = 'TEXT'
646
+ assert_equal 'text', h.main_type
647
+ end
648
+
649
+ def test_sub_type=
650
+ h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
651
+ assert_equal 'plain', h.sub_type
652
+ h.sub_type = 'html'
653
+ assert_equal 'html', h.sub_type
654
+ h.sub_type = 'PLAIN'
655
+ assert_equal 'plain', h.sub_type
656
+ end
657
+ end
658
+
659
+ class ContentEncodingHeaderTester < Test::Unit::TestCase
660
+ def test_s_new
661
+ %w( Content-Transfer-Encoding CONTENT-TRANSFER-ENCODING
662
+ COnteNT-TraNSFer-ENCodiNG ).each do |name|
663
+ h = TMail::HeaderField.new(name, 'Base64')
664
+ assert_instance_of TMail::ContentTransferEncodingHeader, h
665
+ end
666
+ end
667
+
668
+ def test_encoding
669
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
670
+ assert_equal 'base64', h.encoding
671
+
672
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', '7bit')
673
+ assert_equal '7bit', h.encoding
674
+ end
675
+
676
+ def test_encoding=
677
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
678
+ assert_equal 'base64', h.encoding
679
+ h.encoding = '7bit'
680
+ assert_equal '7bit', h.encoding
681
+ end
682
+
683
+ def test_to_s
684
+ h = TMail::HeaderField.new('Content-Transfer-Encoding', 'Base64')
685
+ assert_equal 'Base64', h.to_s
686
+ assert_equal h.to_s, h.decoded
687
+ assert_equal h.to_s, h.encoded
688
+ end
689
+
690
+ def test_insertion_of_headers_and_encoding_them_short
691
+ mail = TMail::Mail.new
692
+ mail['X-Mail-Header'] = "short bit of data"
693
+ assert_equal("X-Mail-Header: short bit of data\r\n\r\n", mail.encoded)
694
+ end
695
+
696
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_with_whitespace
697
+ mail = TMail::Mail.new
698
+ mail['X-Ruby-Talk'] = "<11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA 4614-95FD-9071A4BDF4A1@grayproductions.net>"
699
+ assert_equal("X-Ruby-Talk: <11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA\r\n\t4614-95FD-9071A4BDF4A1@grayproductions.net>\r\n\r\n", mail.encoded)
700
+ result = TMail::Mail.parse(mail.encoded)
701
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
702
+ end
703
+
704
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_with_whitespace
705
+ mail = TMail::Mail.new
706
+ 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>"
707
+ 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)
708
+ result = TMail::Mail.parse(mail.encoded)
709
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
710
+ end
711
+
712
+ def test_insertion_of_headers_and_encoding_them_more_than_78_char_total_without_whitespace
713
+ mail = TMail::Mail.new
714
+ mail['X-Ruby-Talk'] = "<11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA-4614-95FD-9071A4BDF4A1@grayproductions.net>"
715
+ assert_equal("X-Ruby-Talk: <11152772-AAFA-4614-95FD-9071A4BDF4A111152772-AAFA-4614-95FD-9071A4BDF4A1@grayproductions.net>\r\n\r\n", mail.encoded)
716
+ result = TMail::Mail.parse(mail.encoded)
717
+ assert_equal(mail['X-Ruby-Talk'].to_s, result['X-Ruby-Talk'].to_s)
718
+ end
719
+
720
+ def test_insertion_of_headers_and_encoding_them_less_than_998_char_total_without_whitespace
721
+ mail = TMail::Mail.new
722
+ text_with_whitespace = ""; 985.times{text_with_whitespace << "a"}
723
+ mail['Reply-To'] = "#{text_with_whitespace}"
724
+ assert_equal("Reply-To: #{text_with_whitespace}\r\n\r\n", mail.encoded)
725
+ result = TMail::Mail.parse(mail.encoded)
726
+ assert_equal(mail['Reply-To'].to_s, result['Reply-To'].to_s)
727
+ end
728
+
729
+ def test_insertion_of_headers_and_encoding_them_more_than_998_char_total_without_whitespace
730
+ mail = TMail::Mail.new
731
+ text_with_whitespace = ""; 1200.times{text_with_whitespace << "a"}
732
+ before_text = ""; 985.times{before_text << "a"}
733
+ after_text = ""; 215.times{after_text << "a"}
734
+ mail['X-Ruby-Talk'] = "#{text_with_whitespace}"
735
+ assert_equal("X-Ruby-Talk: #{before_text}\r\n\t#{after_text}\r\n\r\n", mail.encoded)
736
+ end
737
+
738
+ def test_insertion_of_headers_and_encoding_with_1_more_than_998_char_total_without_whitespace
739
+ mail = TMail::Mail.new
740
+ text_with_whitespace = ""; 996.times{text_with_whitespace << "a"}
741
+ before_text = ""; 995.times{before_text << "a"}
742
+ after_text = ""; 1.times{after_text << "a"}
743
+ mail['X'] = "#{text_with_whitespace}"
744
+ assert_equal("X: #{before_text}\r\n\t#{after_text}\r\n\r\n", mail.encoded)
745
+ end
746
+
747
+ def test_insertion_of_headers_and_encoding_with_exactly_998_char_total_without_whitespace
748
+ mail = TMail::Mail.new
749
+ text_with_whitespace = ""; 995.times{text_with_whitespace << "a"}
750
+ before_text = ""; 995.times{before_text << "a"}
751
+ mail['X'] = "#{text_with_whitespace}"
752
+ assert_equal("X: #{before_text}\r\n\r\n", mail.encoded)
753
+ end
754
+ end
755
+
756
+ class ContentDispositionHeaderTester < Test::Unit::TestCase
757
+ def test_s_new
758
+ %w( Content-Disposition CONTENT-DISPOSITION
759
+ ConTENt-DIsPOsition ).each do |name|
760
+ h = TMail::HeaderField.new(name, 'attachment; filename="README.txt.pif"')
761
+ assert_instance_of TMail::ContentDispositionHeader, h
762
+ end
763
+ end
764
+
765
+ def test_ATTRS
766
+ begin
767
+ _test_ATTRS
768
+ _test_tspecials
769
+ _test_rfc2231_decode
770
+ #_test_rfc2231_encode
771
+ _test_raw_iso2022jp
772
+ _test_raw_eucjp
773
+ _test_raw_sjis
774
+ _test_code_conversion
775
+ ensure
776
+ TMail.KCODE = 'NONE'
777
+ end
778
+ end
779
+
780
+ def _test_ATTRS
781
+ TMail.KCODE = 'NONE'
782
+
783
+ h = TMail::HeaderField.new('Content-Disposition',
784
+ 'attachment; filename="README.txt.pif"')
785
+ assert_equal 'attachment', h.disposition
786
+ assert_equal 1, h.params.size
787
+ assert_equal 'README.txt.pif', h.params['filename']
788
+
789
+ h = TMail::HeaderField.new('Content-Disposition',
790
+ 'attachment; Filename="README.txt.pif"')
791
+ assert_equal 'attachment', h.disposition
792
+ assert_equal 1, h.params.size
793
+ assert_equal 'README.txt.pif', h.params['filename']
794
+
795
+ h = TMail::HeaderField.new('Content-Disposition',
796
+ 'attachment; filename=')
797
+ assert_equal true, h.empty?
798
+ assert_nil h.params
799
+ assert_nil h['filename']
800
+ end
801
+
802
+ def _test_tspecials
803
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
804
+ h['n'] = %q|()<>[];:@\\,"/?=|
805
+ assert_equal 'a; n="()<>[];:@\\\\,\"/?="', h.encoded
806
+ end
807
+
808
+ def _test_rfc2231_decode
809
+ TMail.KCODE = 'EUC'
810
+
811
+ h = TMail::HeaderField.new('Content-Disposition',
812
+ "attachment; filename*=iso-2022-jp'ja'%1b$B$Q$i$`%1b%28B")
813
+ assert_equal 'attachment', h.disposition
814
+ assert_equal 1, h.params.size
815
+ expected = "\244\321\244\351\244\340"
816
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
817
+ assert_equal expected, h.params['filename']
818
+ end
819
+
820
+ def _test_rfc2231_encode
821
+ TMail.KCODE = 'EUC'
822
+
823
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
824
+ h['n'] = "\245\265\245\363\245\327\245\353.txt"
825
+ assert_equal "a; n*=iso-2022-jp'ja'%1B$B%255%25s%25W%25k%1B%28B.txt",
826
+ h.encoded
827
+
828
+ h = TMail::HeaderField.new('Content-Disposition', 'a; n=a')
829
+ h['n'] = "\245\265()<>[];:@\\,\"/?=%*'"
830
+ 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",
831
+ h.encoded
832
+ end
833
+
834
+ def _test_raw_iso2022jp
835
+ TMail.KCODE = 'EUC'
836
+ # raw iso2022jp string in value (token)
837
+ h = TMail::HeaderField.new('Content-Disposition',
838
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
839
+ assert_equal 'attachment', h.disposition
840
+ assert_equal 1, h.params.size
841
+ # assert_equal "\e$BF|K\\8l\e(B.doc", h.params['filename']
842
+
843
+ expected = "\306\374\313\334\270\354.doc"
844
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
845
+
846
+ assert_equal expected, h.params['filename']
847
+
848
+ # raw iso2022jp string in value (quoted string)
849
+ h = TMail::HeaderField.new('Content-Disposition',
850
+ %Q<attachment; filename="\e$BF|K\\8l\e(B.doc">)
851
+ assert_equal 'attachment', h.disposition
852
+ assert_equal 1, h.params.size
853
+ # assert_equal "\e$BF|K\\8l\e(B.doc", h.params['filename']
854
+ assert_equal expected, h.params['filename']
855
+ end
856
+
857
+ def _test_raw_eucjp
858
+ TMail.KCODE = 'EUC'
859
+ # raw EUC-JP string in value (token)
860
+ h = TMail::HeaderField.new('Content-Disposition',
861
+ %Q<attachment; filename=\306\374\313\334\270\354.doc>)
862
+ assert_equal 'attachment', h.disposition
863
+ assert_equal 1, h.params.size
864
+ expected = "\306\374\313\334\270\354.doc"
865
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
866
+ assert_equal expected, h.params['filename']
867
+
868
+ # raw EUC-JP string in value (quoted-string)
869
+ h = TMail::HeaderField.new('Content-Disposition',
870
+ %Q<attachment; filename="\306\374\313\334\270\354.doc">)
871
+ assert_equal 'attachment', h.disposition
872
+ assert_equal 1, h.params.size
873
+ assert_equal expected, h.params['filename']
874
+ end
875
+
876
+ def _test_raw_sjis
877
+ TMail.KCODE = 'SJIS'
878
+ # raw SJIS string in value (token)
879
+ h = TMail::HeaderField.new('Content-Disposition',
880
+ %Q<attachment; filename=\223\372\226{\214\352.doc>)
881
+ assert_equal 'attachment', h.disposition
882
+ assert_equal 1, h.params.size
883
+ expected = "\223\372\226{\214\352.doc"
884
+ expected.force_encoding('Windows-31J').encode!("Shift_JIS") if expected.respond_to? :force_encoding
885
+ assert_equal expected, h.params['filename']
886
+
887
+ # raw SJIS string in value (quoted-string)
888
+ h = TMail::HeaderField.new('Content-Disposition',
889
+ %Q<attachment; filename="\223\372\226{\214\352.doc">)
890
+ assert_equal 'attachment', h.disposition
891
+ assert_equal 1, h.params.size
892
+ assert_equal expected, h.params['filename']
893
+ end
894
+
895
+ def _test_code_conversion
896
+ # JIS -> TMail.KCODE auto conversion
897
+ TMail.KCODE = 'EUC'
898
+ h = TMail::HeaderField.new('Content-Disposition',
899
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
900
+ assert_equal 'attachment', h.disposition
901
+ assert_equal 1, h.params.size
902
+ expected = "\306\374\313\334\270\354.doc"
903
+ expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
904
+ assert_equal expected, h.params['filename']
905
+
906
+ TMail.KCODE = 'SJIS'
907
+ h = TMail::HeaderField.new('Content-Disposition',
908
+ %Q<attachment; filename=\e$BF|K\\8l\e(B.doc>)
909
+ assert_equal 'attachment', h.disposition
910
+ assert_equal 1, h.params.size
911
+ expected = "\223\372\226{\214\352.doc"
912
+ expected.force_encoding('Windows-31J').encode!("Shift_JIS") if expected.respond_to? :force_encoding
913
+ assert_equal expected, h.params['filename']
914
+ end
915
+
916
+ def test_disposition=
917
+ h = TMail::HeaderField.new('Content-Disposition',
918
+ 'attachment; filename="README.txt.pif"')
919
+ assert_equal 'attachment', h.disposition
920
+ h.disposition = 'virus'
921
+ assert_equal 'virus', h.disposition
922
+ h.disposition = 'AtTaChMeNt'
923
+ assert_equal 'attachment', h.disposition
924
+ end
925
+
926
+ def test_wrong_mail_header
927
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email9")
928
+ assert_raise(TMail::SyntaxError) { TMail::Mail.parse(fixture) }
929
+ end
930
+
931
+ def test_decode_message_with_unknown_charset
932
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email10")
933
+ mail = TMail::Mail.parse(fixture)
934
+ assert_nothing_raised { mail.body }
935
+ end
936
+
937
+ def test_decode_message_with_unquoted_atchar_in_header
938
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email11")
939
+ mail = TMail::Mail.parse(fixture)
940
+ assert_not_nil mail.from
941
+ end
942
+
943
+ def test_new_from_port_should_produce_a_header_object_of_the_correct_class
944
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
945
+ h = TMail::HeaderField.new_from_port(p, 'Message-Id')
946
+ assert_equal(TMail::MessageIdHeader, h.class)
947
+ end
948
+
949
+ def test_should_return_the_evelope_sender_when_given_from_without_a_colon
950
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
951
+ h = TMail::HeaderField.new_from_port(p, 'EnvelopeSender')
952
+ assert_equal("mike@envelope_sender.com.au", h.addrs.join)
953
+ end
954
+
955
+ def test_new_from_port_should_produce_a_header_object_that_contains_the_right_data
956
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
957
+ h = TMail::HeaderField.new_from_port(p, 'From')
958
+ assert_equal("Mikel Lindsaar <mikel@from_address.com>", h.addrs.join)
959
+ end
960
+
961
+ def test_unwrapping_a_long_header_field_using_new_from_port
962
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
963
+ h = TMail::HeaderField.new_from_port(p, 'Content-Type')
964
+ line = 'multipart/signed; protocol="application/pkcs7-signature"; boundary=Apple-Mail-42-587703407; micalg=sha1'
965
+ assert(line =~ /multipart\/signed/)
966
+ assert(line =~ /protocol="application\/pkcs7-signature"/)
967
+ assert(line =~ /boundary=Apple-Mail-42-587703407/)
968
+ assert(line =~ /micalg=sha1/)
969
+ assert_equal(line.length, 103)
970
+ end
971
+
972
+ def test_returning_nil_if_there_is_no_match
973
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
974
+ h = TMail::HeaderField.new_from_port(p, 'Received-Long-Header')
975
+ assert_equal(h, nil)
976
+ end
977
+
978
+ def test_multi_address_header_in_tmail
979
+ h = TMail::Mail.new
980
+ h.to = "Mikel@me.com, mikel@you.com"
981
+ assert_equal("To: Mikel@me.com,\r\n\t mikel@you.com\r\n\r\n", h.encoded)
982
+ end
983
+
984
+ def test_adding_custom_message_id
985
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email")
986
+ mail = TMail::Mail.parse(fixture)
987
+ message_id = "<12345@me.com>"
988
+ mail.enforced_message_id = message_id
989
+ mail.ready_to_send
990
+ assert_equal(message_id, mail.message_id)
991
+ end
992
+
993
+ def test_not_adding_custom_message_id
994
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email")
995
+ mail = TMail::Mail.parse(fixture)
996
+ message_id = mail.message_id
997
+ mail.message_id = "<12345@me.com>"
998
+ mail.ready_to_send
999
+ assert_not_equal(message_id, mail.message_id)
1000
+ end
1001
+
1002
+ end