gurgitate-mail 1.9.1 → 1.10.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.
- data/lib/gurgitate-mail.rb +10 -0
- data/lib/gurgitate/deliver.rb +2 -1
- data/lib/gurgitate/deliver/mh.rb +137 -0
- data/test/gurgitate-test.rb +5 -1
- data/test/test_deliver.rb +17 -0
- data/test/test_delivery.rb +1 -1
- data/test/test_gurgitate_delivery.rb +90 -2
- data/test/test_header.rb +6 -4
- data/test/test_headers.rb +1 -0
- data/test/test_process.rb +7 -1
- data/test/test_writing.rb +11 -2
- metadata +12 -11
data/lib/gurgitate-mail.rb
CHANGED
@@ -87,10 +87,20 @@ module Gurgitate
|
|
87
87
|
spooldir homedir
|
88
88
|
spoolfile File.join(spooldir,"Maildir")
|
89
89
|
maildir spoolfile
|
90
|
+
elsif style[0] == MH then
|
91
|
+
mh_profile_path = File.join(ENV["HOME"],".mh_profile")
|
92
|
+
if File.exists?(mh_profile_path) then
|
93
|
+
mh_profile = YAML.load(File.read(mh_profile_path))
|
94
|
+
maildir mh_profile["Path"]
|
95
|
+
else
|
96
|
+
maildir File.join(ENV["HOME"],"Mail")
|
97
|
+
end
|
98
|
+
spoolfile File.join(maildir,"inbox")
|
90
99
|
else
|
91
100
|
spooldir "/var/spool/mail"
|
92
101
|
spoolfile File.join(spooldir, @passwd.name)
|
93
102
|
end
|
103
|
+
|
94
104
|
@folderstyle = style[0]
|
95
105
|
else
|
96
106
|
raise ArgumentError, "wrong number of arguments "+
|
data/lib/gurgitate/deliver.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
require "gurgitate/deliver/mbox"
|
9
9
|
require "gurgitate/deliver/maildir"
|
10
|
+
require "gurgitate/deliver/mh"
|
10
11
|
|
11
12
|
module Gurgitate
|
12
13
|
module Deliver
|
@@ -38,7 +39,7 @@ module Gurgitate
|
|
38
39
|
end
|
39
40
|
|
40
41
|
begin
|
41
|
-
[MBox,Maildir].each do |mod|
|
42
|
+
[MBox,Maildir,MH].each do |mod|
|
42
43
|
if mod::check_mailbox(mailbox) then
|
43
44
|
extend mod
|
44
45
|
raise MailboxFound
|
@@ -0,0 +1,137 @@
|
|
1
|
+
#!/opt/bin/ruby -w
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
#------------------------------------------------------------------------
|
6
|
+
# Delivers a message to an mbox (also includes mbox detector)
|
7
|
+
#------------------------------------------------------------------------
|
8
|
+
|
9
|
+
module Gurgitate
|
10
|
+
module Deliver
|
11
|
+
module MH
|
12
|
+
# Checks to see if +mailbox+ is an mbox mailbox
|
13
|
+
# mailbox::
|
14
|
+
# A string containing the path of the mailbox to save
|
15
|
+
# the message to. If it is of the form "=mailbox", it
|
16
|
+
# saves the message to +Maildir+/+mailbox+. Otherwise,
|
17
|
+
# it simply saves the message to the file +mailbox+.
|
18
|
+
def self::check_mailbox(mailbox)
|
19
|
+
begin
|
20
|
+
# Rather annoyingly, pretty well any directory can
|
21
|
+
# be a MH mailbox, but this just checks to make sure
|
22
|
+
# it's not actually a Maildir by mistake.
|
23
|
+
#
|
24
|
+
# I could put in a check for the path given in
|
25
|
+
# $HOME/.mh_profile, but Claws-Mail uses MH mailboxes and
|
26
|
+
# disregards $HOME/.mh_profile.
|
27
|
+
if File.stat(mailbox).directory? and
|
28
|
+
not ( File.exists?(File.join(mailbox, "cur")) or
|
29
|
+
File.exists?(File.join(mailbox, "tmp")) or
|
30
|
+
File.exists?(File.join(mailbox, "new"))) then
|
31
|
+
return MH
|
32
|
+
end
|
33
|
+
rescue Errno::ENOENT
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Delivers the message to +mailbox+
|
39
|
+
# mailbox::
|
40
|
+
# A string containing the path of the mailbox to save
|
41
|
+
# the message to. If it is of the form "=mailbox", it
|
42
|
+
# saves the message to +Maildir+/+mailbox+. Otherwise,
|
43
|
+
# it simply saves the message to the file +mailbox+.
|
44
|
+
def deliver_message(mailbox)
|
45
|
+
if ! File.exists? mailbox then
|
46
|
+
Dir.mkdir(mailbox)
|
47
|
+
end
|
48
|
+
|
49
|
+
if File.exists? mailbox and not File.directory? mailbox then
|
50
|
+
raise SystemError, "not a directory"
|
51
|
+
end
|
52
|
+
|
53
|
+
new_msgnum = next_message(mailbox) do |filehandle|
|
54
|
+
filehandle.print self.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
update_sequences(mailbox, new_msgnum)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def update_sequences(mailbox, msgnum)
|
63
|
+
sequences = File.join(mailbox, ".mh_sequences")
|
64
|
+
lockfile = sequences + ".lock" # how quaint
|
65
|
+
loop do
|
66
|
+
begin
|
67
|
+
File.open(lockfile,
|
68
|
+
File::WRONLY |
|
69
|
+
File::CREAT |
|
70
|
+
File::EXCL ) do |lock|
|
71
|
+
File.open(sequences,
|
72
|
+
File::RDWR | File::CREAT) do |seq|
|
73
|
+
|
74
|
+
seq.flock(File::LOCK_EX)
|
75
|
+
metadata = YAML.load(seq.read) || Hash.new
|
76
|
+
|
77
|
+
metadata["unseen"] = update_unseen \
|
78
|
+
metadata["unseen"], msgnum
|
79
|
+
|
80
|
+
seq.rewind
|
81
|
+
metadata.each do |key, val|
|
82
|
+
seq.puts "#{key}: #{val}"
|
83
|
+
end
|
84
|
+
seq.truncate seq.tell
|
85
|
+
seq.flock(File::LOCK_UN)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
File.unlink(lockfile)
|
90
|
+
break
|
91
|
+
rescue Errno::EEXIST
|
92
|
+
# some other process is doing something, so wait a few
|
93
|
+
# milliseconds until it's done
|
94
|
+
sleep(0.01)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def update_unseen unseen, msgnum
|
100
|
+
prevmsg = msgnum - 1
|
101
|
+
if unseen
|
102
|
+
unseenstring = unseen.to_s
|
103
|
+
|
104
|
+
if unseenstring =~ /-#{prevmsg}/ then
|
105
|
+
return unseenstring.sub(/\b#{prevmsg}\b/, msgnum.to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
if unseenstring.match(/\b#{prevmsg}\b/) then
|
109
|
+
return "#{unseenstring}-#{msgnum}"
|
110
|
+
end
|
111
|
+
|
112
|
+
return "#{unseenstring} #{msgnum}"
|
113
|
+
else
|
114
|
+
return msgnum
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def next_message(mailbox)
|
119
|
+
next_msgnum = Dir.open(mailbox).map { |ent| ent.to_i }.max + 1
|
120
|
+
loop do
|
121
|
+
begin
|
122
|
+
File.open(File.join(mailbox, next_msgnum.to_s),
|
123
|
+
File::WRONLY |
|
124
|
+
File::CREAT |
|
125
|
+
File::EXCL ) do |filehandle|
|
126
|
+
yield filehandle
|
127
|
+
end
|
128
|
+
break
|
129
|
+
rescue Errno::EEXIST
|
130
|
+
next_msgnum += 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
return next_msgnum
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/test/gurgitate-test.rb
CHANGED
@@ -31,13 +31,17 @@ class GurgitateTest < Test::Unit::TestCase
|
|
31
31
|
@spoolfile = File.join(testdir, "default")
|
32
32
|
end
|
33
33
|
|
34
|
-
def maildirmake mailbox # per the command
|
34
|
+
def maildirmake mailbox # per the UNIX command
|
35
35
|
FileUtils.mkdir mailbox
|
36
36
|
%w/cur tmp new/.each do |subdir|
|
37
37
|
FileUtils.mkdir File.join(mailbox, subdir)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def mhdirmake mailbox # per "maildirmake"
|
42
|
+
FileUtils.mkdir mailbox
|
43
|
+
end
|
44
|
+
|
41
45
|
def teardown
|
42
46
|
FileUtils.rmtree @testdir
|
43
47
|
end
|
data/test/test_deliver.rb
CHANGED
@@ -73,4 +73,21 @@ class TC_Deliver < Test::Unit::TestCase
|
|
73
73
|
assert File.exists?(contents[0])
|
74
74
|
assert_equal File.read(contents[0]), @deliver_test.to_s
|
75
75
|
end
|
76
|
+
|
77
|
+
def test_basic_delivery_mh
|
78
|
+
@deliver_test.folderstyle = Gurgitate::Deliver::MH
|
79
|
+
assert_nothing_raised do
|
80
|
+
@deliver_test.save(@spoolfile)
|
81
|
+
end
|
82
|
+
|
83
|
+
assert File.exists?(@spoolfile)
|
84
|
+
assert File.directory?(@spoolfile)
|
85
|
+
|
86
|
+
mess = File.join(@spoolfile,"1")
|
87
|
+
seq = File.join(@spoolfile,".mh_sequences")
|
88
|
+
assert File.exists?(mess)
|
89
|
+
assert File.exists?(seq)
|
90
|
+
assert_equal File.read(mess), @deliver_test.to_s
|
91
|
+
assert_equal File.read(seq), "unseen: 1\n"
|
92
|
+
end
|
76
93
|
end
|
data/test/test_delivery.rb
CHANGED
@@ -4,8 +4,8 @@ require 'stringio'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'pathname'
|
6
6
|
require 'irb'
|
7
|
-
require "./gurgitate-mail"
|
8
7
|
require "test/gurgitate-test"
|
8
|
+
require "gurgitate-mail"
|
9
9
|
|
10
10
|
class TC_Delivery < GurgitateTest
|
11
11
|
#************************************************************************
|
@@ -4,8 +4,8 @@ require 'stringio'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'pathname'
|
6
6
|
require 'irb'
|
7
|
-
require "./gurgitate-mail"
|
8
7
|
require "test/gurgitate-test"
|
8
|
+
require "gurgitate-mail"
|
9
9
|
|
10
10
|
class TC_Gurgitate_delivery < GurgitateTest
|
11
11
|
#************************************************************************
|
@@ -46,6 +46,23 @@ class TC_Gurgitate_delivery < GurgitateTest
|
|
46
46
|
setup
|
47
47
|
end
|
48
48
|
|
49
|
+
def test_detect_mhdir
|
50
|
+
mhdirmake @spoolfile
|
51
|
+
|
52
|
+
assert_nothing_raised do
|
53
|
+
@gurgitate.process { nil }
|
54
|
+
end
|
55
|
+
|
56
|
+
assert File.exists?(@spoolfile)
|
57
|
+
assert File.directory?(@spoolfile)
|
58
|
+
assert File.exists?(File.join(@spoolfile,"1"))
|
59
|
+
assert File.exists?(File.join(@spoolfile,".mh_sequences"))
|
60
|
+
FileUtils.rmtree @spoolfile
|
61
|
+
teardown
|
62
|
+
test_detect_mbox
|
63
|
+
setup
|
64
|
+
end
|
65
|
+
|
49
66
|
def test_save_folders
|
50
67
|
assert_nothing_raised do
|
51
68
|
@gurgitate.process do
|
@@ -83,6 +100,31 @@ class TC_Gurgitate_delivery < GurgitateTest
|
|
83
100
|
assert_equal 1, Dir[File.join(@folders, "test", "new", "*")].length
|
84
101
|
end
|
85
102
|
|
103
|
+
def test_save_guess_mh
|
104
|
+
mhdirmake File.join(@folders,"test")
|
105
|
+
|
106
|
+
assert File.exists?(File.join(@folders, "test"))
|
107
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
108
|
+
|
109
|
+
assert_equal 0, Dir[File.join(@folders, "test", "*")].length
|
110
|
+
|
111
|
+
assert_nothing_raised do
|
112
|
+
@gurgitate.process do
|
113
|
+
save "=test"
|
114
|
+
break
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
assert File.exists?(File.join(@folders, "test"))
|
119
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
120
|
+
assert File.exists?(File.join(@folders, "test", "1"))
|
121
|
+
assert File.stat(File.join(@folders, "test","1")).file?
|
122
|
+
assert File.exists?(File.join(@folders, "test", ".mh_sequences"))
|
123
|
+
assert File.stat(File.join(@folders, "test", ".mh_sequences")).file?
|
124
|
+
assert_equal "unseen: 1\n",
|
125
|
+
File.read(File.join(@folders, "test", ".mh_sequences"))
|
126
|
+
end
|
127
|
+
|
86
128
|
def test_save_maildir_collision
|
87
129
|
maildirmake File.join(@folders,"test")
|
88
130
|
|
@@ -109,6 +151,33 @@ class TC_Gurgitate_delivery < GurgitateTest
|
|
109
151
|
assert_equal 2, Dir[File.join(@folders, "test", "new", "*")].length
|
110
152
|
end
|
111
153
|
|
154
|
+
def test_save_mh_collision
|
155
|
+
mhdirmake File.join(@folders,"test")
|
156
|
+
|
157
|
+
assert File.exists?(File.join(@folders, "test"))
|
158
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
159
|
+
assert_equal 0, Dir[File.join(@folders, "test", "*")].length
|
160
|
+
|
161
|
+
assert_nothing_raised do
|
162
|
+
@gurgitate.process do
|
163
|
+
save "=test"
|
164
|
+
save "=test"
|
165
|
+
break
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
assert File.exists?(File.join(@folders, "test"))
|
170
|
+
assert File.stat(File.join(@folders, "test")).directory?
|
171
|
+
assert File.exists?(File.join(@folders, "test", "1"))
|
172
|
+
assert File.stat(File.join(@folders, "test","1")).file?
|
173
|
+
assert File.exists?(File.join(@folders, "test", "2"))
|
174
|
+
assert File.stat(File.join(@folders, "test","2")).file?
|
175
|
+
assert File.exists?(File.join(@folders, "test", ".mh_sequences"))
|
176
|
+
assert File.stat(File.join(@folders, "test", ".mh_sequences")).file?
|
177
|
+
assert_equal "unseen: 1-2\n",
|
178
|
+
File.read(File.join(@folders, "test", ".mh_sequences"))
|
179
|
+
end
|
180
|
+
|
112
181
|
def test_save_create_maildir
|
113
182
|
maildirmake @spoolfile
|
114
183
|
|
@@ -129,6 +198,26 @@ class TC_Gurgitate_delivery < GurgitateTest
|
|
129
198
|
assert_equal 1, Dir[File.join(@spoolfile, ".test", "new", "*")].length
|
130
199
|
end
|
131
200
|
|
201
|
+
def test_save_create_mh
|
202
|
+
maildirmake @spoolfile
|
203
|
+
|
204
|
+
assert_nothing_raised do
|
205
|
+
@gurgitate.process do
|
206
|
+
@folderstyle = Gurgitate::Deliver::MH
|
207
|
+
@maildir = @spoolfile
|
208
|
+
save "=test"
|
209
|
+
break
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
assert File.exists?(File.join(@spoolfile, "test"))
|
214
|
+
assert File.stat(File.join(@spoolfile, "test")).directory?
|
215
|
+
assert File.exists?(File.join(@spoolfile, "test", ".mh_sequences"))
|
216
|
+
assert File.stat(File.join(@spoolfile, "test",".mh_sequences")).file?
|
217
|
+
assert File.exists?(File.join(@spoolfile, "test", "1"))
|
218
|
+
assert File.stat(File.join(@spoolfile, "test", "1")).file?
|
219
|
+
end
|
220
|
+
|
132
221
|
def test_save_bad_filename
|
133
222
|
assert_nothing_raised do
|
134
223
|
@gurgitate.process do
|
@@ -209,4 +298,3 @@ class TC_Gurgitate_delivery < GurgitateTest
|
|
209
298
|
assert_equal("Subject: test", mess.header("Subject"), "Subject header wrong")
|
210
299
|
end
|
211
300
|
end
|
212
|
-
|
data/test/test_header.rb
CHANGED
@@ -4,6 +4,11 @@
|
|
4
4
|
#
|
5
5
|
#------------------------------------------------------------------------
|
6
6
|
|
7
|
+
builddir = File.join(File.dirname(__FILE__),"..")
|
8
|
+
unless $:[0] == builddir
|
9
|
+
$:.unshift builddir
|
10
|
+
end
|
11
|
+
|
7
12
|
require 'test/unit'
|
8
13
|
require 'test/unit/ui/console/testrunner'
|
9
14
|
require 'stringio'
|
@@ -11,12 +16,9 @@ require 'stringio'
|
|
11
16
|
class TC_Header < Test::Unit::TestCase
|
12
17
|
|
13
18
|
def setup
|
14
|
-
require '
|
19
|
+
require 'gurgitate-mail'
|
15
20
|
end
|
16
21
|
|
17
|
-
# def teardown
|
18
|
-
# end
|
19
|
-
|
20
22
|
def test_simple_header
|
21
23
|
h=Gurgitate::Header.new("From: fromheader@example.com")
|
22
24
|
assert_equal(h.name,"From", "Simple header name is From")
|
data/test/test_headers.rb
CHANGED
data/test/test_process.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
builddir = File.join(File.dirname(__FILE__),"..")
|
2
|
+
unless $:[0] == builddir
|
3
|
+
$:.unshift builddir
|
4
|
+
end
|
5
|
+
|
1
6
|
require 'test/unit'
|
2
7
|
require 'test/unit/ui/console/testrunner'
|
3
8
|
require 'stringio'
|
4
9
|
require 'fileutils'
|
5
10
|
require 'pathname'
|
6
11
|
require 'irb'
|
7
|
-
require "
|
12
|
+
require "gurgitate-mail"
|
13
|
+
require "test/gurgitate-test"
|
8
14
|
|
9
15
|
class TC_Process < GurgitateTest
|
10
16
|
#************************************************************************
|
data/test/test_writing.rb
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
#/opt/bin/ruby -w
|
2
2
|
|
3
|
+
builddir = File.join(File.dirname(__FILE__),"..")
|
4
|
+
unless $:[0] == builddir
|
5
|
+
$:.unshift builddir
|
6
|
+
end
|
7
|
+
|
3
8
|
require 'test/unit'
|
4
9
|
require 'test/unit/ui/console/testrunner'
|
5
10
|
require 'stringio'
|
6
11
|
|
7
12
|
class TC_Writing < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
require 'gurgitate-mail'
|
15
|
+
end
|
16
|
+
|
8
17
|
def test_null_message
|
9
18
|
assert_nothing_raised do
|
10
19
|
Gurgitate::Mailmessage.new
|
@@ -102,7 +111,7 @@ class TC_Writing < Test::Unit::TestCase
|
|
102
111
|
assert_equal "sender@test", mess.from
|
103
112
|
assert_equal "recipient@test", mess.to
|
104
113
|
assert_equal "This is a test", mess.body
|
105
|
-
assert_equal "From: from@test", mess.headers["From"].to_s
|
106
|
-
assert_equal "To: to@test", mess.headers["To"].to_s
|
114
|
+
assert_equal "From: from@test", (mess.headers["From"]).to_s
|
115
|
+
assert_equal "To: to@test", (mess.headers["To"]).to_s
|
107
116
|
end
|
108
117
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: gurgitate-mail
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date:
|
6
|
+
version: 1.10.0
|
7
|
+
date: 2008-01-30 00:00:00 +09:00
|
8
8
|
summary: gurgitate-mail is a mail filter (and a mail-delivery agent)
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,23 +30,24 @@ authors:
|
|
30
30
|
- Dave Brown
|
31
31
|
files:
|
32
32
|
- lib/gurgitate-mail.rb
|
33
|
+
- lib/gurgitate/deliver.rb
|
33
34
|
- lib/gurgitate/headers.rb
|
35
|
+
- lib/gurgitate/header.rb
|
34
36
|
- lib/gurgitate/mailmessage.rb
|
35
37
|
- lib/gurgitate/deliver/maildir.rb
|
36
38
|
- lib/gurgitate/deliver/mbox.rb
|
37
|
-
- lib/gurgitate/deliver.rb
|
38
|
-
-
|
39
|
+
- lib/gurgitate/deliver/mh.rb
|
40
|
+
- test/gurgitate-test.rb
|
41
|
+
- test/runtests.rb
|
39
42
|
- test/test_configuration.rb
|
40
|
-
- test/
|
41
|
-
- test/test_gurgitate_delivery.rb
|
43
|
+
- test/test_deliver.rb
|
42
44
|
- test/test_delivery.rb
|
45
|
+
- test/test_header.rb
|
43
46
|
- test/test_process.rb
|
44
|
-
- test/runtests.rb
|
45
|
-
- test/gurgitate-test.rb
|
46
|
-
- test/test_deliver.rb
|
47
47
|
- test/test_rules.rb
|
48
48
|
- test/test_writing.rb
|
49
|
-
- test/
|
49
|
+
- test/test_gurgitate_delivery.rb
|
50
|
+
- test/test_headers.rb
|
50
51
|
test_files:
|
51
52
|
- test/runtests.rb
|
52
53
|
rdoc_options: []
|