sup 0.17.0 → 0.18.0

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +3 -0
  5. data/HACKING +42 -0
  6. data/History.txt +8 -0
  7. data/Rakefile +12 -0
  8. data/ReleaseNotes +4 -0
  9. data/bin/sup-sync +1 -1
  10. data/bin/sup-tweak-labels +6 -1
  11. data/contrib/colorpicker.rb +100 -0
  12. data/contrib/completion/_sup.zsh +114 -0
  13. data/devel/console.sh +3 -0
  14. data/devel/count-loc.sh +3 -0
  15. data/devel/load-index.rb +9 -0
  16. data/devel/profile.rb +12 -0
  17. data/devel/start-console.rb +5 -0
  18. data/doc/FAQ.txt +119 -0
  19. data/doc/Hooks.txt +79 -0
  20. data/doc/Philosophy.txt +69 -0
  21. data/lib/sup/colormap.rb +6 -0
  22. data/lib/sup/modes/thread_index_mode.rb +12 -1
  23. data/lib/sup/modes/thread_view_mode.rb +20 -0
  24. data/lib/sup/version.rb +1 -1
  25. data/sup.gemspec +55 -0
  26. data/test/dummy_source.rb +61 -0
  27. data/test/gnupg_test_home/gpg.conf +1 -0
  28. data/test/gnupg_test_home/pubring.gpg +0 -0
  29. data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
  30. data/test/gnupg_test_home/receiver_secring.gpg +0 -0
  31. data/test/gnupg_test_home/receiver_trustdb.gpg +0 -0
  32. data/test/gnupg_test_home/secring.gpg +0 -0
  33. data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -0
  34. data/test/gnupg_test_home/trustdb.gpg +0 -0
  35. data/test/integration/test_label_service.rb +18 -0
  36. data/test/messages/bad-content-transfer-encoding-1.eml +8 -0
  37. data/test/messages/binary-content-transfer-encoding-2.eml +21 -0
  38. data/test/messages/missing-line.eml +9 -0
  39. data/test/test_crypto.rb +109 -0
  40. data/test/test_header_parsing.rb +168 -0
  41. data/test/test_helper.rb +7 -0
  42. data/test/test_message.rb +532 -0
  43. data/test/test_messages_dir.rb +147 -0
  44. data/test/test_yaml_migration.rb +85 -0
  45. data/test/test_yaml_regressions.rb +17 -0
  46. data/test/unit/service/test_label_service.rb +19 -0
  47. data/test/unit/test_horizontal_selector.rb +40 -0
  48. data/test/unit/util/test_query.rb +46 -0
  49. data/test/unit/util/test_string.rb +57 -0
  50. data/test/unit/util/test_uri.rb +19 -0
  51. metadata +81 -36
  52. checksums.yaml.gz.sig +0 -1
  53. data.tar.gz.sig +0 -0
  54. metadata.gz.sig +0 -0
