gurgitate-mail 1.10.0 → 1.10.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.
@@ -1,30 +1,56 @@
1
- #!/opt/bin/ruby -w
2
-
3
- #------------------------------------------------------------------------
4
- # Handles a complete mail message
5
- #------------------------------------------------------------------------
1
+ # Contains the class Gurgitate::Mailmessage, used to handle the parsing
2
+ # of existing messages and the creation of new messages.
6
3
 
7
4
  require 'gurgitate/headers'
5
+ require 'gurgitate/message'
8
6
 
9
7
  module Gurgitate
10
8
 
11
- # A complete mail message.
12
- class Mailmessage
9
+ # A complete mail message. This is the base class for
10
+ # gurgitate-mail itself: if you want to use gurgitate-mail to create
11
+ # new messages, this is what you want to use.
12
+ class Mailmessage < Message
13
13
 
14
14
  Fromregex=/([^ ]+@[^ ]+) \(.*\)|[^<][<](.*@.*)[>]|([^ ]+@[^ ]+)/;
15
15
 
16
- # The headers of the message
17
- attr_reader :headers
18
- # The body of the message
19
- attr_accessor :body
20
-
21
16
  # The envelope sender and recipient, if anyone thought to
22
17
  # mention them to us.
23
18
  attr_accessor :sender
24
19
  attr_accessor :recipient
25
20
 
26
- # Creates a new mail message with headers built from the options hash,
27
- # and the body of the message in a string.
21
+ # Creates a new mail message from the options hash, and the body of the
22
+ # message in a string.
23
+ #
24
+ # This can actually be invoked in several ways:
25
+ #
26
+ # Gurgitate::Mailmessage.create "This is the message body",
27
+ # :from => "from_address@example.com",
28
+ # :to => "to_address@example.com",
29
+ # :subject => "This is the message subject"
30
+ #
31
+ # This results in an email message that, when rendered via to_s, will
32
+ # look like this:
33
+ #
34
+ # From: from_address@example.com
35
+ # To: to_address@example.com
36
+ # Subject: This is the message subject
37
+ #
38
+ # This is the message body
39
+ #
40
+ # If you prefer to do things entirely by options hashes, as some do,
41
+ # you can substitute a :body key for the first argument:
42
+ #
43
+ # Gurgitate::Mailmessage.create(
44
+ # :body => "This is the message body",
45
+ # :from => "from_address@example.com",
46
+ # :to => "to_address@example.com",
47
+ # :subject => "This is the message subject"
48
+ # )
49
+ #
50
+ # There are two other special options you can use: :sender and
51
+ # :recipient. These are used to specify the sender and recipient of
52
+ # email messages, when the message is sent via SMTP.
53
+ #
28
54
  def self.create(*args)
29
55
  options = body = nil
30
56
 
@@ -51,7 +77,7 @@ module Gurgitate
51
77
  end
52
78
  end
53
79
 
54
- @headers = Headers.new(options)
80
+ @headers = MailHeaders.new(options)
55
81
  end
56
82
 
57
83
  message
@@ -64,30 +90,33 @@ module Gurgitate
64
90
 
65
91
  if text
66
92
  (@headertext,@body)=text.split(/\n\n/,2)
67
- @headers=Headers.new(@headertext);
93
+ @headers=MailHeaders.new(@headertext);
68
94
  Fromregex.match(@headers["From"][0].contents);
69
95
  @from=$+
70
96
  else
71
- @headers = Headers.new
72
- @body = ""
97
+ super(text)
73
98
  end
74
99
  end
75
100
 
76
- # Returns the header +name+
77
- def header(name)
78
- @headers[name].each { |h| h.contents }.join(", ")
79
- end
80
-
81
101
  # custom accessors
82
102
 
83
103
  # Returns the message's sender
84
104
  def from; @sender || @headers.from; end
85
105
 
86
106
  # Returns all the candidates for a recipient
87
- def to; @recipient || @headers["To", "Cc"][0].contents; end
88
-
89
- # Returns the formatted mail message
90
- def to_s; @headers.to_s + "\n\n" + ( @body || ""); end
107
+ def to
108
+ if @recipient
109
+ then @recipient
110
+ elsif @headers["To"]
111
+ then @headers["To"][0].contents
112
+ elsif @headers["Cc"]
113
+ then @headers["Cc"][0].contents
114
+ elsif @headers["X-Original-To"]
115
+ then @headers["X-Original-To"][0].contents
116
+ else
117
+ ""
118
+ end
119
+ end
91
120
 
92
121
  # Returns the mail message formatted for mbox
93
122
  def to_mbox; @headers.to_mbox + "\n\n" + @body; end
@@ -0,0 +1,113 @@
1
+ #!/opt/bin/ruby -w
2
+
3
+ #------------------------------------------------------------------------
4
+ # Handles a complete mail message
5
+ #------------------------------------------------------------------------
6
+
7
+ require 'gurgitate/mail_headers'
8
+
9
+ module Gurgitate
10
+
11
+ # A complete mail message.
12
+ class Message
13
+
14
+ # The headers of the message
15
+ attr_reader :headers
16
+ # The body of the message
17
+ attr_accessor :body
18
+
19
+ # Creates a new message from the options hash, and the body of the
20
+ # message in a string.
21
+ #
22
+ # This can actually be invoked in several ways:
23
+ #
24
+ # Gurgitate::Mailmessage.create "This is the message body",
25
+ # :from => "from_address@example.com",
26
+ # :to => "to_address@example.com",
27
+ # :subject => "This is the message subject"
28
+ #
29
+ # This results in an email message that, when rendered via to_s, will
30
+ # look like this:
31
+ #
32
+ # From: from_address@example.com
33
+ # To: to_address@example.com
34
+ # Subject: This is the message subject
35
+ #
36
+ # This is the message body
37
+ #
38
+ # If you prefer to do things entirely by options hashes, as some do,
39
+ # you can substitute a :body key for the first argument:
40
+ #
41
+ # Gurgitate::Mailmessage.create(
42
+ # :body => "This is the message body",
43
+ # :from => "from_address@example.com",
44
+ # :to => "to_address@example.com",
45
+ # :subject => "This is the message subject"
46
+ # )
47
+ #
48
+ # There are two other special options you can use: :sender and
49
+ # :recipient. These are used to specify the sender and recipient of
50
+ # email messages, when the message is sent via SMTP.
51
+ #
52
+ def self.create(*args)
53
+ options = body = nil
54
+
55
+ if String === args[0]
56
+ options = args[1]
57
+ body = args[0]
58
+ elsif Hash === args[0]
59
+ options = args[0]
60
+ else
61
+ options = {}
62
+ end
63
+
64
+ message = self.new
65
+
66
+ message.instance_eval do
67
+ if body
68
+ @body=body
69
+ end
70
+
71
+ @headers = Headers.new(options)
72
+ end
73
+
74
+ message
75
+ end
76
+
77
+ # Creates a new Gurgitate message from a pre-existing message.
78
+ # This is what is used when gurgitate-mail is used as a mail filter.
79
+ #
80
+ # ARGUMENTS::
81
+ # +text+ :: An RFC822-formatted message.
82
+ # +recipient+ :: The recipient of the email message, from the MTA
83
+ # +sender+ :: The sender of the email message, also from the MTA
84
+ #
85
+ # All of its arguments can be nil: if called with no arguments,
86
+ # it simply returns an empty email message, which can be populated
87
+ # after the fact.
88
+ def initialize(text=nil)
89
+ if text
90
+ (@headertext,@body)=text.split(/\n\n/,2)
91
+ @headers=Headers.new(@headertext);
92
+ else
93
+ @headers = Headers.new
94
+ @body = ""
95
+ end
96
+ end
97
+
98
+ # Returns the header +name+, which is, note, a HeaderBag of all
99
+ # headers by that name, not just a single header.
100
+ #
101
+ # If you want the text of the header, then you have to coerce it to a
102
+ # string:
103
+ #
104
+ # header("name").to_s
105
+ #
106
+ def header(name)
107
+ @headers[name].each { |h| h.contents }.join(", ")
108
+ end
109
+
110
+ # Returns the formatted mail message
111
+ def to_s; @headers.to_s + "\n\n" + ( @body || ""); end
112
+ end
113
+ end
@@ -1,11 +1,17 @@
1
+ builddir = File.dirname(File.dirname(__FILE__))
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
1
7
  require 'test/unit'
