lonbaker-tmail 1.2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/CHANGES +74 -0
  2. data/LICENSE +21 -0
  3. data/NOTES +7 -0
  4. data/README +169 -0
  5. data/ext/Makefile +20 -0
  6. data/ext/tmailscanner/tmail/MANIFEST +4 -0
  7. data/ext/tmailscanner/tmail/depend +1 -0
  8. data/ext/tmailscanner/tmail/extconf.rb +33 -0
  9. data/ext/tmailscanner/tmail/tmailscanner.c +583 -0
  10. data/lib/tmail.rb +5 -0
  11. data/lib/tmail/Makefile +18 -0
  12. data/lib/tmail/address.rb +426 -0
  13. data/lib/tmail/attachments.rb +46 -0
  14. data/lib/tmail/base64.rb +46 -0
  15. data/lib/tmail/compat.rb +41 -0
  16. data/lib/tmail/config.rb +67 -0
  17. data/lib/tmail/core_extensions.rb +63 -0
  18. data/lib/tmail/encode.rb +590 -0
  19. data/lib/tmail/header.rb +962 -0
  20. data/lib/tmail/index.rb +9 -0
  21. data/lib/tmail/interface.rb +1130 -0
  22. data/lib/tmail/loader.rb +3 -0
  23. data/lib/tmail/mail.rb +580 -0
  24. data/lib/tmail/mailbox.rb +496 -0
  25. data/lib/tmail/main.rb +6 -0
  26. data/lib/tmail/mbox.rb +3 -0
  27. data/lib/tmail/net.rb +248 -0
  28. data/lib/tmail/obsolete.rb +132 -0
  29. data/lib/tmail/parser.rb +1476 -0
  30. data/lib/tmail/parser.y +381 -0
  31. data/lib/tmail/port.rb +379 -0
  32. data/lib/tmail/quoting.rb +118 -0
  33. data/lib/tmail/require_arch.rb +58 -0
  34. data/lib/tmail/scanner.rb +49 -0
  35. data/lib/tmail/scanner_r.rb +261 -0
  36. data/lib/tmail/stringio.rb +280 -0
  37. data/lib/tmail/utils.rb +351 -0
  38. data/lib/tmail/version.rb +39 -0
  39. data/meta/MANIFEST +128 -0
  40. data/meta/project.yaml +30 -0
  41. data/meta/unixname +1 -0
  42. data/sample/bench_base64.rb +48 -0
  43. data/sample/data/multipart +23 -0
  44. data/sample/data/normal +29 -0
  45. data/sample/data/sendtest +5 -0
  46. data/sample/data/simple +14 -0
  47. data/sample/data/test +27 -0
  48. data/sample/extract-attachements.rb +33 -0
  49. data/sample/from-check.rb +26 -0
  50. data/sample/multipart.rb +26 -0
  51. data/sample/parse-bench.rb +68 -0
  52. data/sample/parse-test.rb +19 -0
  53. data/sample/sendmail.rb +94 -0
  54. data/test/extctrl.rb +6 -0
  55. data/test/fixtures/mailbox +414 -0
  56. data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
  57. data/test/fixtures/mailbox_without_from +11 -0
  58. data/test/fixtures/mailbox_without_return_path +12 -0
  59. data/test/fixtures/raw_base64_decoded_string +0 -0
  60. data/test/fixtures/raw_base64_email +83 -0
  61. data/test/fixtures/raw_base64_encoded_string +1 -0
  62. data/test/fixtures/raw_email +14 -0
  63. data/test/fixtures/raw_email10 +20 -0
  64. data/test/fixtures/raw_email11 +34 -0
  65. data/test/fixtures/raw_email12 +32 -0
  66. data/test/fixtures/raw_email13 +29 -0
  67. data/test/fixtures/raw_email2 +114 -0
  68. data/test/fixtures/raw_email3 +70 -0
  69. data/test/fixtures/raw_email4 +59 -0
  70. data/test/fixtures/raw_email5 +19 -0
  71. data/test/fixtures/raw_email6 +20 -0
  72. data/test/fixtures/raw_email7 +66 -0
  73. data/test/fixtures/raw_email8 +47 -0
  74. data/test/fixtures/raw_email9 +28 -0
  75. data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
  76. data/test/fixtures/raw_email_reply +32 -0
  77. data/test/fixtures/raw_email_simple +11 -0
  78. data/test/fixtures/raw_email_with_bad_date +48 -0
  79. data/test/fixtures/raw_email_with_illegal_boundary +58 -0
  80. data/test/fixtures/raw_email_with_multipart_mixed_quoted_boundary +50 -0
  81. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  82. data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
  83. data/test/fixtures/raw_email_with_quoted_illegal_boundary +58 -0
  84. data/test/kcode.rb +14 -0
  85. data/test/test_address.rb +1211 -0
  86. data/test/test_attachments.rb +60 -0
  87. data/test/test_base64.rb +64 -0
  88. data/test/test_encode.rb +85 -0
  89. data/test/test_header.rb +969 -0
  90. data/test/test_helper.rb +9 -0
  91. data/test/test_mail.rb +753 -0
  92. data/test/test_mbox.rb +184 -0
  93. data/test/test_port.rb +436 -0
  94. data/test/test_quote.rb +98 -0
  95. data/test/test_scanner.rb +209 -0
  96. data/test/test_utils.rb +36 -0
  97. metadata +159 -0
@@ -0,0 +1,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