rumbster 1.0.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.
@@ -0,0 +1,64 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'test/unit'
4
+ require 'smtp_protocol'
5
+
6
+ class SmtpProtocolTest < Test::Unit::TestCase
7
+
8
+ def test_protocol_sets_protocol_property_on_each_state
9
+ init_state = TestState.new
10
+
11
+ protocol = SmtpProtocol.new(:init, {:init => init_state})
12
+
13
+ assert_same protocol, init_state.protocol
14
+ end
15
+
16
+ def test_protocol_starts_in_the_initial_state
17
+ init_state = TestState.new
18
+
19
+ protocol = SmtpProtocol.new(:init, {:init => init_state})
20
+ protocol.serve(nil)
21
+
22
+ assert init_state.called
23
+ end
24
+
25
+ def test_state_is_changed_when_a_new_state_is_set
26
+ next_state = TestState.new
27
+
28
+ protocol = SmtpProtocol.new(:init, {:init => TestState.new, :next => next_state})
29
+ protocol.state = :next
30
+ protocol.serve(nil)
31
+
32
+ assert next_state.called
33
+ end
34
+
35
+ def test_listeners_are_notified_when_a_new_message_is_received
36
+ protocol = SmtpProtocol.new(:init, {:init => TestState.new})
37
+ observer = TestObserver.new
38
+ message = 'hi'
39
+
40
+ protocol.add_observer(observer)
41
+
42
+ protocol.new_message_received(message)
43
+
44
+ assert_same message, observer.received_message
45
+ end
46
+
47
+ end
48
+
49
+ class TestObserver
50
+ attr_accessor :received_message
51
+
52
+ def update(message)
53
+ @received_message = message
54
+ end
55
+ end
56
+
57
+ class TestState
58
+ attr_accessor :called, :protocol
59
+
60
+ def serve(io)
61
+ @called = true
62
+ end
63
+
64
+ end
@@ -0,0 +1,217 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'test/unit'
4
+ require 'stringio'
5
+ require 'smtp_protocol'
6
+
7
+ class SmtpStatesTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ buffer = ''
11
+ @server_stream = StringIO.new(buffer)
12
+ @client_stream = StringIO.new(buffer)
13
+ @protocol = TestProtocol.new
14
+ end
15
+
16
+ def test_greeting_is_returned_upon_initial_client_connection
17
+ init_state = InitState.new(@protocol)
18
+ init_state.serve(@server_stream)
19
+
20
+ assert_equal "220 ruby ESMTP\n", @client_stream.readline
21
+ end
22
+
23
+ def test_initial_state_passes_protocol_connect_as_the_next_state_in_the_chain
24
+ init_state = InitState.new(@protocol)
25
+ init_state.serve(@server_stream)
26
+
27
+ assert_equal :connect, @protocol.state
28
+ end
29
+
30
+ def test_initial_state_passes_protocol_the_same_io_as_it_received
31
+ init_state = InitState.new(@protocol)
32
+ init_state.serve(@server_stream)
33
+
34
+ assert_same @server_stream, @protocol.io
35
+ end
36
+
37
+ def test_initial_state_raises_not_initialized_when_protocol_is_not_set
38
+ init_state = InitState.new
39
+
40
+ assert_raise NotInitializedError do
41
+ init_state.serve(@server_stream)
42
+ end
43
+ end
44
+
45
+ def test_helo_is_accepted_while_in_connect_state
46
+ @client_stream.puts "HELO test.client"
47
+ connect_state = ConnectState.new(@protocol)
48
+
49
+ connect_state.serve(@server_stream)
50
+
51
+ assert_equal "250 ruby\n", @client_stream.readline
52
+ end
53
+
54
+ def test_connect_state_passes_protocol_connected_as_the_next_state_in_the_chain
55
+ @client_stream.puts "HELO test.client"
56
+ connect_state = ConnectState.new(@protocol)
57
+
58
+ connect_state.serve(@server_stream)
59
+
60
+ assert_equal :connected, @protocol.state
61
+ end
62
+
63
+ def test_connect_state_passes_protocol_the_same_io_as_it_received
64
+ @client_stream.puts "HELO test.client"
65
+ connect_state = ConnectState.new(@protocol)
66
+
67
+ connect_state.serve(@server_stream)
68
+
69
+ assert_same @server_stream, @protocol.io
70
+ end
71
+
72
+ def test_connect_state_raises_not_initialized_when_protocol_is_not_set
73
+ connect_state = ConnectState.new
74
+
75
+ assert_raise NotInitializedError do
76
+ connect_state.serve(@server_stream)
77
+ end
78
+ end
79
+
80
+ def test_from_okayed_while_in_connected_state
81
+ @client_stream.puts "MAIL FROM:<adam@esterlines.com>"
82
+ connected_state = ConnectedState.new(@protocol)
83
+
84
+ connected_state.serve(@server_stream)
85
+
86
+ assert_equal "250 ok\n", @client_stream.readline
87
+ end
88
+
89
+ def test_connected_state_passes_protocol_connected_as_the_next_state_when_client_sends_from_request
90
+ @client_stream.puts "MAIL FROM:<junk@junkster.com>"
91
+ connected_state = ConnectedState.new(@protocol)
92
+
93
+ connected_state.serve(@server_stream)
94
+
95
+ assert_equal :connected, @protocol.state
96
+ end
97
+
98
+ def test_rcpt_okayed_while_in_connected_state
99
+ @client_stream.puts "RCPT TO:<junk@junkster.com>"
100
+ connected_state = ConnectedState.new(@protocol)
101
+
102
+ connected_state.serve(@server_stream)
103
+
104
+ assert_equal "250 ok\n", @client_stream.readline
105
+ end
106
+
107
+ def test_connected_state_passes_protocol_connected_as_the_next_state_when_client_sends_rcpt_request
108
+ @client_stream.puts "RCPT TO:<foo@foo.com>"
109
+ connected_state = ConnectedState.new(@protocol)
110
+
111
+ connected_state.serve(@server_stream)
112
+
113
+ assert_equal :connected, @protocol.state
114
+ end
115
+
116
+ def test_connected_state_passes_protocol_the_same_io_as_it_received
117
+ @client_stream.puts "MAIL FROM:<foo@foo.com>"
118
+ connected_state = ConnectedState.new(@protocol)
119
+
120
+ connected_state.serve(@server_stream)
121
+
122
+ assert_same @server_stream, @protocol.io
123
+ end
124
+
125
+ def test_data_request_given_the_go_ahead_while_in_connected_state
126
+ @client_stream.puts "DATA"
127
+ connected_state = ConnectedState.new(@protocol)
128
+
129
+ connected_state.serve(@server_stream)
130
+
131
+ assert_equal "354 go ahead\n", @client_stream.readline
132
+ end
133
+
134
+ def test_connected_state_passes_protocol_read_mail_as_the_next_state_when_client_sends_data_request
135
+ @client_stream.puts "DATA"
136
+ connected_state = ConnectedState.new(@protocol)
137
+
138
+ connected_state.serve(@server_stream)
139
+
140
+ assert_equal :read_mail, @protocol.state
141
+ end
142
+
143
+ def test_connected_state_raises_not_initialized_when_protocol_is_not_set
144
+ connected_state = ConnectedState.new
145
+
146
+ assert_raise NotInitializedError do
147
+ connected_state.serve(@server_stream)
148
+ end
149
+ end
150
+
151
+ def test_read_mail_state_reads_until_a_single_dot_is_found_on_a_line_then_returns_an_ok_message
152
+ @client_stream.puts "To: junk@junk.com\nFrom: junk2@junk2.com\n\nHi\n.\n"
153
+ read_mail_state = ReadMailState.new(@protocol)
154
+
155
+ read_mail_state.serve(@server_stream)
156
+
157
+ assert_equal "250 ok\n", @client_stream.readline
158
+ end
159
+
160
+ def test_read_mail_state_passes_read_message_to_protocol
161
+ message = "To: junk@junk.com\nFrom: junk2@junk2.com\n\nHi\n"
162
+ @client_stream.puts "#{message}.\n"
163
+ read_mail_state = ReadMailState.new(@protocol)
164
+
165
+ read_mail_state.serve(@server_stream)
166
+
167
+ assert_equal message, @protocol.new_message
168
+ end
169
+
170
+ def test_read_mail_state_passes_protocol_quit_as_the_next_state_when_mail_message_is_read
171
+ @client_stream.puts "To: junk@junk.com\nFrom: junk2@junk2.com\n\nHi\n.\n"
172
+ read_mail_state = ReadMailState.new(@protocol)
173
+
174
+ read_mail_state.serve(@server_stream)
175
+
176
+ assert_equal :quit, @protocol.state
177
+ end
178
+
179
+ def test_read_mail_state_raises_not_initialized_when_protocol_is_not_set
180
+ read_mail_state = ReadMailState.new
181
+
182
+ assert_raise NotInitializedError do
183
+ read_mail_state.serve(@server_stream)
184
+ end
185
+ end
186
+
187
+ def test_quit_state_reads_client_quit_and_says_goodbye
188
+ @client_stream.puts "QUIT"
189
+ quit_state = QuitState.new(@protocol)
190
+
191
+ quit_state.serve(@server_stream)
192
+
193
+ assert_equal "221 ruby goodbye\n", @client_stream.readline
194
+ end
195
+
196
+ def test_quit_state_raises_not_initialized_when_protocol_is_not_set
197
+ quit_state = QuitState.new
198
+
199
+ assert_raise NotInitializedError do
200
+ quit_state.serve(@server_stream)
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ class TestProtocol
207
+ attr_accessor :state, :io
208
+ attr_reader :new_message
209
+
210
+ def serve (io)
211
+ @io = io
212
+ end
213
+
214
+ def new_message_received(message)
215
+ @new_message = message
216
+ end
217
+ end
data/vendor/tmail.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'tmail/info'
2
+ require 'tmail/mail'
3
+ require 'tmail/mailbox'
4
+ require 'tmail/obsolete'
@@ -0,0 +1,3 @@
1
+ parser.rb
2
+ output.parser
3
+ stringio.rb
@@ -0,0 +1,19 @@
1
+ #
2
+ # lib/tmail/Makefile
3
+ #
4
+
5
+ debug:
6
+ rm -f parser.rb
7
+ make parser.rb DEBUG=true
8
+
9
+ parser.rb: parser.y
10
+ if [ "$(DEBUG)" = true ]; then \
11
+ racc -v -g -o$@ parser.y ;\
12
+ else \
13
+ racc -E -o$@ parser.y ;\
14
+ fi
15
+
16
+ clean:
17
+ rm -f parser.rb parser.output
18
+
19
+ distclean: clean
@@ -0,0 +1,222 @@
1
+ #
2
+ # address.rb
3
+ #
4
+ # Copyright (c) 1998-2004 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2.1.
9
+ #
10
+
11
+ require 'tmail/encode'
12
+ require 'tmail/parser'
13
+
14
+ module TMail
15
+
16
+ class Address
17
+
18
+ include TextUtils
19
+
20
+ def Address.parse(str)
21
+ Parser.parse :ADDRESS, str
22
+ end
23
+
24
+ def address_group?
25
+ false
26
+ end
27
+
28
+ def initialize(local, domain)
29
+ if domain
30
+ domain.each do |s|
31
+ raise SyntaxError, 'empty word in domain' if s.empty?
32
+ end
33
+ end
34
+ @local = local
35
+ @domain = domain
36
+ @name = nil
37
+ @routes = []
38
+ end
39
+
40
+ attr_reader :name
41
+
42
+ def name=(str)
43
+ @name = str
44
+ @name = nil if str and str.empty?
45
+ end
46
+
47
+ alias phrase name
48
+ alias phrase= name=
49
+
50
+ attr_reader :routes
51
+
52
+ def inspect
53
+ "#<#{self.class} #{address()}>"
54
+ end
55
+
56
+ def local
57
+ return nil unless @local
58
+ return '""' if @local.size == 1 and @local[0].empty?
59
+ @local.map {|i| quote_atom(i) }.join('.')
60
+ end
61
+
62
+ def domain
63
+ return nil unless @domain
64
+ join_domain(@domain)
65
+ end
66
+
67
+ def spec
68
+ s = self.local
69
+ d = self.domain
70
+ if s and d
71
+ s + '@' + d
72
+ else
73
+ s
74
+ end
75
+ end
76
+
77
+ alias address spec
78
+
79
+
80
+ def ==(other)
81
+ other.respond_to? :spec and self.spec == other.spec
82
+ end
83
+
84
+ alias eql? ==
85
+
86
+ def hash
87
+ @local.hash ^ @domain.hash
88
+ end
89
+
90
+ def dup
91
+ obj = self.class.new(@local.dup, @domain.dup)
92
+ obj.name = @name.dup if @name
93
+ obj.routes.replace @routes
94
+ obj
95
+ end
96
+
97
+ include StrategyInterface
98
+
99
+ def accept(strategy, dummy1 = nil, dummy2 = nil)
100
+ unless @local
101
+ strategy.meta '<>' # empty return-path
102
+ return
103
+ end
104
+
105
+ spec_p = (not @name and @routes.empty?)
106
+ if @name
107
+ strategy.phrase @name
108
+ strategy.space
109
+ end
110
+ tmp = spec_p ? '' : '<'
111
+ unless @routes.empty?
112
+ tmp << @routes.map {|i| '@' + i }.join(',') << ':'
113
+ end
114
+ tmp << self.spec
115
+ tmp << '>' unless spec_p
116
+ strategy.meta tmp
117
+ strategy.lwsp ''
118
+ end
119
+
120
+ end
121
+
122
+
123
+ class AddressGroup
124
+
125
+ include Enumerable
126
+
127
+ def address_group?
128
+ true
129
+ end
130
+
131
+ def initialize(name, addrs)
132
+ @name = name
133
+ @addresses = addrs
134
+ end
135
+
136
+ attr_reader :name
137
+
138
+ def ==(other)
139
+ other.respond_to? :to_a and @addresses == other.to_a
140
+ end
141
+
142
+ alias eql? ==
143
+
144
+ def hash
145
+ map {|i| i.hash }.hash
146
+ end
147
+
148
+ def [](idx)
149
+ @addresses[idx]
150
+ end
151
+
152
+ def size
153
+ @addresses.size
154
+ end
155
+
156
+ def empty?
157
+ @addresses.empty?
158
+ end
159
+
160
+ def each(&block)
161
+ @addresses.each(&block)
162
+ end
163
+
164
+ def to_a
165
+ @addresses.dup
166
+ end
167
+
168
+ alias to_ary to_a
169
+
170
+ def include?(a)
171
+ @addresses.include? a
172
+ end
173
+
174
+ def flatten
175
+ set = []
176
+ @addresses.each do |a|
177
+ if a.respond_to? :flatten
178
+ set.concat a.flatten
179
+ else
180
+ set.push a
181
+ end
182
+ end
183
+ set
184
+ end
185
+
186
+ def each_address(&block)
187
+ flatten.each(&block)
188
+ end
189
+
190
+ def add(a)
191
+ @addresses.push a
192
+ end
193
+
194
+ alias push add
195
+
196
+ def delete(a)
197
+ @addresses.delete a
198
+ end
199
+
200
+ include StrategyInterface
201
+
202
+ def accept(strategy, dummy1 = nil, dummy2 = nil)
203
+ strategy.phrase @name
204
+ strategy.meta ':'
205
+ strategy.space
206
+ first = true
207
+ each do |mbox|
208
+ if first
209
+ first = false
210
+ else
211
+ strategy.meta ','
212
+ end
213
+ strategy.space
214
+ mbox.accept strategy
215
+ end
216
+ strategy.meta ';'
217
+ strategy.lwsp ''
218
+ end
219
+
220
+ end
221
+
222
+ end # module TMail