2
8
  require 'test/unit/ui/console/testrunner'
3
9
  require 'stringio'
4
10
  require 'fileutils'
5
11
  require 'pathname'
6
12
  require 'irb'
7
- $:.unshift File.dirname(__FILE__) + "/.."
8
13
  require "gurgitate-mail"
14
+ require "etc"
9
15
 
10
16
  class GurgitateTest < Test::Unit::TestCase
11
17
  def setup
data/test/runtests.rb CHANGED
@@ -1,14 +1,23 @@
1
- #!/opt/bin/ruby -w
2
-
3
- #------------------------------------------------------------------------
4
- # Unit tests for gurgitate-mail
5
- #------------------------------------------------------------------------
6
-
7
1
  require 'test/unit'
8
- require 'test/unit/ui/console/testrunner'
2
+ tester = nil
3
+ begin
4
+ require 'test/unit/ui/console/testrunner'
5
+ tester = Test::Unit::UI::Console::TestRunner
6
+ rescue LoadError # ruby 1.9
7
+ require 'test/unit'
8
+ tester = Test::Unit
9
+ end
9
10
  require 'stringio'
10
11
  require 'pathname'
11
12
 
13
+ builddir = File.dirname(File.dirname(__FILE__))
14
+
15
+ unless $:[0] == builddir
16
+ $:.unshift builddir
17
+ end
18
+
19
+ require "test/gurgitate-test"
20
+
12
21
  def runtests(testcases)
13
22
  testcases.each do |testcase|
14
23
  Test::Unit::UI::Console::TestRunner.run testcase
@@ -1,3 +1,9 @@
1
+ builddir = File.dirname(File.dirname(__FILE__))
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
1
7
  require "test/gurgitate-test"
2
8
  require "etc"
3
9
 
data/test/test_deliver.rb CHANGED
@@ -1,3 +1,9 @@
1
+ builddir = File.dirname(File.dirname(__FILE__))
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
1
7
  require 'test/unit'
2
8
  require 'test/unit/ui/console/testrunner'
3
9
  require 'stringio'
@@ -1,3 +1,9 @@
1
+ builddir = File.dirname(File.dirname(__FILE__))
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
1
7
  require 'test/unit'
2
8
  require 'test/unit/ui/console/testrunner'
3
9
  require 'stringio'
@@ -0,0 +1,43 @@
1
+ builddir = File.join(File.dirname(__FILE__),"..")
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
7
+ require "test/gurgitate-test"
8
+ require "test/test_rules"
9
+ require "etc"
10
+
11
+ class TC_Execute_rules < TC_Rules
12
+ def setup
13
+ super
14
+ @invalidrules = File.join(@testdir, "rules_invalid.rb")
15
+ File.open @invalidrules, "w" do |f|
16
+ f.puts "invalid syntax"
17
+ end
18
+ @exceptionrules = File.join(@testdir, "rules_exception.rb")
19
+ File.open @exceptionrules, "w" do |f|
20
+ f.puts "raise RuntimeError, 'testing'"
21
+ end
22
+ end
23
+
24
+ def teardown
25
+ File.unlink @invalidrules if File.exists? @invalidrules
26
+ end
27
+
28
+ def test_process_default
29
+ @gurgitate.add_rules :default
30
+ assert_nothing_raised do
31
+ @gurgitate.process
32
+ end
33
+ end
34
+
35
+ def test_process_rules_not_found
36
+ @gurgitate.add_rules @rulesfile
37
+ File.unlink @rulesfile
38
+ assert_nothing_raised do
39
+ @gurgitate.process
40
+ end
41
+ assert File.exists?(@spoolfile)
42
+ end
43
+ end
@@ -1,3 +1,9 @@
1
+ builddir = File.dirname(File.dirname(__FILE__))
2
+
3
+ unless $:[0] == builddir
4
+ $:.unshift builddir
5
+ end
6
+
1
7
  require 'test/unit'