@@ -0,0 +1,8 @@
1
+ From: foo@example.org
2
+ MIME-Version: 1.0
3
+ Subject: Content-Transfer-Encoding:-bug in sup
4
+ Content-Type: message/rfc822
5
+ Content-Transfer-Encoding: nosuchcontenttransferencoding
6
+
7
+ foo
8
+
@@ -0,0 +1,21 @@
1
+ From: foo@example.org
2
+ MIME-Version: 1.0
3
+ Content-type: multipart/report; boundary="======11647==82899======"; report-type="spam-notification"
4
+ Subject: Important
5
+
6
+ This is a multi-part message in MIME format...
7
+
8
+ --======11647==82899======
9
+ Content-Type: text/plain; charset="ISO-8859-1"
10
+ Content-Disposition: inline
11
+ Content-Transfer-Encoding: quoted-printable
12
+
13
+
14
+ --======11647==82899======
15
+ Content-Type: message/rfc822
16
+ Content-Disposition: attachment
17
+ Content-Transfer-Encoding: binary
18
+
19
+
20
+ --======11647==82899======--
21
+
@@ -0,0 +1,9 @@
1
+ From: foo@aol.com
2
+ To: foo@test.com
3
+ Subject: Encoding bug
4
+ Content-Type: text/plain; charset="iso-8859-1"
5
+ Content-Transfer-Encoding: quoted-printable
6
+
7
+ This is =91 a test: the first line seems to disappear from the mail body but is
8
+ still visible in the thread view.
9
+
@@ -0,0 +1,109 @@
1
+ # tests for sup's crypto libs
2
+ #
3
+ # Copyright Clint Byrum <clint@ubuntu.com> 2011. All Rights Reserved.
4
+ # Copyright Sup Developers 2013.
5
+ #
6
+ # This program is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; either version 2
9
+ # of the License, or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
+ # 02110-1301, USA.
20
+
21
+ require 'test_helper'
22
+ require 'sup'
23
+ require 'stringio'
24
+ require 'tmpdir'
25
+
26
+ module Redwood
27
+
28
+ class TestCryptoManager < ::Minitest::Unit::TestCase
29
+
30
+ def setup
31
+ @from_email = 'sup-test-1@foo.bar'
32
+ @to_email = 'sup-test-2@foo.bar'
33
+ # Use test gnupg setup
34
+ @orig_gnupghome = ENV['GNUPGHOME']
35
+ ENV['GNUPGHOME'] = File.join(File.dirname(__FILE__), 'gnupg_test_home')
36
+
37
+ @path = Dir.mktmpdir
38
+ Redwood::HookManager.init File.join(@path, 'hooks')
39
+
40
+ am = {:default=> {:name => "test", :email=> 'sup-test-1@foo.bar'}}
41
+ Redwood::AccountManager.init am
42
+
43
+ Redwood::CryptoManager.init
44
+
45
+ if not CryptoManager.have_crypto?
46
+ warn "No crypto set up, crypto will not be tested. Reason: #{CryptoManager.not_working_reason}"
47
+ end
48
+ end
49
+
50
+ def teardown
51
+ CryptoManager.deinstantiate!
52
+ AccountManager.deinstantiate!
53
+ HookManager.deinstantiate!
54
+ FileUtils.rm_r @path
55
+
56
+ ENV['GNUPGHOME'] = @orig_gnupghome
57
+ end
58
+
59
+ def test_sign
60
+ if CryptoManager.have_crypto? then
61
+ signed = CryptoManager.sign @from_email,@to_email,"ABCDEFG"
62
+ assert_instance_of RMail::Message, signed
63
+ assert_equal "ABCDEFG", signed.body[0]
64
+ assert signed.body[1].body.length > 0 , "signature length must be > 0"
65
+ assert (signed.body[1].body.include? "-----BEGIN PGP SIGNATURE-----") , "Expecting PGP armored data"
66
+ end
67
+ end
68
+
69
+ def test_encrypt
70
+ if CryptoManager.have_crypto? then
71
+ encrypted = CryptoManager.encrypt @from_email, [@to_email], "ABCDEFG"
72
+ assert_instance_of RMail::Message, encrypted
73
+ assert (encrypted.body[1].body.include? "-----BEGIN PGP MESSAGE-----") , "Expecting PGP armored data"
74
+ end
75
+ end
76
+
77
+ def test_sign_and_encrypt
78
+ if CryptoManager.have_crypto? then
79
+ encrypted = CryptoManager.sign_and_encrypt @from_email, [@to_email], "ABCDEFG"
80
+ assert_instance_of RMail::Message, encrypted
81
+ assert (encrypted.body[1].body.include? "-----BEGIN PGP MESSAGE-----") , "Expecting PGP armored data"
82
+ end
83
+ end
84
+
85
+ def test_decrypt
86
+ if CryptoManager.have_crypto? then
87
+ encrypted = CryptoManager.encrypt @from_email, [@to_email], "ABCDEFG"
88
+ assert_instance_of RMail::Message, encrypted
89
+ assert_instance_of String, (encrypted.body[1].body)
90
+ decrypted = CryptoManager.decrypt encrypted.body[1], true
91
+ assert_instance_of Array, decrypted
92
+ assert_instance_of Chunk::CryptoNotice, decrypted[0]
93
+ assert_instance_of Chunk::CryptoNotice, decrypted[1]
94
+ assert_instance_of RMail::Message, decrypted[2]
95
+ assert_equal "ABCDEFG" , decrypted[2].body
96
+ end
97
+ end
98
+
99
+ def test_verify
100
+ if CryptoManager.have_crypto?
101
+ signed = CryptoManager.sign @from_email, @to_email, "ABCDEFG"
102
+ assert_instance_of RMail::Message, signed
103
+ assert_instance_of String, (signed.body[1].body)
104
+ CryptoManager.verify signed.body[0], signed.body[1], true
105
+ end
106
+ end
107
+ end
108
+
109
+ end
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'test_helper'
4
+ require 'sup'
5
+ require 'stringio'
6
+
7
+ include Redwood
8
+
9
+ class TestMBoxParsing < Minitest::Unit::TestCase
10
+
11
+ def setup
12
+ @path = Dir.mktmpdir
13
+ @mbox = File.join(@path, 'test_mbox')
14
+ end
15
+
16
+ def teardown
17
+ FileUtils.rm_r @path
18
+ end
19
+
20
+ def test_normal_headers
21
+ h = Source.parse_raw_email_header StringIO.new(<<EOS)
22
+ From: Bob <bob@bob.com>
23
+ To: Sally <sally@sally.com>
24
+ EOS
25
+
26
+ assert_equal "Bob <bob@bob.com>", h["from"]
27
+ assert_equal "Sally <sally@sally.com>", h["to"]
28
+ assert_nil h["message-id"]
29
+ end
30
+
31
+ def test_multiline
32
+ h = Source.parse_raw_email_header StringIO.new(<<EOS)
33
+ From: Bob <bob@bob.com>
34
+ Subject: one two three
35
+ four five six
36
+ To: Sally <sally@sally.com>
37
+ References: <seven>
38
+ <eight>
39
+ Seven: Eight
40
+ EOS
41
+
42
+ assert_equal "one two three four five six", h["subject"]
43
+ assert_equal "Sally <sally@sally.com>", h["to"]
44
+ assert_equal "<seven> <eight>", h["references"]
45
+ end
46
+
47
+ def test_ignore_spacing
48
+ variants = [
49
+ "Subject:one two three end\n",
50
+ "Subject: one two three end\n",
51
+ "Subject: one two three end \n",
52
+ ]
53
+ variants.each do |s|
54
+ h = Source.parse_raw_email_header StringIO.new(s)
55
+ assert_equal "one two three end", h["subject"]
56
+ end
57
+ end
58
+
59
+ def test_message_id_ignore_spacing
60
+ variants = [
61
+ "Message-Id: <one@bob.com> \n",
62
+ "Message-Id:<one@bob.com> \n",
63
+ ]
64
+ variants.each do |s|
65
+ h = Source.parse_raw_email_header StringIO.new(s)
66
+ assert_equal "<one@bob.com>", h["message-id"]
67
+ end
68
+ end
69
+
70
+ def test_blank_lines
71
+ h = Source.parse_raw_email_header StringIO.new("")
72
+ assert_equal nil, h["message-id"]
73
+ end
74
+
75
+ def test_empty_headers
76
+ variants = [
77
+ "Message-Id: \n",
78
+ "Message-Id:\n",
79
+ ]
80
+ variants.each do |s|
81
+ h = Source.parse_raw_email_header StringIO.new(s)
82
+ assert_equal "", h["message-id"]
83
+ end
84
+ end
85
+
86
+ def test_detect_end_of_headers
87
+ h = Source.parse_raw_email_header StringIO.new(<<EOS)
88
+ From: Bob <bob@bob.com>
89
+
90
+ To: a dear friend
91
+ EOS
92
+ assert_equal "Bob <bob@bob.com>", h["from"]
93
+ assert_nil h["to"]
94
+
95
+ h = Source.parse_raw_email_header StringIO.new(<<EOS)
96
+ From: Bob <bob@bob.com>
97
+ \r
98
+ To: a dear friend
99
+ EOS
100
+ assert_equal "Bob <bob@bob.com>", h["from"]
101
+ assert_nil h["to"]
102
+
103
+ h = Source.parse_raw_email_header StringIO.new(<<EOS)
104
+ From: Bob <bob@bob.com>
105
+ \r\n\r
106
+ To: a dear friend
107
+ EOS
108
+ assert_equal "Bob <bob@bob.com>", h["from"]
109
+ assert_nil h["to"]
110
+ end
111
+
112
+ def test_from_line_splitting
113
+ l = MBox.new mbox_for_string(<<EOS)
114
+ From sup-talk-bounces@rubyforge.org Mon Apr 27 12:56:18 2009
115
+ From: Bob <bob@bob.com>
116
+ To: a dear friend
117
+
118
+ Hello there friend. How are you?
119
+
120
+ From sea to shining sea
121
+
122
+ From bob@bob.com I get only spam.
123
+
124
+ From bob@bob.com
125
+
126
+ From bob@bob.com
127
+
128
+ (that second one has spaces at the endj
129
+
130
+ This is the end of the email.
131
+ EOS
132
+ offset = l.next_offset 0
133
+ assert_equal 61, offset
134
+ offset = l.next_offset 61
135
+ assert_nil offset
136
+ end
137
+
138
+ def test_more_from_line_splitting
139
+ l = MBox.new mbox_for_string(<<EOS)
140
+ From sup-talk-bounces@rubyforge.org Mon Apr 27 12:56:18 2009
141
+ From: Bob <bob@bob.com>
142
+ To: a dear friend
143
+
144
+ Hello there friend. How are you?
145
+
146
+ From bob@bob.com Mon Apr 27 12:56:19 2009
147
+ From: Bob <bob@bob.com>
148
+ To: a dear friend
149
+
150
+ Hello again! Would you like to buy my products?
151
+ EOS
152
+ offset = l.next_offset 0
153
+ refute_nil offset
154
+
155
+ offset = l.next_offset offset
156
+ refute_nil offset
157
+
158
+ offset = l.next_offset offset
159
+ assert_nil offset
160
+ end
161
+
162
+ def mbox_for_string content
163
+ File.open(@mbox, 'w') do |f|
164
+ f.write content
165
+ end
166
+ "mbox://#{@mbox}"
167
+ end
168
+ end
@@ -0,0 +1,7 @@
1
+ require "rubygems" rescue nil
2
+ require 'minitest/autorun'
3
+ require "rr"
4
+
5
+ class Minitest::Unit::TestCase
6
+ include ::RR::Adapters::MiniTest
7
+ end
@@ -0,0 +1,532 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'test_helper'
4
+ require 'sup'
5
+ require 'stringio'
6
+
7
+ require 'dummy_source'
8
+
9
+ # override File.exists? to make it work with StringIO for testing.
10
+ # FIXME: do aliasing to avoid breaking this when sup moves from
11
+ # File.exists? to File.exist?
12
+
13
+ class File
14
+
15
+ def File.exists? file
16
+ # puts "fake File::exists?"
17
+
18
+ if file.is_a?(StringIO)
19
+ return false
20
+ end
21
+ # use the different function
22
+ File.exist?(file)
23
+ end
24
+
25
+ end
26
+
27
+ module Redwood
28
+
29
+ class TestMessage < ::Minitest::Unit::TestCase
30
+
31
+ def setup
32
+ @path = Dir.mktmpdir
33
+ Redwood::HookManager.init File.join(@path, 'hooks')
34
+ end
35
+
36
+ def teardown
37
+ Redwood::HookManager.deinstantiate!
38
+ FileUtils.rm_r @path
39
+ end
40
+
41
+ def test_simple_message
42
+
43
+ message = <<EOS
44
+ Return-path: <fake_sender@example.invalid>
45
+ Envelope-to: fake_receiver@localhost
46
+ Delivery-date: Sun, 09 Dec 2007 21:48:19 +0200
47
+ Received: from fake_sender by localhost.localdomain with local (Exim 4.67)
48
+ (envelope-from <fake_sender@example.invalid>)
49
+ id 1J1S8R-0006lA-MJ
50
+ for fake_receiver@localhost; Sun, 09 Dec 2007 21:48:19 +0200
51
+ Date: Sun, 9 Dec 2007 21:48:19 +0200
52
+ Mailing-List: contact example-help@example.invalid; run by ezmlm
53
+ Precedence: bulk
54
+ List-Id: <example.list-id.example.invalid>
55
+ List-Post: <mailto:example@example.invalid>
56
+ List-Help: <mailto:example-help@example.invalid>
57
+ List-Unsubscribe: <mailto:example-unsubscribe@example.invalid>
58
+ List-Subscribe: <mailto:example-subscribe@example.invalid>
59
+ Delivered-To: mailing list example@example.invalid
60
+ Delivered-To: moderator for example@example.invalid
61
+ From: Fake Sender <fake_sender@example.invalid>
62
+ To: Fake Receiver <fake_receiver@localhost>
63
+ Subject: Re: Test message subject
64
+ Message-ID: <20071209194819.GA25972@example.invalid>
65
+ References: <E1J1Rvb-0006k2-CE@localhost.localdomain>
66
+ MIME-Version: 1.0
67
+ Content-Type: text/plain; charset=us-ascii
68
+ Content-Disposition: inline
69
+ In-Reply-To: <E1J1Rvb-0006k2-CE@localhost.localdomain>
70
+ User-Agent: Sup/0.3
71
+
72
+ Test message!
73
+ EOS
74
+
75
+ source = DummySource.new("sup-test://test_simple_message")
76
+ source.messages = [ message ]
77
+ source_info = 0
78
+
79
+ sup_message = Message.build_from_source(source, source_info)
80
+ sup_message.load_from_source!
81
+
82
+ # see how well parsing the header went
83
+
84
+ to = sup_message.to
85
+ # "to" is an Array containing person items
86
+
87
+ # there should be only one item
88
+ assert_equal(1, to.length)
89
+
90
+ # sup doesn't do capitalized letters in email addresses
91
+ assert_equal("fake_receiver@localhost", to[0].email)
92
+ assert_equal("Fake Receiver", to[0].name)
93
+
94
+ from = sup_message.from
95
+ # "from" is just a simple person item
96
+
97
+ assert_equal("fake_sender@example.invalid", from.email)
98
+ assert_equal("Fake Sender", from.name)
99
+
100
+ subj = sup_message.subj
101
+ assert_equal("Re: Test message subject", subj)
102
+
103
+ list_subscribe = sup_message.list_subscribe
104
+ assert_equal("<mailto:example-subscribe@example.invalid>", list_subscribe)
105
+
106
+ list_unsubscribe = sup_message.list_unsubscribe
107
+ assert_equal("<mailto:example-unsubscribe@example.invalid>", list_unsubscribe)
108
+
109
+ list_address = sup_message.list_address
110
+ assert_equal("example@example.invalid", list_address.email)
111
+ assert_equal("example", list_address.name)
112
+
113
+ date = sup_message.date
114
+ assert_equal(Time.parse("Sun, 9 Dec 2007 21:48:19 +0200"), date)
115
+
116
+ id = sup_message.id
117
+ assert_equal("20071209194819.GA25972@example.invalid", id)
118
+
119
+ refs = sup_message.refs
120
+ assert_equal(1, refs.length)
121
+ assert_equal("E1J1Rvb-0006k2-CE@localhost.localdomain", refs[0])
122
+
123
+ replytos = sup_message.replytos
124
+ assert_equal(1, replytos.length)
125
+ assert_equal("E1J1Rvb-0006k2-CE@localhost.localdomain", replytos[0])
126
+
127
+ cc = sup_message.cc
128
+ # there are no ccs
129
+ assert_equal(0, cc.length)
130
+
131
+ bcc = sup_message.bcc
132
+ # there are no bccs
133
+ assert_equal(0, bcc.length)
134
+
135
+ recipient_email = sup_message.recipient_email
136
+ assert_equal("fake_receiver@localhost", recipient_email)
137
+
138
+ message_source = sup_message.source
139
+ assert_equal(message_source, source)
140
+
141
+ message_source_info = sup_message.source_info
142
+ assert_equal(message_source_info, source_info)
143
+
144
+ # read the message body chunks
145
+
146
+ chunks = sup_message.load_from_source!
147
+
148
+ # there should be only one chunk
149
+ assert_equal(1, chunks.length)
150
+
151
+ lines = chunks[0].lines
152
+
153
+ # there should be only one line
154
+ assert_equal(1, lines.length)
155
+
156
+ assert_equal("Test message!", lines[0])
157
+
158
+ end
159
+
160
+ def test_multipart_message
161
+
162
+ message = <<EOS
163
+ From fake_receiver@localhost Sun Dec 09 22:33:37 +0200 2007
164
+ Subject: Re: Test message subject
165
+ From: Fake Receiver <fake_receiver@localhost>
166
+ To: Fake Sender <fake_sender@example.invalid>
167
+ References: <E1J1Rvb-0006k2-CE@localhost.localdomain> <20071209194819.GA25972example.invalid>
168
+ In-Reply-To: <20071209194819.GA25972example.invalid>
169
+ Date: Sun, 09 Dec 2007 22:33:37 +0200
170
+ Message-Id: <1197232243-sup-2663example.invalid>
171
+ User-Agent: Sup/0.3
172
+ Content-Type: multipart/mixed; boundary="=-1197232418-506707-26079-6122-2-="
173
+ MIME-Version: 1.0
174
+
175
+
176
+ --=-1197232418-506707-26079-6122-2-=
177
+ Content-Type: text/plain; charset=utf-8
178
+ Content-Disposition: inline
179
+
180
+ Excerpts from Fake Sender's message of Sun Dec 09 21:48:19 +0200 2007:
181
+ > Test message!
182
+
183
+ Thanks for the message!
184
+ --=-1197232418-506707-26079-6122-2-=
185
+ Content-Disposition: attachment; filename="HACKING"
186
+ Content-Type: application/octet-stream; name="HACKING"
187
+ Content-Transfer-Encoding: base64
188
+
189
+ UnVubmluZyBTdXAgbG9jYWxseQotLS0tLS0tLS0tLS0tLS0tLS0tCkludm9r
190
+ ZSBpdCBsaWtlIHRoaXM6CgpydWJ5IC1JIGxpYiAtdyBiaW4vc3VwCgpZb3Un
191
+ bGwgaGF2ZSB0byBpbnN0YWxsIGFsbCBnZW1zIG1lbnRpb25lZCBpbiB0aGUg
192
+ UmFrZWZpbGUgKGxvb2sgZm9yIHRoZSBsaW5lCnNldHRpbmcgcC5leHRyYV9k
193
+ ZXBzKS4gSWYgeW91J3JlIG9uIGEgRGViaWFuIG9yIERlYmlhbi1iYXNlZCBz
194
+ eXN0ZW0gKGUuZy4KVWJ1bnR1KSwgeW91J2xsIGhhdmUgdG8gbWFrZSBzdXJl
195
+ IHlvdSBoYXZlIGEgY29tcGxldGUgUnVieSBpbnN0YWxsYXRpb24sCmVzcGVj
196
+ aWFsbHkgbGlic3NsLXJ1YnkuCgpDb2Rpbmcgc3RhbmRhcmRzCi0tLS0tLS0t
197
+ LS0tLS0tLS0KCi0gRG9uJ3Qgd3JhcCBjb2RlIHVubGVzcyBpdCByZWFsbHkg
198
+ YmVuZWZpdHMgZnJvbSBpdC4gVGhlIGRheXMgb2YKICA4MC1jb2x1bW4gZGlz
199
+ cGxheXMgYXJlIGxvbmcgb3Zlci4gQnV0IGRvIHdyYXAgY29tbWVudHMgYW5k
200
+ IG90aGVyCiAgdGV4dCBhdCB3aGF0ZXZlciBFbWFjcyBtZXRhLVEgZG9lcy4K
201
+ LSBJIGxpa2UgcG9ldHJ5IG1vZGUuCi0gVXNlIHt9IGZvciBvbmUtbGluZXIg
202
+ YmxvY2tzIGFuZCBkby9lbmQgZm9yIG11bHRpLWxpbmUgYmxvY2tzLgoK
203
+
204
+ --=-1197232418-506707-26079-6122-2-=
205
+ Content-Disposition: attachment; filename="Manifest.txt"
206
+ Content-Type: text/plain; name="Manifest.txt"
207
+ Content-Transfer-Encoding: quoted-printable
208
+
209
+ HACKING
210
+ History.txt
211
+ LICENSE
212
+ Manifest.txt
213
+ README.txt
214
+ Rakefile
215
+ bin/sup
216
+ bin/sup-add
217
+ bin/sup-config
218
+ bin/sup-dump
219
+ bin/sup-recover-sources
220
+ bin/sup-sync
221
+ bin/sup-sync-back
222
+
223
+ --=-1197232418-506707-26079-6122-2-=--
224
+ EOS
225
+ source = DummySource.new("sup-test://test_multipart_message")
226
+ source.messages = [ message ]
227
+ source_info = 0
228
+
229
+ sup_message = Message.build_from_source(source, source_info)
230
+ sup_message.load_from_source!
231
+
232
+ # read the message body chunks
233
+
234
+ chunks = sup_message.load_from_source!
235
+
236
+ # this time there should be four chunks: first the quoted part of
237
+ # the message, then the non-quoted part, then the two attachments
238
+ assert_equal(4, chunks.length)
239
+
240
+ assert_equal(chunks[0].class, Redwood::Chunk::Quote)
241
+ assert_equal(chunks[1].class, Redwood::Chunk::Text)
242
+ assert_equal(chunks[2].class, Redwood::Chunk::Attachment)
243
+ assert_equal(chunks[3].class, Redwood::Chunk::Attachment)
244
+
245
+ # further testing of chunks will happen in test_message_chunks.rb
246
+ # (possibly not yet implemented)
247
+
248
+ end
249
+
250
+ def test_broken_message_1
251
+
252
+ # an example of a broken message, missing "to" and "from" fields
253
+
254
+ message = <<EOS
255
+ Return-path: <fake_sender@example.invalid>
256
+ Envelope-to: fake_receiver@localhost
257
+ Delivery-date: Sun, 09 Dec 2007 21:48:19 +0200
258
+ Received: from fake_sender by localhost.localdomain with local (Exim 4.67)
259
+ (envelope-from <fake_sender@example.invalid>)
260
+ id 1J1S8R-0006lA-MJ
261
+ for fake_receiver@localhost; Sun, 09 Dec 2007 21:48:19 +0200
262
+ Date: Sun, 9 Dec 2007 21:48:19 +0200
263
+ Subject: Re: Test message subject
264
+ Message-ID: <20071209194819.GA25972@example.invalid>
265
+ References: <E1J1Rvb-0006k2-CE@localhost.localdomain>
266
+ MIME-Version: 1.0
267
+ Content-Type: text/plain; charset=us-ascii
268
+ Content-Disposition: inline
269
+ In-Reply-To: <E1J1Rvb-0006k2-CE@localhost.localdomain>
270
+ User-Agent: Sup/0.3
271
+
272
+ Test message!
273
+ EOS
274
+
275
+ source = DummySource.new("sup-test://test_broken_message_1")
276
+ source.messages = [ message ]
277
+ source_info = 0
278
+
279
+ sup_message = Message.build_from_source(source, source_info)
280
+ sup_message.load_from_source!
281
+
282
+ to = sup_message.to
283
+
284
+ # there should no items, since the message doesn't have any
285
+ # recipients -- still not nil
286
+ assert_equal(0, to.length)
287
+
288
+ # from will have bogus values
289
+ from = sup_message.from
290
+ # very basic email address check
291
+ assert_match(/\w+@\w+\.\w{2,4}/, from.email)
292
+ refute_nil(from.name)
293
+
294
+ end
295
+
296
+ def test_broken_message_2
297
+
298
+ # an example of a broken message, no body at all
299
+
300
+ message = <<EOS
301
+ Return-path: <fake_sender@example.invalid>
302
+ From: Fake Sender <fake_sender@example.invalid>
303
+ To: Fake Receiver <fake_receiver@localhost>
304
+ Envelope-to: fake_receiver@localhost
305
+ Delivery-date: Sun, 09 Dec 2007 21:48:19 +0200
306
+ Received: from fake_sender by localhost.localdomain with local (Exim 4.67)
307
+ (envelope-from <fake_sender@example.invalid>)
308
+ id 1J1S8R-0006lA-MJ
309
+ for fake_receiver@localhost; Sun, 09 Dec 2007 21:48:19 +0200
310
+ Date: Sun, 9 Dec 2007 21:48:19 +0200
311
+ Subject: Re: Test message subject
312
+ Message-ID: <20071209194819.GA25972@example.invalid>
313
+ References: <E1J1Rvb-0006k2-CE@localhost.localdomain>
314
+ MIME-Version: 1.0
315
+ Content-Type: text/plain; charset=us-ascii
316
+ Content-Disposition: inline
317
+ In-Reply-To: <E1J1Rvb-0006k2-CE@localhost.localdomain>
318
+ User-Agent: Sup/0.3
319
+ EOS
320
+
321
+ source = DummySource.new("sup-test://test_broken_message_1")
322
+ source.messages = [ message ]
323
+ source_info = 0
324
+
325
+ sup_message = Message.build_from_source(source, source_info)
326
+ sup_message.load_from_source!
327
+
328
+ # read the message body chunks: no errors should reach this level
329
+
330
+ chunks = sup_message.load_from_source!
331
+
332
+ # the chunks list should be empty
333
+
334
+ assert_equal(0, chunks.length)
335
+
336
+ end
337
+
338
+ def test_multipart_message_2
339
+
340
+ message = <<EOS
341
+ Return-path: <vim-mac-return-3938-fake_receiver=localhost@vim.org>
342
+ Envelope-to: fake_receiver@localhost
343
+ Delivery-date: Wed, 14 Jun 2006 19:22:54 +0300
344
+ Received: from localhost ([127.0.0.1] helo=localhost.localdomain)
345
+ by localhost.localdomain with esmtp (Exim 4.60)
346
+ (envelope-from <vim-mac-return-3938-fake_receiver=localhost@vim.org>)
347
+ id 1FqXk3-0006jM-48
348
+ for fake_receiver@localhost; Wed, 14 Jun 2006 18:57:15 +0300
349
+ Received: from pop.gmail.com
350
+ by localhost.localdomain with POP3 (fetchmail-6.3.2)
351
+ for <fake_receiver@localhost> (single-drop); Wed, 14 Jun 2006 18:57:15 +0300 (EEST)
352
+ X-Gmail-Received: 8ee0fe5f895736974c042c8eaf176014b1ba7b88
353
+ Delivered-To: fake_receiver@localhost
354
+ Received: by 10.49.8.16 with SMTP id l16cs11327nfi;
355
+ Sun, 26 Mar 2006 19:31:56 -0800 (PST)
356
+ Received: by 10.66.224.8 with SMTP id w8mr2172862ugg;
357
+ Sun, 26 Mar 2006 19:31:56 -0800 (PST)
358
+ Received: from foobar.math.fu-berlin.de (foobar.math.fu-berlin.de [160.45.45.151])
359
+ by mx.gmail.com with SMTP id j3si553645ugd.2006.03.26.19.31.56;
360
+ Sun, 26 Mar 2006 19:31:56 -0800 (PST)
361
+ Received-SPF: neutral (gmail.com: 160.45.45.151 is neither permitted nor denied by best guess record for domain of vim-mac-return-3938-fake_receiver=localhost@vim.org)
362
+ Message-Id: <44275cac.74a494f1.315a.ffff825cSMTPIN_ADDED@mx.gmail.com>
363
+ Received: (qmail 24265 invoked by uid 200); 27 Mar 2006 02:32:39 -0000
364
+ Mailing-List: contact vim-mac-help@vim.org; run by ezmlm
365
+ Precedence: bulk
366
+ Delivered-To: mailing list vim-mac@vim.org
367
+ Received: (qmail 7913 invoked from network); 26 Mar 2006 23:37:34 -0000
368
+ Received: from cpe-138-217-96-243.vic.bigpond.net.au (HELO vim.org) (138.217.96.243)
369
+ by foobar.math.fu-berlin.de with SMTP; 26 Mar 2006 23:37:34 -0000
370
+ From: fake_sender@example.invalid
371
+ To: vim-mac@vim.org
372
+ Subject: Mail Delivery (failure vim-mac@vim.org)
373
+ Date: Mon, 27 Mar 2006 10:29:39 +1000
374
+ MIME-Version: 1.0
375
+ Content-Type: multipart/related;
376
+ type="multipart/alternative";
377
+ boundary="----=_NextPart_000_001B_01C0CA80.6B015D10"
378
+ X-Priority: 3
379
+ X-MSMail-Priority: Normal
380
+
381
+ ------=_NextPart_000_001B_01C0CA80.6B015D10
382
+ Content-Type: multipart/alternative;
383
+ boundary="----=_NextPart_001_001C_01C0CA80.6B015D10"
384
+
385
+ ------=_NextPart_001_001C_01C0CA80.6B015D10
386
+ Content-Type: text/plain;
387
+ charset="iso-8859-1"
388
+ Content-Transfer-Encoding: quoted-printable
389
+
390
+ ------=_NextPart_001_001C_01C0CA80.6B015D10
391
+ Content-Type: text/html;
392
+ charset="iso-8859-1"
393
+ Content-Transfer-Encoding: quoted-printable
394
+
395
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
396
+ <HTML><HEAD>
397
+ <META content=3D"text/html; charset=3Diso-8859-1" =
398
+ http-equiv=3DContent-Type>
399
+ <META content=3D"MSHTML 5.00.2920.0" name=3DGENERATOR>
400
+ <STYLE></STYLE>
401
+ </HEAD>
402
+ <BODY bgColor=3D#ffffff>If the message will not displayed automatically,<br>
403
+ follow the link to read the delivered message.<br><br>
404
+ Received message is available at:<br>
405
+ <a href=3Dcid:031401Mfdab4$3f3dL780$73387018@57W81fa70Re height=3D0 width=3D0>www.vim.org/inbox/vim-mac/read.php?sessionid-18559</a>
406
+ <iframe
407
+ src=3Dcid:031401Mfdab4$3f3dL780$73387018@57W81fa70Re height=3D0 width=3D0></iframe>
408
+ <DIV>&nbsp;</DIV></BODY></HTML>
409
+
410
+ ------=_NextPart_001_001C_01C0CA80.6B015D10--
411
+
412
+ ------=_NextPart_000_001B_01C0CA80.6B015D10--
413
+
414
+
415
+ EOS
416
+ source = DummySource.new("sup-test://test_multipart_message_2")
417
+ source.messages = [ message ]
418
+ source_info = 0
419
+
420
+ sup_message = Message.build_from_source(source, source_info)
421
+ sup_message.load_from_source!
422
+
423
+ # read the message body chunks
424
+
425
+ sup_message.load_from_source!
426
+ end
427
+
428
+ def test_blank_header_lines
429
+
430
+ message = <<EOS
431
+ Return-Path: <monitor-list-bounces@widget.com>
432
+ X-Original-To: nobody@localhost
433
+ Delivered-To: nobody@localhost.eng.widget.com
434
+ Received: from localhost (localhost.localdomain [127.0.0.1])
435
+ by soquel.eng.widget.com (Postfix) with ESMTP id 609BC13C0DB1
436
+ for <nobody@localhost>; Thu, 19 Mar 2009 13:43:21 -0700 (PDT)
437
+ MIME-Version: 1.0
438
+ Received: from pa-excas-vip.widget.com [10.16.67.200]
439
+ by localhost with IMAP (fetchmail-6.2.5)
440
+ for nobody@localhost (single-drop); Thu, 19 Mar 2009 13:43:21 -0700 (PDT)
441
+ Received: from pa-exht01.widget.com (10.113.81.167) by pa-excaht11.widget.com
442
+ (10.113.81.197) with Microsoft SMTP Server (TLS) id 8.1.311.2; Thu, 19 Mar
443
+ 2009 13:42:30 -0700
444
+ Received: from mailman2.widget.com (10.16.64.159) by pa-exht01.widget.com
445
+ (10.113.81.167) with Microsoft SMTP Server id 8.1.336.0; Thu, 19 Mar 2009
446
+ 13:42:30 -0700
447
+ Received: by mailman2.widget.com (Postfix) id 47095AE30856; Thu, 19 Mar 2009
448
+ 13:42:29 -0700 (PDT)
449
+ Received: from countchocula.widget.com (localhost.localdomain [127.0.0.1]) by
450
+ mailman2.widget.com (Postfix) with ESMTP id 5F782ABC5948; Thu, 19 Mar 2009
451
+ 13:42:28 -0700 (PDT)
452
+ Received: from mailhost4.widget.com (mailhost4.widget.com [10.16.67.124]) by
453
+ mailman2.widget.com (Postfix) with ESMTP id 6CDCCABC5948 for
454
+ <monitor-list@mailman2.widget.com>; Thu, 19 Mar 2009 13:42:26 -0700 (PDT)
455
+ Received: by mailhost4.widget.com (Postfix) id 2364AC9AC4; Thu, 19 Mar 2009
456
+ 13:42:26 -0700 (PDT)
457
+ Received: from pa-exht01.widget.com (pa-exht01.widget.com [10.113.81.167]) by
458
+ mailhost4.widget.com (Postfix) with ESMTP id 17A68C9AC3 for
459
+ <monitor-list@widget.com>; Thu, 19 Mar 2009 13:42:26 -0700 (PDT)
460
+ Received: from PA-EXMBX04.widget.com ([10.113.81.142]) by pa-exht01.widget.com
461
+ ([10.113.81.167]) with mapi; Thu, 19 Mar 2009 13:42:26 -0700
462
+ From: Some User <someuser@widget.com>
463
+ To: "monitor-list@widget.com" <monitor-list@widget.com>
464
+ Sender: "monitor-list-bounces@widget.com" <monitor-list-bounces@widget.com>
465
+ Date: Thu, 19 Mar 2009 13:42:25 -0700
466
+ Subject: Looking for a mac
467
+ Thread-Topic: Looking for a mac
468
+ Thread-Index: AQHJqNM1xIqqjNRWuUCUBaxzPFK5eQ==
469
+ Message-ID:
470
+ <D3C12B2AD838B44DA9D6B2CA334246D011E72A73A4@PA-EXMBX04.widget.com>
471
+ List-Help: <mailto:monitor-list-request@widget.com?subject=help>
472
+ List-Subscribe: <http://mailman2.widget.com/mailman/listinfo/monitor-list>,
473
+ <mailto:monitor-list-request@widget.com?subject=subscribe>
474
+ List-Unsubscribe:
475
+ <http://mailman2.widget.com/mailman/listinfo/monitor-list>,
476
+ <mailto:monitor-list-request@widget.com?subject=unsubscribe>
477
+ Accept-Language: en-US
478
+ Content-Language: en-US
479
+ X-MS-Exchange-Organization-AuthAs: Anonymous
480
+ X-MS-Exchange-Organization-AuthSource: pa-exht01.widget.com
481
+ X-MS-Has-Attach:
482
+ X-Auto-Response-Suppress: All
483
+ X-MS-TNEF-Correlator:
484
+ acceptlanguage: en-US
485
+ delivered-to: monitor-list@widget.com
486
+ errors-to: monitor-list-bounces@widget.com
487
+ list-id: engineering monitor related <monitor-list.widget.com>
488
+ x-mailman-version: 2.1.8
489
+ x-beenthere: monitor-list@widget.com
490
+ x-original-to: monitor-list@mailman2.widget.com
491
+ list-post: <mailto:monitor-list@widget.com>
492
+ list-archive: <http://mailman2.widget.com/pipermail/monitor-list>
493
+ Content-Type: text/plain; charset="us-ascii"
494
+ Content-Transfer-Encoding: quoted-printable
495
+
496
+ Hi all,
497
+
498
+ Just wondering if anybody can lend me a mac to reproduce PR 384931 ?
499
+ Thanks.
500
+
501
+ Michael=
502
+ EOS
503
+
504
+ source = DummySource.new("sup-test://test_blank_header_lines")
505
+ source.messages = [ message ]
506
+ source_info = 0
507
+
508
+ sup_message = Message.build_from_source(source, source_info)
509
+ sup_message.load_from_source!
510
+
511
+ # See how well parsing the message ID went.
512
+ id = sup_message.id
513
+ assert_equal("D3C12B2AD838B44DA9D6B2CA334246D011E72A73A4@PA-EXMBX04.widget.com", id)
514
+
515
+ # Look at another header field whose first line was blank.
516
+ list_unsubscribe = sup_message.list_unsubscribe
517
+ assert_equal("<http://mailman2.widget.com/mailman/listinfo/monitor-list>,\n \t" +
518
+ "<mailto:monitor-list-request@widget.com?subject=unsubscribe>",
519
+ list_unsubscribe)
520
+
521
+ end
522
+
523
+ # TODO: test different error cases, malformed messages etc.
524
+
525
+ # TODO: test different quoting styles, see that they are all divided
526
+ # to chunks properly
527
+
528
+ end
529
+
530
+ end
531
+
532
+ # vim:noai:ts=2:sw=2: