gurgitate-mail 1.8.4 → 1.8.5
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.
- data/bin/gurgitate-mail +5 -1
- data/lib/gurgitate-mail.rb +30 -28
- data/lib/gurgitate/deliver.rb +8 -11
- data/lib/gurgitate/deliver/maildir.rb +5 -1
- data/lib/gurgitate/headers.rb +106 -51
- data/lib/gurgitate/mailmessage.rb +56 -11
- data/test/gurgitate-test.rb +62 -0
- data/{test.rb → test/runtests.rb} +4 -1
- data/test/test_configuration.rb +35 -0
- data/test/test_delivery.rb +213 -0
- data/test/test_header.rb +154 -0
- data/test/test_headers.rb +478 -0
- data/test/test_process.rb +87 -0
- data/test/test_rules.rb +108 -0
- data/test/test_writing.rb +56 -0
- metadata +14 -6
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/ui/console/testrunner'
|
3
|
+
require 'stringio'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'pathname'
|
6
|
+
require 'irb'
|
7
|
+
require "./gurgitate-mail"
|
8
|
+
|
9
|
+
class GurgitateTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
currentdir = Pathname.new(File.join(File.dirname(__FILE__),
|
12
|
+
"..")).realpath.to_s
|
13
|
+
@testdir = File.join(currentdir,"test-data")
|
14
|
+
testdir = @testdir
|
15
|
+
@folders = File.join(@testdir,"folders")
|
16
|
+
folders = @folders
|
17
|
+
FileUtils.rmtree @testdir if File.exists? @testdir
|
18
|
+
Dir.mkdir @testdir
|
19
|
+
Dir.mkdir @folders
|
20
|
+
m = StringIO.new("From: me\nTo: you\nSubject: test\n\nHi.\n")
|
21
|
+
@gurgitate = nil
|
22
|
+
@gurgitate = Gurgitate::Gurgitate.new(m)
|
23
|
+
|
24
|
+
@sendmail = File.join(@testdir, "bin", "sendmail")
|
25
|
+
sendmail = @sendmail
|
26
|
+
|
27
|
+
Dir.mkdir File.join(@testdir,"bin")
|
28
|
+
|
29
|
+
File.open(@sendmail,"w") do |f|
|
30
|
+
f.puts "#!/bin/sh"
|
31
|
+
f.puts "exec > #{@testdir}/sendmail_output 2>&1"
|
32
|
+
f.puts 'echo "$@"'
|
33
|
+
f.puts 'cat'
|
34
|
+
end
|
35
|
+
|
36
|
+
FileUtils.chmod 0755, @sendmail
|
37
|
+
|
38
|
+
@gurgitate.instance_eval do
|
39
|
+
sendmail "/bin/cat"
|
40
|
+
homedir testdir
|
41
|
+
spooldir testdir
|
42
|
+
spoolfile File.join(testdir, "default")
|
43
|
+
maildir folders
|
44
|
+
end
|
45
|
+
@spoolfile = File.join(testdir, "default")
|
46
|
+
end
|
47
|
+
|
48
|
+
def maildirmake mailbox # per the command
|
49
|
+
FileUtils.mkdir mailbox
|
50
|
+
%w/cur tmp new/.each do |subdir|
|
51
|
+
FileUtils.mkdir File.join(mailbox, subdir)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def teardown
|
56
|
+
FileUtils.rmtree @testdir
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_truth
|
60
|
+
assert true
|
61
|
+
end
|
62
|
+
end
|
@@ -7,6 +7,7 @@
|
|
7
7
|
require 'test/unit'
|
8
8
|
require 'test/unit/ui/console/testrunner'
|
9
9
|
require 'stringio'
|
10
|
+
require 'pathname'
|
10
11
|
|
11
12
|
def runtests(testcases)
|
12
13
|
testcases.each do |testcase|
|
@@ -14,7 +15,9 @@ def runtests(testcases)
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
+
testpath = Pathname.new(__FILE__).dirname.realpath
|
19
|
+
|
20
|
+
testcases = Dir[File.join(testpath,"test_*")].map do |file|
|
18
21
|
load file
|
19
22
|
eval("TC_" + File.basename(file,".rb").sub(/^test_/,'').capitalize)
|
20
23
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "test/gurgitate-test"
|
2
|
+
require "etc"
|
3
|
+
|
4
|
+
class TC_Configuration < GurgitateTest
|
5
|
+
def test_default_configuration
|
6
|
+
assert_equal Gurgitate::Deliver::MBox, @gurgitate.folderstyle
|
7
|
+
assert_equal @folders, @gurgitate.maildir
|
8
|
+
assert_equal @spoolfile, @gurgitate.spoolfile
|
9
|
+
assert_equal @testdir, @gurgitate.homedir
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_changing_folderstyle_to_maildir
|
13
|
+
assert_nothing_raised do
|
14
|
+
@gurgitate.folderstyle Gurgitate::Deliver::Maildir
|
15
|
+
end
|
16
|
+
assert_equal File.join(@testdir,"Maildir"), @gurgitate.spoolfile
|
17
|
+
assert_equal File.join(@testdir,"Maildir"), @gurgitate.maildir
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_changing_folderstyle_to_mbox
|
21
|
+
assert_nothing_raised do
|
22
|
+
@gurgitate.folderstyle Gurgitate::Deliver::MBox
|
23
|
+
end
|
24
|
+
|
25
|
+
assert_equal "/var/spool/mail", @gurgitate.spooldir
|
26
|
+
assert_equal File.join("/var/spool/mail",
|
27
|
+
Etc.getpwuid.name), @gurgitate.spoolfile
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_illegal_folderstyle_syntax
|
31
|
+
assert_raises ArgumentError do
|
32
|
+
@gurgitate.folderstyle 1, 2, 3
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/unit/ui/console/testrunner'
|
3
|
+
require 'stringio'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'pathname'
|
6
|
+
require 'irb'
|
7
|
+
require "./gurgitate-mail"
|
8
|
+
require "test/gurgitate-test"
|
9
|
+
|
10
|
+
class TC_Delivery < GurgitateTest
|
11
|
+
#************************************************************************
|
12
|
+
# tests
|
13
|
+
#************************************************************************
|
14
|
+
|
15
|
+
def test_basic_delivery
|
16
|
+
assert_nothing_raised do
|
17
|
+
@gurgitate.process { nil }
|
18
|
+
end
|
19
|
+
assert File.exists?(@spoolfile)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_detect_mbox
|
23
|
+
Dir.mkdir(@testdir) rescue nil
|
24
|
+
File.open(@spoolfile, File::WRONLY | File::CREAT) do |f|
|
25
|
+
f.print ""
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_nothing_raised do
|
29
|
+
@gurgitate.process { nil }
|
30
|
+
end
|
31
|
+
|
32
|
+
assert File.exists?(@spoolfile)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_detect_maildir
|
36
|
+
maildirmake @spoolfile
|
37
|
+
|
38
|
+
assert_nothing_raised do
|
39
|
+
@gurgitate.process { nil }
|
40
|
+
end
|
41
|
+
|
42
|
+
assert Dir[File.join(@spoolfile,"new","*")].length > 0
|
43
|
+
assert File.exists?(Dir[File.join(@spoolfile,"new","*")][0])
|
44
|
+
FileUtils.rmtree @spoolfile
|
45
|
+
teardown
|
46
|
+
test_detect_mbox
|
47
|
+
setup
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_save_folders
|
51
|
+
assert_nothing_raised do
|
52
|
+
@gurgitate.process do
|
53
|
+
save "=test"
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
assert File.exists?(File.join(@folders, "test"))
|
59
|
+
assert File.stat(File.join(@folders, "test")).file?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_save_guess_maildir
|
63
|
+
maildirmake File.join(@folders,"test")
|
64
|
+
|
65
|
+
assert File.exists?(File.join(@folders, "test"))
|
66
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
67
|
+
assert File.exists?(File.join(@folders, "test", "new"))
|
68
|
+
|
69
|
+
assert_equal 0, Dir[File.join(@folders, "test", "new", "*")].length
|
70
|
+
assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
|
71
|
+
|
72
|
+
assert_nothing_raised do
|
73
|
+
@gurgitate.process do
|
74
|
+
save "=test"
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
assert File.exists?(File.join(@folders, "test"))
|
80
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
81
|
+
assert File.exists?(File.join(@folders, "test", "new"))
|
82
|
+
assert File.stat(File.join(@folders, "test","new")).directory?
|
83
|
+
assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
|
84
|
+
assert_equal 1, Dir[File.join(@folders, "test", "new", "*")].length
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_save_maildir_collision
|
88
|
+
maildirmake File.join(@folders,"test")
|
89
|
+
|
90
|
+
assert File.exists?(File.join(@folders, "test"))
|
91
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
92
|
+
assert File.exists?(File.join(@folders, "test", "new"))
|
93
|
+
|
94
|
+
assert_equal 0, Dir[File.join(@folders, "test", "new", "*")].length
|
95
|
+
assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
|
96
|
+
|
97
|
+
assert_nothing_raised do
|
98
|
+
@gurgitate.process do
|
99
|
+
save "=test"
|
100
|
+
save "=test"
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
assert File.exists?(File.join(@folders, "test"))
|
106
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
107
|
+
assert File.exists?(File.join(@folders, "test", "new"))
|
108
|
+
assert File.stat(File.join(@folders, "test","new")).directory?
|
109
|
+
assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
|
110
|
+
assert_equal 2, Dir[File.join(@folders, "test", "new", "*")].length
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_save_create_maildir
|
114
|
+
maildirmake @spoolfile
|
115
|
+
|
116
|
+
assert_nothing_raised do
|
117
|
+
@gurgitate.process do
|
118
|
+
@folderstyle = Gurgitate::Deliver::Maildir
|
119
|
+
@maildir = @spoolfile
|
120
|
+
save "=test"
|
121
|
+
break
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
assert File.exists?(File.join(@spoolfile, ".test"))
|
126
|
+
assert File.stat(File.join(@spoolfile, ".test")).directory?
|
127
|
+
assert File.exists?(File.join(@spoolfile, ".test", "new"))
|
128
|
+
assert File.stat(File.join(@spoolfile, ".test","new")).directory?
|
129
|
+
assert_equal 0, Dir[File.join(@spoolfile, ".test", "cur", "*")].length
|
130
|
+
assert_equal 1, Dir[File.join(@spoolfile, ".test", "new", "*")].length
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_save_bad_filename
|
134
|
+
assert_nothing_raised do
|
135
|
+
@gurgitate.process do
|
136
|
+
save "testing"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
assert File.exists?(@spoolfile)
|
141
|
+
assert !File.exists?("testing")
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_cannot_save
|
145
|
+
FileUtils.touch @spoolfile
|
146
|
+
FileUtils.chmod 0, @spoolfile
|
147
|
+
|
148
|
+
assert_raises Errno::EACCES do
|
149
|
+
@gurgitate.process do
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_mailbox_heuristics_mbox
|
156
|
+
@gurgitate.instance_eval do
|
157
|
+
@folderstyle = nil
|
158
|
+
end
|
159
|
+
|
160
|
+
assert_nothing_raised do
|
161
|
+
@gurgitate.process do
|
162
|
+
save "=test"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
assert File.exists?(File.join(@folders, "test"))
|
167
|
+
assert File.stat(File.join(@folders, "test")).file?
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_mailbox_heuristics_maildir
|
171
|
+
@gurgitate.instance_eval do
|
172
|
+
@folderstyle = nil
|
173
|
+
end
|
174
|
+
|
175
|
+
assert_nothing_raised do
|
176
|
+
@gurgitate.process do
|
177
|
+
save "=test/"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
assert File.exists?(File.join(@folders, "test"))
|
182
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
183
|
+
assert File.exists?(File.join(@folders, "test", "new"))
|
184
|
+
assert File.stat(File.join(@folders, "test","new")).directory?
|
185
|
+
assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
|
186
|
+
assert_equal 1, Dir[File.join(@folders, "test", "new", "*")].length
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_message_parsed_correctly
|
190
|
+
assert_equal("From: me",@gurgitate.header("From"))
|
191
|
+
assert_equal("To: you", @gurgitate.header("To"))
|
192
|
+
assert_equal("Subject: test", @gurgitate.header("Subject"))
|
193
|
+
assert_equal("Hi.\n", @gurgitate.body, "Message body is wrong")
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_message_written_correctly
|
197
|
+
test_message_parsed_correctly
|
198
|
+
assert_nothing_raised do
|
199
|
+
@gurgitate.process
|
200
|
+
end
|
201
|
+
|
202
|
+
mess=nil
|
203
|
+
assert_nothing_raised do
|
204
|
+
mess = Gurgitate::Mailmessage.new(File.read(@spoolfile))
|
205
|
+
end
|
206
|
+
|
207
|
+
assert_equal("From: me", mess.header("From"), "From header is wrong")
|
208
|
+
assert_equal("To: you", mess.header("To"), "To header is wrong")
|
209
|
+
assert_equal("Hi.\n", mess.body, "Body is wrong")
|
210
|
+
assert_equal("Subject: test", mess.header("Subject"), "Subject header wrong")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
data/test/test_header.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
#!/opt/bin/ruby -w
|
2
|
+
|
3
|
+
#------------------------------------------------------------------------
|
4
|
+
#
|
5
|
+
#------------------------------------------------------------------------
|
6
|
+
|
7
|
+
require 'test/unit'
|
8
|
+
require 'test/unit/ui/console/testrunner'
|
9
|
+
require 'stringio'
|
10
|
+
|
11
|
+
class TC_Header < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def setup
|
14
|
+
require './gurgitate-mail'
|
15
|
+
end
|
16
|
+
|
17
|
+
# def teardown
|
18
|
+
# end
|
19
|
+
|
20
|
+
def test_simple_header
|
21
|
+
h=Gurgitate::Header.new("From: fromheader@example.com")
|
22
|
+
assert_equal(h.name,"From", "Simple header name is From")
|
23
|
+
assert_equal(h.contents,"fromheader@example.com",
|
24
|
+
"Contents is fromheader@example.com")
|
25
|
+
assert_equal(h.value,"fromheader@example.com",
|
26
|
+
"Contents is fromheader@example.com")
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_canonicalize_crashing
|
30
|
+
String.class_eval do
|
31
|
+
alias old_capitalize capitalize
|
32
|
+
def capitalize
|
33
|
+
raise RuntimeError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test_simple_header
|
38
|
+
|
39
|
+
String.class_eval do
|
40
|
+
alias capitalize old_capitalize
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# This is an illegal header that turns up in spam sometimes.
|
46
|
+
# Crashing when you get spam is bad.
|
47
|
+
def test_malcapitalized_header
|
48
|
+
h=Gurgitate::Header.new("FROM: fromheader@example.com")
|
49
|
+
assert_equal(h.name,"From", "Badly-capitalized header is From")
|
50
|
+
assert_equal(h.contents,"fromheader@example.com",
|
51
|
+
"Badly-capitalized header")
|
52
|
+
assert_equal(h.value,"fromheader@example.com",
|
53
|
+
"Badly-capitalized header")
|
54
|
+
end
|
55
|
+
|
56
|
+
# I got a message with "X-Qmail-Scanner-1.19" once. I hate whoever did
|
57
|
+
# that.
|
58
|
+
def test_dot_in_header
|
59
|
+
h=Gurgitate::Header.new("From.Header: fromheader@example.com")
|
60
|
+
assert_equal(h.name, "From.header",
|
61
|
+
"header with dot in it is From.header")
|
62
|
+
assert_equal(h.contents, "fromheader@example.com",
|
63
|
+
"header with dot in it")
|
64
|
+
assert_equal(h.value, "fromheader@example.com",
|
65
|
+
"header with dot in it")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Dammit! My new "anything goes" header parser was parsing too much
|
69
|
+
def test_delivered_to
|
70
|
+
h=Gurgitate::Header.new("Delivered-To: dagbrown@example.com")
|
71
|
+
assert_equal("Delivered-To", h.name)
|
72
|
+
assert_equal "dagbrown@example.com", h.contents
|
73
|
+
assert_equal "dagbrown@example.com", h.value
|
74
|
+
end
|
75
|
+
|
76
|
+
# This is another particularly horrible spamware-generated not-a-header.
|
77
|
+
def test_header_that_starts_with_hyphen
|
78
|
+
h=Gurgitate::Header.new("-From: -fromheader@example.com")
|
79
|
+
assert_equal(h.name, "-From",
|
80
|
+
"header with leading hyphen is -From")
|
81
|
+
assert_equal(h.contents, "-fromheader@example.com",
|
82
|
+
"header with leading hyphen")
|
83
|
+
assert_equal(h.value, "-fromheader@example.com",
|
84
|
+
"header with leading hyphen")
|
85
|
+
end
|
86
|
+
|
87
|
+
# This is another illegal header that turns up in spam sometimes.
|
88
|
+
# Crashing when you get spam is bad.
|
89
|
+
def test_nonalphabetic_initial_char_header
|
90
|
+
h=Gurgitate::Header.new("2From: fromheader@example.com")
|
91
|
+
assert_equal(h.name,"2from",
|
92
|
+
"Header that starts with illegal char is 2From")
|
93
|
+
assert_equal(h.contents, "fromheader@example.com",
|
94
|
+
"Header that starts with illegal char")
|
95
|
+
assert_equal(h.value, "fromheader@example.com",
|
96
|
+
"Header that starts with illegal char")
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_bad_headers
|
100
|
+
assert_raises(Gurgitate::IllegalHeader,"Empty name") {
|
101
|
+
h=Gurgitate::Header.new(": Hi")
|
102
|
+
}
|
103
|
+
# assert_raises(Gurgitate::IllegalHeader,"Empty header contents") {
|
104
|
+
# h=Gurgitate::Header.new("From: ")
|
105
|
+
# }
|
106
|
+
assert_raises(Gurgitate::IllegalHeader,"Bad header syntax") {
|
107
|
+
h=Gurgitate::Header.new("This is completely wrong")
|
108
|
+
}
|
109
|
+
end
|
110
|
+
def test_extending_header
|
111
|
+
h=Gurgitate::Header.new("From: fromheader@example.com")
|
112
|
+
h << " (Dave Brown)"
|
113
|
+
assert_equal(h.name,"From","Extended header is From")
|
114
|
+
assert_equal(h.contents,"fromheader@example.com\n (Dave Brown)",
|
115
|
+
"Extended header contains all data")
|
116
|
+
assert_equal(h.contents,h.value,"Contents same as value")
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_empty_header_with_extension
|
120
|
+
h=Gurgitate::Header.new("From:")
|
121
|
+
h << " fromheader@example.com"
|
122
|
+
assert_equal("From",h.name,"Empty extended header is From")
|
123
|
+
assert_equal("\n fromheader@example.com", h.contents,
|
124
|
+
"Empty extended header contains all data")
|
125
|
+
assert_equal(h.contents, h.value, "Contents same as value")
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_changing_header
|
129
|
+
h=Gurgitate::Header.new("From: fromheader@example.com")
|
130
|
+
h.contents="anotherfromheader@example.com"
|
131
|
+
assert_equal(h.contents,"anotherfromheader@example.com",
|
132
|
+
"header contents contains new data")
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_tabseparated_header
|
136
|
+
h=Gurgitate::Header.new("From:\tfromheader@example.com")
|
137
|
+
assert_equal(h.name,"From","Tabseparated header is From (bug#154)")
|
138
|
+
assert_equal(h.contents,"fromheader@example.com",
|
139
|
+
"Tabseparated header's contents are correct (bug#154)")
|
140
|
+
assert_equal(h.contents,h.value,"Contents same as value (bug#154)")
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_conversion_to_String
|
144
|
+
h=Gurgitate::Header.new("From: fromheader@example.com")
|
145
|
+
assert_equal(h.to_s,"From: fromheader@example.com", "Conversion to string returns input")
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_regex_match
|
149
|
+
h=Gurgitate::Header.new("From: fromheader@example.com")
|
150
|
+
assert_equal(0,h.matches(/fromheader/),"Matches regex that would match input")
|
151
|
+
assert_equal(nil,h.matches(/notininput/),"Does not match regex that would not match input")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|