2
8
  require 'test/unit/ui/console/testrunner'
3
9
  require 'stringio'
@@ -8,6 +14,40 @@ require "test/gurgitate-test"
8
14
  require "gurgitate-mail"
9
15
 
10
16
  class TC_Gurgitate_delivery < GurgitateTest
17
+ def ensure_empty_maildir(dir)
18
+ assert File.exists?(dir)
19
+ assert File.stat(dir).directory?
20
+ assert File.exists?(File.join(dir, "new"))
21
+
22
+ assert_equal 0, Dir[File.join(dir, "new", "*")].length
23
+ assert_equal 0, Dir[File.join(dir, "cur", "*")].length
24
+ end
25
+
26
+ def ensure_maildir_with_n_messages(dir, n)
27
+ assert File.exists?(dir)
28
+ assert File.stat(dir).directory?
29
+ assert File.exists?(File.join(dir, "new"))
30
+ assert File.stat(File.join(dir, "new")).directory?
31
+ assert_equal 0, Dir[File.join(dir, "cur", "*")].length
32
+ assert_equal n, Dir[File.join(dir, "new", "*")].length
33
+ end
34
+
35
+ def ensure_empty_mhdir(dir)
36
+ assert File.exists?(dir)
37
+ assert File.stat(dir).directory?
38
+
39
+ assert_equal 0, Dir[File.join(dir, "*")].length
40
+ end
41
+
42
+ def ensure_mhdir_with_messages(dir, *messages)
43
+ assert File.exists?(dir)
44
+ assert File.stat(dir).directory?
45
+ messages.each do |message|
46
+ assert File.exists?(File.join(dir, message.to_s))
47
+ assert File.stat(File.join(dir,message.to_s)).file?
48
+ end
49
+ end
50
+
11
51
  #************************************************************************
12
52
  # tests
13
53
  #************************************************************************
@@ -78,12 +118,7 @@ class TC_Gurgitate_delivery < GurgitateTest
78
118
  def test_save_guess_maildir
79
119
  maildirmake File.join(@folders,"test")
80
120
 
81
- assert File.exists?(File.join(@folders, "test"))
82
- assert File.stat(File.join(@folders, "test")).directory?
83
- assert File.exists?(File.join(@folders, "test", "new"))
84
-
85
- assert_equal 0, Dir[File.join(@folders, "test", "new", "*")].length
86
- assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
121
+ ensure_empty_maildir File.join(@folders, "test")
87
122
 
88
123
  assert_nothing_raised do
89
124
  @gurgitate.process do
@@ -92,21 +127,13 @@ class TC_Gurgitate_delivery < GurgitateTest
92
127
  end
93
128
  end
94
129
 
95
- assert File.exists?(File.join(@folders, "test"))
96
- assert File.stat(File.join(@folders, "test")).directory?
97
- assert File.exists?(File.join(@folders, "test", "new"))
98
- assert File.stat(File.join(@folders, "test","new")).directory?
99
- assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
100
- assert_equal 1, Dir[File.join(@folders, "test", "new", "*")].length
130
+ ensure_maildir_with_n_messages(File.join(@folders, "test"), 1)
101
131
  end
102
132
 
103
133
  def test_save_guess_mh
104
134
  mhdirmake File.join(@folders,"test")
105
135
 
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
136
+ ensure_empty_mhdir File.join(@folders, "test")
110
137
 
111
138
  assert_nothing_raised do
112
139
  @gurgitate.process do
@@ -115,10 +142,7 @@ class TC_Gurgitate_delivery < GurgitateTest
115
142
  end
116
143
  end
117
144
 
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?
145
+ ensure_mhdir_with_messages(File.join(@folders,"test"),1)
122
146
  assert File.exists?(File.join(@folders, "test", ".mh_sequences"))
123
147
  assert File.stat(File.join(@folders, "test", ".mh_sequences")).file?
124
148
  assert_equal "unseen: 1\n",
@@ -128,12 +152,7 @@ class TC_Gurgitate_delivery < GurgitateTest
128
152
  def test_save_maildir_collision
