tmail 1.2.0 → 1.2.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 (51) hide show
  1. data/CHANGES +11 -0
  2. data/NOTES +48 -38
  3. data/README +3 -2
  4. data/Rakefile +11 -0
  5. data/ext/Makefile +8 -8
  6. data/ext/{mailscanner → tmailscanner}/tmail/MANIFEST +1 -1
  7. data/ext/tmailscanner/tmail/depend +1 -0
  8. data/ext/{mailscanner → tmailscanner}/tmail/extconf.rb +1 -1
  9. data/ext/{mailscanner/tmail/mailscanner.c → tmailscanner/tmail/tmailscanner.c} +10 -10
  10. data/lib/tmail/address.rb +9 -1
  11. data/lib/tmail/encode.rb +1 -0
  12. data/lib/tmail/header.rb +34 -2
  13. data/lib/tmail/mailbox.rb +3 -3
  14. data/lib/tmail/quoting.rb +0 -24
  15. data/lib/tmail/scanner.rb +4 -4
  16. data/lib/tmail/scanner_r.rb +1 -1
  17. data/lib/tmail/utils.rb +2 -3
  18. data/lib/tmail/version.rb +1 -1
  19. data/log/ChangeLog.txt +22 -0
  20. data/log/History.txt +1 -1
  21. data/meta/MANIFEST +18 -8
  22. data/{script → meta}/config.yaml +1 -1
  23. data/meta/tmail.roll +3 -0
  24. data/script/clobber/distclean +1 -1
  25. data/script/compile +2 -2
  26. data/script/pack/gem +93 -0
  27. data/script/pack/tgz +41 -0
  28. data/script/pack/zip +41 -0
  29. data/script/prepare +6 -1
  30. data/script/publish +2 -2
  31. data/script/rdoc +42 -0
  32. data/script/release +1 -3
  33. data/script/stamp +33 -0
  34. data/script/test +1 -1
  35. data/test/fixtures/mailbox +13 -0
  36. data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
  37. data/test/fixtures/mailbox_without_from +11 -0
  38. data/test/fixtures/mailbox_without_return_path +12 -0
  39. data/test/fixtures/raw_email11 +2 -2
  40. data/test/fixtures/raw_email_with_bad_date +5 -5
  41. data/test/test_address.rb +32 -2
  42. data/test/test_attachments.rb +15 -0
  43. data/test/test_encode.rb +54 -52
  44. data/test/test_header.rb +57 -0
  45. data/test/test_helper.rb +1 -0
  46. data/test/test_mail.rb +49 -1
  47. data/test/test_mbox.rb +21 -0
  48. data/test/test_quote.rb +71 -0
  49. metadata +173 -153
  50. data/ext/mailscanner/tmail/depend +0 -1
  51. data/meta/ROLLRC +0 -3
@@ -0,0 +1,11 @@
1
+ From mike@envelope_sender.com.au
2
+ Received: from mikel091a by oaamta05sl.mx.bigpond.com with SMTP id
3
+ <20071021093820.JFMT24025.oaamta05sl.mx.bigpond.com@mikel091a> for
4
+ <mikel@nowhere.com.else>; Sun, 21 Oct 2007 19:38:20 +1000
5
+ Date: Sun, 21 Oct 2007 19:38:13 +1000
6
+ To: Mikel <mikel@somewhere.com>
7
+ Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
8
+ Subject: Testing outlook
9
+
10
+ Hello Mikel
11
+
@@ -0,0 +1,12 @@
1
+ From mike@envelope_sender.com.au
2
+ Received: from mikel091a by oaamta05sl.mx.bigpond.com with SMTP id
3
+ <20071021093820.JFMT24025.oaamta05sl.mx.bigpond.com@mikel091a> for
4
+ <mikel@nowhere.com.else>; Sun, 21 Oct 2007 19:38:20 +1000
5
+ Date: Sun, 21 Oct 2007 19:38:13 +1000
6
+ From: Mikel Lindsaar <mikel@from_address.com>
7
+ To: Mikel <mikel@somewhere.com>
8
+ Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
9
+ Subject: Testing outlook
10
+
11
+ Hello Mikel
12
+
@@ -1,10 +1,10 @@
1
1
  From xxx@xxxx.com Wed Apr 27 14:15:31 2005
2
2
  Mime-Version: 1.0 (Apple Message framework v619.2)
3
- To: xxxxx@xxxxx <matmail>
3
+ To: "xxxxx@xxxxx" <matmail>
4
4
  Message-Id: <416eaebec6d333ec6939eaf8a7d80724@xxxxx>
5
5
  Content-Type: multipart/alternative;
6
6
  boundary=Apple-Mail-5-1037861608
7
- From: xxxxx@xxxxx <xxxxx@xxxxx>
7
+ From: "xxxxx@xxxxx" <xxxxx@xxxxx>
8
8
  Subject: worse when you use them.
9
9
  Date: Wed, 27 Apr 2005 14:15:31 -0700
10
10
 
@@ -27,13 +27,13 @@ X-MSMail-Priority: Normal
27
27
  X-Mailer: Microsoft Outlook, Build 10.0.3416
28
28
  Importance: Normal
29
29
  X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.150
30
- X-CSI-MailScanner-Information: Please contact the ISP for more information
31
- X-CSI-MailScanner: Found to be clean
32
- X-CSI-MailScanner-SpamCheck: not spam, SpamAssassin (score=1.87, required 4,
30
+ X-CSI-TMailScanner-Information: Please contact the ISP for more information
31
+ X-CSI-TMailScanner: Found to be clean
32
+ X-CSI-TMailScanner-SpamCheck: not spam, SpamAssassin (score=1.87, required 4,
33
33
  autolearn=disabled, INVALID_DATE 0.23, RAZOR2_CF_RANGE_51_100 1.49,
34
34
  RAZOR2_CHECK 0.15)
35
- X-CSI-MailScanner-SpamScore: s
36
- X-MailScanner-From: subventive@vodtravel.com
35
+ X-CSI-TMailScanner-SpamScore: s
36
+ X-TMailScanner-From: subventive@vodtravel.com
37
37
  Resent-Date: Mon, 05 Nov 2007 20:17:37 +1100 (EST)
38
38
  Resent-From: <mail_dump@ns1.xxxxxxxx.xxx.xx>
39
39
  Resent-To: <mikel@xxxxxxxx.xxx>
@@ -1022,6 +1022,7 @@ class TestAddress < Test::Unit::TestCase
1022
1022
  :local => %Q("#{ch}"),
1023
1023
  :format => %Q("#{ch}" <"#{ch}"@test>)
1024
1024
  end
1025
+
1025
1026
  ['"', "\\"].each do |ch|
1026
1027
  validate_case__address\
1027
1028
  %Q("\\#{ch}" <"\\#{ch}"@test>),
@@ -1032,9 +1033,9 @@ class TestAddress < Test::Unit::TestCase
1032
1033
  :domain => 'test',
1033
1034
  :local => %Q("\\#{ch}"),
1034
1035
  :format => %Q("\\#{ch}" <"\\#{ch}"@test>)
1036
+
1035
1037
  end
1036
1038
 
1037
- =begin TMail does not have #comments in Address.
1038
1039
  (ctext - boring).each do |ch|
1039
1040
  validate_case__address\
1040
1041
  "bob@test (#{ch})",
@@ -1067,7 +1068,7 @@ class TestAddress < Test::Unit::TestCase
1067
1068
  :local => 'bob',
1068
1069
  :format => "bob@test (\\#{ch})"
1069
1070
  end
1070
- =end
1071
+
1071
1072
 
1072
1073
  (dtext - boring).each do |ch|
1073
1074
  validate_case__address\
@@ -1111,6 +1112,10 @@ class TestAddress < Test::Unit::TestCase
1111
1112
  :local => 'test',
1112
1113
  :format => 'Bob <test@[' + (dtext - boring).join('') + ']>'
1113
1114
 
1115
+ end
1116
+
1117
+ def test_quoted_at_char_in_local()
1118
+
1114
1119
  validate_case__address\
1115
1120
  %Q("@" <"@"@test>),
1116
1121
  :name => "@",
@@ -1120,7 +1125,32 @@ class TestAddress < Test::Unit::TestCase
1120
1125
  :domain => 'test',
1121
1126
  :local => %Q("@"),
1122
1127
  :format => %Q("@" <"@"@test>)
1128
+
1129
+ validate_case__address\
1130
+ %Q("@" <"me@me"@test>),
1131
+ :name => "@",
1132
+ :display_name => "@",
1133
+ :address => %Q("me@me"@test),
1134
+ :comments => nil,
1135
+ :domain => 'test',
1136
+ :local => %Q("me@me"),
1137
+ :format => %Q("@" <"me@me"@test>)
1138
+
1139
+ end
1140
+
1141
+ def test_full_stop_in_local()
1123
1142
 
1143
+ validate_case__address\
1144
+ %Q(Minero A. <aamine@loveruby.net>),
1145
+ :name => "Minero A.",
1146
+ :display_name => "Minero A.",
1147
+ :address => %Q(aamine@loveruby.net),
1148
+ :comments => nil,
1149
+ :domain => 'loveruby.net',
1150
+ :local => %Q(aamine),
1151
+ :format => %Q("me@my_place" <aamine@loveruby.net>)
1152
+
1124
1153
  end
1154
+
1125
1155
 
1126
1156
  end
@@ -31,4 +31,19 @@ HERE
31
31
  assert_equal(true, mail.multipart?)
32
32
  assert_equal(1, mail.attachments.length)
33
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
+
34
49
  end
@@ -3,65 +3,67 @@ require 'tmail/port'
3
3
  require 'tmail/encode'
4
4
  require 'nkf'
5
5
  require 'test/unit'
6
+ require 'rubygems'
7
+ require 'ruby-debug'
6
8
 
7
9
  class TestEncode < Test::Unit::TestCase
8
10
 
9
11
  SRCS = [
10
- "a cde あいうえおあいうえおあいうえおあいうえおあいうえお",
11
- "a cde あいうえおあいうえおあいうえおあいうえおあいうえ",
12
- "a cde あいうえおあいうえおあいうえおあいうえおあいう",
13
- "a cde あいうえおあいうえおあいうえおあいうえおあい",
14
- "a cde あいうえおあいうえおあいうえおあいうえおあ",
15
- "a cde あいうえおあいうえおあいうえおあいうえお", #
16
- "a cde あいうえおあいうえおあいうえおあいうえ",
17
- "a cde あいうえおあいうえおあいうえおあいう",
18
- "a cde あいうえおあいうえおあいうえおあい",
19
- "a cde あいうえおあいうえおあいうえおあ",
20
- "a cde あいうえおあいうえおあいうえお",
21
- "a cde あいうえおあいうえおあいうえ",
22
- "a cde あいうえおあいうえおあいう",
23
- "a cde あいうえおあいうえおあい",
24
- "a cde あいうえおあいうえおあ",
25
- "a cde あいうえおあいうえお",
26
- "a cde あいうえおあいうえ",
27
- "a cde あいうえおあいう",
28
- "a cde あいうえおあい",
29
- "a cde あいうえおあ",
30
- "a cde あいうえお",
31
- "a cde あいうえ",
32
- "a cde あいう",
33
- "a cde あい",
34
- "a cde あ",
35
- "aあa aあa aあa aあa"
12
+ "a cde あいうえおあいうえおあいうえおあいうえおあいうえお", #1
13
+ "a cde あいうえおあいうえおあいうえおあいうえおあいうえ", #2
14
+ "a cde あいうえおあいうえおあいうえおあいうえおあいう", #3
15
+ "a cde あいうえおあいうえおあいうえおあいうえおあい", #4
16
+ "a cde あいうえおあいうえおあいうえおあいうえおあ", #5
17
+ "a cde あいうえおあいうえおあいうえおあいうえお", #6 #
18
+ "a cde あいうえおあいうえおあいうえおあいうえ", #7
19
+ "a cde あいうえおあいうえおあいうえおあいう", #8
20
+ "a cde あいうえおあいうえおあいうえおあい", #9
21
+ "a cde あいうえおあいうえおあいうえおあ", #10
22
+ "a cde あいうえおあいうえおあいうえお", #11
23
+ "a cde あいうえおあいうえおあいうえ", #12
24
+ "a cde あいうえおあいうえおあいう", #13
25
+ "a cde あいうえおあいうえおあい", #14
26
+ "a cde あいうえおあいうえおあ", #15
27
+ "a cde あいうえおあいうえお", #16
28
+ "a cde あいうえおあいうえ", #17
29
+ "a cde あいうえおあいう", #18
30
+ "a cde あいうえおあい", #19
31
+ "a cde あいうえおあ", #20
32
+ "a cde あいうえお", #21
33
+ "a cde あいうえ", #22
34
+ "a cde あいう", #23
35
+ "a cde あい", #24
36
+ "a cde あ", #25
37
+ "aあa aあa aあa aあa aあa aあa" #26
36
38
  ]
37
39
 
38
40
  OK = [
39
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqGyhC?=",
40
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCokIiQkJCYkKBsoQg==?=",
41
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=",
42
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCokIiQkGyhC?=",
43
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCokIhsoQg==?=",
44
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoJCobKEI=?=",
45
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJiQoGyhC?=",
46
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQkJhsoQg==?=",
47
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiJCQbKEI=?=",
48
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKiQiGyhC?=",
49
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgkKhsoQg==?=",
50
- "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCgbKEI=?=",
51
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=',
52
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkGyhC?=',
53
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIhsoQg==?=',
54
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCobKEI=?=',
55
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoGyhC?=',
56
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJhsoQg==?=',
57
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQbKEI=?=',
58
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiGyhC?=',
59
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKhsoQg==?=',
60
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgbKEI=?=',
61
- 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmGyhC?=',
62
- 'a cde =?iso-2022-jp?B?GyRCJCIkJBsoQg==?=',
63
- 'a cde =?iso-2022-jp?B?GyRCJCIbKEI=?=',
64
- "=?iso-2022-jp?B?YRskQiQiGyhCYSBhGyRCJCIbKEJhIGEbJEIkIhsoQmEgYQ==?=\n\t=?iso-2022-jp?B?GyRCJCIbKEJh?="
41
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYkKCQqGyhC?=", #1
42
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYkKBsoQg==?=", #2
43
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkJCYbKEI=?=", #3
44
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIiQkGyhC?=", #4
45
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCokIhsoQg==?=", #5
46
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoJCobKEI=?=", #6
47
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJiQoGyhC?=", #7
48
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQkJhsoQg==?=", #8
49
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=\n\t=?iso-2022-jp?B?GyRCJCQbKEI=?=", #9
50
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqJCIbKEI=?=", #10
51
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKCQqGyhC?=", #11
52
+ "a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYkKBsoQg==?=", #12
53
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkJCYbKEI=?=', #13
54
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIiQkGyhC?=', #14
55
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCokIhsoQg==?=', #15
56
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoJCobKEI=?=', #16
57
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJiQoGyhC?=', #17
58
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQkJhsoQg==?=', #18
59
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiJCQbKEI=?=', #19
60
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKiQiGyhC?=', #20
61
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgkKhsoQg==?=', #21
62
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmJCgbKEI=?=', #22
63
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJCQmGyhC?=', #23
64
+ 'a cde =?iso-2022-jp?B?GyRCJCIkJBsoQg==?=', #24
65
+ 'a cde =?iso-2022-jp?B?GyRCJCIbKEI=?=', #25
66
+ "=?iso-2022-jp?B?YRskQiQiGyhCYSBhGyRCJCIbKEJhIGEbJEIkIhsoQmEgYRskQiQiGyhCYSBh?=\r\n\t=?iso-2022-jp?B?GyRCJCIbKEJhIGEbJEIkIhsoQmE=?=" #26
65
67
  ]
66
68
 
67
69
  def test_s_encode
@@ -608,6 +608,14 @@ class ContentTypeHeaderTester < Test::Unit::TestCase
608
608
  assert_equal '----=_=NextPart_000_0093_01C81419.EB75E850', h.params['boundary']
609
609
  end
610
610
 
611
+ def test_multipart_with_extra_with_multiple_params
612
+ h = TMail::HeaderField.new('Content-Type', 'multipart/related;boundary=1_4626B816_9F1690;Type="application/smil";Start="<mms.smil.txt>"')
613
+ assert_equal 'multipart', h.main_type
614
+ assert_equal 'related', h.sub_type
615
+ assert_equal 3, h.params.size
616
+ assert_equal '1_4626B816_9F1690', h.params['boundary']
617
+ end
618
+
611
619
  def test_main_type=
612
620
  h = TMail::HeaderField.new('Content-Type', 'text/plain; charset=iso-2022-jp')
613
621
  assert_equal 'text', h.main_type
@@ -881,4 +889,53 @@ class ContentDispositionHeaderTester < Test::Unit::TestCase
881
889
  h.disposition = 'AtTaChMeNt'
882
890
  assert_equal 'attachment', h.disposition
883
891
  end
892
+
893
+ def test_wrong_mail_header
894
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email9")
895
+ assert_raise(TMail::SyntaxError) { TMail::Mail.parse(fixture) }
896
+ end
897
+
898
+ def test_decode_message_with_unknown_charset
899
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email10")
900
+ mail = TMail::Mail.parse(fixture)
901
+ assert_nothing_raised { mail.body }
902
+ end
903
+
904
+ def test_decode_message_with_unquoted_atchar_in_header
905
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email11")
906
+ mail = TMail::Mail.parse(fixture)
907
+ assert_not_nil mail.from
908
+ end
909
+
910
+ def test_new_from_port_should_produce_a_header_object_of_the_correct_class
911
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
912
+ h = TMail::HeaderField.new_from_port(p, 'Message-Id')
913
+ assert_equal(TMail::MessageIdHeader, h.class)
914
+ end
915
+
916
+ def test_should_return_the_evelope_sender_when_given_from_without_a_colon
917
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
918
+ h = TMail::HeaderField.new_from_port(p, 'EnvelopeSender')
919
+ assert_equal("mike@envelope_sender.com.au", h.addrs.to_s)
920
+ end
921
+
922
+ def test_new_from_port_should_produce_a_header_object_that_contains_the_right_data
923
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
924
+ h = TMail::HeaderField.new_from_port(p, 'From')
925
+ assert_equal("Mikel Lindsaar <mikel@from_address.com>", h.addrs.to_s)
926
+ end
927
+
928
+ def test_unwrapping_a_long_header_field_using_new_from_port
929
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
930
+ h = TMail::HeaderField.new_from_port(p, 'Received')
931
+ line = "from mikel091a by oaamta05sl.mx.bigpond.com with SMTP id <20071021093820.JFMT24025.oaamta05sl.mx.bigpond.com@mikel091a> for <mikel@nowhere.com.else>; Sun, 21 Oct 2007 19:38:20 +1000"
932
+ assert_equal(h.to_s, line)
933
+ end
934
+
935
+ def test_returning_nil_if_there_is_no_match
936
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
937
+ h = TMail::HeaderField.new_from_port(p, 'Received-Long-Header')
938
+ assert_equal(h, nil)
939
+ end
940
+
884
941
  end
@@ -1,5 +1,6 @@
1
1
  # Add in the local library for the load path so we get that before any possible
2
2
  # gem that is already installed.
3
+ require 'stringio'
3
4
  $:.unshift File.dirname(__FILE__) + "/../lib"
4
5
  $:.unshift File.dirname(__FILE__) + "/../lib/tmail"
5
6
  require 'test/unit'
@@ -342,7 +342,9 @@ Content-Type: text/plain; charset=iso-8859-1
342
342
  The body
343
343
  EOF
344
344
  mail = TMail::Mail.parse(msg)
345
- assert_equal "testing testing \326\244", mail.subject
345
+ expected = "testing testing \326\244"
346
+ expected.force_encoding 'utf-8' if expected.respond_to? :force_encoding
347
+ assert_equal expected, mail.subject
346
348
  assert_equal "=?utf-8?Q?testing_testing_=D6=A4?=", mail.quoted_subject
347
349
  end
348
350
 
@@ -604,11 +606,38 @@ EOF
604
606
  assert_equal 1026, attachment.read.length
605
607
  end
606
608
 
609
+ def test_attachment_using_content_location
610
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email12")
611
+ mail = TMail::Mail.parse(fixture)
612
+ assert_equal 1, mail.attachments.length
613
+ assert_equal "Photo25.jpg", mail.attachments.first.original_filename
614
+ end
615
+
616
+ def test_attachment_with_text_type
617
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email13")
618
+ mail = TMail::Mail.parse(fixture)
619
+ assert mail.has_attachments?
620
+ assert_equal 1, mail.attachments.length
621
+ assert_equal "hello.rb", mail.attachments.first.original_filename
622
+ end
623
+
624
+ def test_decode_part_without_content_type
625
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4")
626
+ mail = TMail::Mail.parse(fixture)
627
+ assert_nothing_raised { mail.body }
628
+ end
629
+
607
630
  def test_decode_message_without_content_type
608
631
  mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email4")
609
632
  assert_nothing_raised { mail.body }
610
633
  end
611
634
 
635
+ def test_decode_message_with_incorrect_charset
636
+ fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email6")
637
+ mail = TMail::Mail.parse(fixture)
638
+ assert_nothing_raised { mail.body }
639
+ end
640
+
612
641
  def test_quoting_of_illegal_boundary_when_doing_mail_to_s
613
642
  mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_illegal_boundary")
614
643
  assert_equal(true, mail.multipart?)
@@ -648,5 +677,24 @@ EOF
648
677
  assert_equal(true, forward.multipart?)
649
678
  assert_equal(TMail::Mail, forward.class)
650
679
  end
680
+
681
+ def test_body
682
+ m = TMail::Mail.new
683
+ expected = 'something_with_underscores'
684
+ m.encoding = 'quoted-printable'
685
+ quoted_body = [expected].pack('*M')
686
+ m.body = quoted_body
687
+ assert_equal "something_with_underscores=\n", m.quoted_body
688
+ assert_equal expected, m.body
689
+ end
690
+
691
+ def test_nested_attachments_are_recognized_correctly
692
+ fixture = File.read("#{File.dirname(__FILE__)}/fixtures/raw_email_with_nested_attachment")
693
+ mail = TMail::Mail.parse(fixture)
694
+ assert_equal 2, mail.attachments.length
695
+ assert_equal "image/png", mail.attachments.first.content_type
696
+ assert_equal 1902, mail.attachments.first.length
697
+ assert_equal "application/pkcs7-signature", mail.attachments.last.content_type
698
+ end
651
699
 
652
700
  end
@@ -123,4 +123,25 @@ class MailboxTester < Test::Unit::TestCase
123
123
  end
124
124
  assert_equal 0, c
125
125
  end
126
+
127
+ def test_unix_mbox_fromaddr_method
128
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox")
129
+ assert_equal(TMail::UNIXMbox.fromaddr(p), "mikel@return_path.com")
130
+ end
131
+
132
+ def test_unix_mbox_fromaddr_method_missing_return_path
133
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox_without_return_path")
134
+ assert_equal(TMail::UNIXMbox.fromaddr(p), "mikel@from_address.com")
135
+ end
136
+
137
+ def test_unix_mbox_fromaddr_method_missing_from_address
138
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox_without_from")
139
+ assert_equal(TMail::UNIXMbox.fromaddr(p), "mike@envelope_sender.com.au")
140
+ end
141
+
142
+ def test_unix_mbox_from_addr_method_missing_all_from_fields_in_the_email
143
+ p = TMail::FilePort.new("#{File.dirname(__FILE__)}/fixtures/mailbox_without_any_from_or_sender")
144
+ assert_equal(TMail::UNIXMbox.fromaddr(p), "nobody")
145
+ end
146
+
126
147
  end