tmail 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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