129
153
  maildirmake File.join(@folders,"test")
130
154
 
131
- assert File.exists?(File.join(@folders, "test"))
132
- assert File.stat(File.join(@folders, "test")).directory?
133
- assert File.exists?(File.join(@folders, "test", "new"))
134
-
135
- assert_equal 0, Dir[File.join(@folders, "test", "new", "*")].length
136
- assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
155
+ ensure_empty_maildir(File.join(@folders, "test"))
137
156
 
138
157
  assert_nothing_raised do
139
158
  @gurgitate.process do
@@ -143,20 +162,13 @@ class TC_Gurgitate_delivery < GurgitateTest
143
162
  end
144
163
  end
145
164
 
146
- assert File.exists?(File.join(@folders, "test"))
147
- assert File.stat(File.join(@folders, "test")).directory?
148
- assert File.exists?(File.join(@folders, "test", "new"))
149
- assert File.stat(File.join(@folders, "test","new")).directory?
150
- assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
151
- assert_equal 2, Dir[File.join(@folders, "test", "new", "*")].length
165
+ ensure_maildir_with_n_messages(File.join(@folders,"test"),2)
152
166
  end
153
167
 
154
168
  def test_save_mh_collision
155
169
  mhdirmake File.join(@folders,"test")
156
170
 
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
171
+ ensure_empty_mhdir File.join(@folders,"test")
160
172
 
161
173
  assert_nothing_raised do
162
174
  @gurgitate.process do
@@ -166,12 +178,8 @@ class TC_Gurgitate_delivery < GurgitateTest
166
178
  end
167
179
  end
168
180
 
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?
181
+ ensure_mhdir_with_messages(File.join(@folders, "test"), 1, 2)
182
+
175
183
  assert File.exists?(File.join(@folders, "test", ".mh_sequences"))
176
184
  assert File.stat(File.join(@folders, "test", ".mh_sequences")).file?
177
185
  assert_equal "unseen: 1-2\n",
@@ -190,12 +198,7 @@ class TC_Gurgitate_delivery < GurgitateTest
190
198
  end
191
199
  end
192
200
 
193
- assert File.exists?(File.join(@spoolfile, ".test"))
194
- assert File.stat(File.join(@spoolfile, ".test")).directory?
195
- assert File.exists?(File.join(@spoolfile, ".test", "new"))
196
- assert File.stat(File.join(@spoolfile, ".test","new")).directory?
197
- assert_equal 0, Dir[File.join(@spoolfile, ".test", "cur", "*")].length
198
- assert_equal 1, Dir[File.join(@spoolfile, ".test", "new", "*")].length
201
+ ensure_maildir_with_n_messages(File.join(@spoolfile,".test"),1)
199
202
  end
200
203
 
201
204
  def test_save_create_mh
@@ -210,12 +213,9 @@ class TC_Gurgitate_delivery < GurgitateTest
210
213
  end
211
214
  end
212
215
 
213
- assert File.exists?(File.join(@spoolfile, "test"))
214
- assert File.stat(File.join(@spoolfile, "test")).directory?
216
+ ensure_mhdir_with_messages(File.join(@spoolfile,"test"),1)
215
217
  assert File.exists?(File.join(@spoolfile, "test", ".mh_sequences"))
216
218
  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
219
  end
220
220
 
221
221
  def test_save_bad_filename
@@ -266,12 +266,7 @@ class TC_Gurgitate_delivery < GurgitateTest
266
266
  end
267
267
  end
268
268
 
269
- assert File.exists?(File.join(@folders, "test"))
270
- assert File.stat(File.join(@folders, "test")).directory?
271
- assert File.exists?(File.join(@folders, "test", "new"))
272
- assert File.stat(File.join(@folders, "test","new")).directory?
273
- assert_equal 0, Dir[File.join(@folders, "test", "cur", "*")].length
274
- assert_equal 1, Dir[File.join(@folders, "test", "new", "*")].length
269
+ ensure_maildir_with_n_messages(File.join(@folders, "test"), 1)
275
270
  end
276
271
 
277
272
  def test_message_parsed_correctly