rumbster 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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