remailer 0.3.6 → 0.3.8
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/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/remailer/connection.rb +15 -7
- data/lib/remailer/connection/smtp_interpreter.rb +22 -3
- data/lib/remailer/interpreter.rb +15 -7
- data/remailer.gemspec +29 -31
- data/test/unit/remailer_interpreter_test.rb +68 -1
- metadata +6 -7
- data/.gitignore +0 -25
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "remailer"
|
8
8
|
gem.summary = %Q{Reactor-Ready SMTP Mailer}
|
9
|
-
gem.description = %Q{EventMachine
|
9
|
+
gem.description = %Q{EventMachine SMTP Mail User Agent}
|
10
10
|
gem.email = "scott@twg.ca"
|
11
11
|
gem.homepage = "http://github.com/twg/remailer"
|
12
12
|
gem.authors = [ "Scott Tadman" ]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.8
|
data/lib/remailer/connection.rb
CHANGED
@@ -295,13 +295,18 @@ class Remailer::Connection < EventMachine::Connection
|
|
295
295
|
|
296
296
|
@timeout_at = nil
|
297
297
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
298
|
+
if (@connected and @active_message)
|
299
|
+
message_callback(:timeout, "Response timed out before send could complete")
|
300
|
+
error_notification(:timeout, "Response timed out")
|
301
|
+
debug_notification(:timeout, "Response timed out")
|
302
|
+
send_callback(:on_error)
|
303
|
+
elsif (!@connected)
|
304
|
+
connect_notification(false, "Timed out before a connection could be established")
|
305
|
+
debug_notification(:timeout, "Timed out before a connection could be established")
|
306
|
+
error_notification(:timeout, "Timed out before a connection could be established")
|
304
307
|
send_callback(:on_error)
|
308
|
+
else
|
309
|
+
send_callback(:on_disconnect)
|
305
310
|
end
|
306
311
|
|
307
312
|
close_connection
|
@@ -341,6 +346,7 @@ class Remailer::Connection < EventMachine::Connection
|
|
341
346
|
debug_notification(:closed, "Connection closed")
|
342
347
|
super
|
343
348
|
@closed = true
|
349
|
+
@timeout_at = nil
|
344
350
|
end
|
345
351
|
alias_method :close, :close_connection
|
346
352
|
|
@@ -401,8 +407,10 @@ class Remailer::Connection < EventMachine::Connection
|
|
401
407
|
end
|
402
408
|
|
403
409
|
def connect_notification(code, message = nil)
|
410
|
+
@connected = code
|
411
|
+
|
404
412
|
send_notification(:connect, code, message || self.remote)
|
405
|
-
send_callback(:on_connect)
|
413
|
+
send_callback(:on_connect) if (code)
|
406
414
|
end
|
407
415
|
|
408
416
|
def error_notification(code, message)
|
@@ -49,6 +49,15 @@ class Remailer::Connection::SmtpInterpreter < Remailer::Interpreter
|
|
49
49
|
enter_state(:helo)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
interpret(421) do |message|
|
54
|
+
delegate.connect_notification(false, "Connection timed out")
|
55
|
+
delegate.debug_notification(:error, "[#{@state}] 421 #{message}")
|
56
|
+
delegate.error_notification(421, message)
|
57
|
+
delegate.send_callback(:on_error)
|
58
|
+
|
59
|
+
enter_state(:terminated)
|
60
|
+
end
|
52
61
|
end
|
53
62
|
|
54
63
|
state :helo do
|
@@ -161,7 +170,12 @@ class Remailer::Connection::SmtpInterpreter < Remailer::Interpreter
|
|
161
170
|
|
162
171
|
state :mail_from do
|
163
172
|
enter do
|
164
|
-
|
173
|
+
if (delegate.active_message)
|
174
|
+
delegate.send_line("MAIL FROM:<#{delegate.active_message[:from]}>")
|
175
|
+
else
|
176
|
+
delegate.message_callback(false, "Delegate has no active message")
|
177
|
+
enter_state(:reset)
|
178
|
+
end
|
165
179
|
end
|
166
180
|
|
167
181
|
interpret(250) do
|
@@ -171,7 +185,12 @@ class Remailer::Connection::SmtpInterpreter < Remailer::Interpreter
|
|
171
185
|
|
172
186
|
state :rcpt_to do
|
173
187
|
enter do
|
174
|
-
|
188
|
+
if (delegate.active_message)
|
189
|
+
delegate.send_line("RCPT TO:<#{delegate.active_message[:to]}>")
|
190
|
+
else
|
191
|
+
delegate.message_callback(false, "Delegate has no active message")
|
192
|
+
enter_state(:reset)
|
193
|
+
end
|
175
194
|
end
|
176
195
|
|
177
196
|
interpret(250) do
|
@@ -234,7 +253,7 @@ class Remailer::Connection::SmtpInterpreter < Remailer::Interpreter
|
|
234
253
|
|
235
254
|
state :reset do
|
236
255
|
enter do
|
237
|
-
delegate.send_line("
|
256
|
+
delegate.send_line("RSET")
|
238
257
|
end
|
239
258
|
|
240
259
|
interpret(250) do
|
data/lib/remailer/interpreter.rb
CHANGED
@@ -59,6 +59,11 @@ class Remailer::Interpreter
|
|
59
59
|
StateProxy.new(config, &block)
|
60
60
|
end
|
61
61
|
|
62
|
+
# This is a method to convert a spec and a block into a proper parser
|
63
|
+
# method. If spec is specified, it should be a Fixnum, or a Regexp. A
|
64
|
+
# Fixnum defines a minimum size to process, useful for packed binary
|
65
|
+
# streams, and a Regexp defines a pattern that must match before the parser
|
66
|
+
# is engaged.
|
62
67
|
def self.parser_for_spec(spec, &block)
|
63
68
|
case (spec)
|
64
69
|
when nil
|
@@ -100,7 +105,7 @@ class Remailer::Interpreter
|
|
100
105
|
@on_error = block
|
101
106
|
end
|
102
107
|
|
103
|
-
# Returns the
|
108
|
+
# Returns the parser used when no state-specific parser has been defined.
|
104
109
|
def self.default_parser
|
105
110
|
@parser ||= lambda { |s| _s = s.dup; s.replace(''); _s }
|
106
111
|
end
|
@@ -152,9 +157,10 @@ class Remailer::Interpreter
|
|
152
157
|
end
|
153
158
|
|
154
159
|
# Parses a given string and returns the first interpretable token, if any,
|
155
|
-
# or nil otherwise.
|
156
|
-
|
157
|
-
|
160
|
+
# or nil otherwise. If an interpretable token is found, the supplied string
|
161
|
+
# will be modified to have that matching portion removed.
|
162
|
+
def parse(buffer)
|
163
|
+
instance_exec(buffer, &parser)
|
158
164
|
end
|
159
165
|
|
160
166
|
# Returns the parser defined for the current state, or the default parser.
|
@@ -184,7 +190,8 @@ class Remailer::Interpreter
|
|
184
190
|
# Interprets a given object with an optional set of arguments. The actual
|
185
191
|
# interpretation should be defined by declaring a state with an interpret
|
186
192
|
# block defined.
|
187
|
-
def interpret(
|
193
|
+
def interpret(*args)
|
194
|
+
object = args.first
|
188
195
|
config = self.class.states[@state]
|
189
196
|
callbacks = (config and config[:interpret])
|
190
197
|
|
@@ -194,16 +201,17 @@ class Remailer::Interpreter
|
|
194
201
|
end
|
195
202
|
|
196
203
|
if (matched)
|
204
|
+
args.shift
|
197
205
|
instance_exec(*args, &proc)
|
198
206
|
|
199
207
|
return true
|
200
208
|
end
|
201
209
|
end
|
202
210
|
|
203
|
-
if (trigger_callbacks(@state, :default, *
|
211
|
+
if (trigger_callbacks(@state, :default, *args))
|
204
212
|
# Handled by default
|
205
213
|
true
|
206
|
-
elsif (proc = self.class.
|
214
|
+
elsif (proc = self.class.default_interpreter)
|
207
215
|
instance_exec(*args, &proc)
|
208
216
|
else
|
209
217
|
if (proc = self.class.on_error_handler)
|
data/remailer.gemspec
CHANGED
@@ -1,56 +1,54 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{remailer}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Scott Tadman"]
|
12
|
-
s.date = %q{
|
13
|
-
s.description = %q{EventMachine
|
12
|
+
s.date = %q{2011-01-12}
|
13
|
+
s.description = %q{EventMachine SMTP Mail User Agent}
|
14
14
|
s.email = %q{scott@twg.ca}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README.rdoc"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
19
|
".document",
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
"test/unit/remailer_test.rb"
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"lib/remailer.rb",
|
24
|
+
"lib/remailer/connection.rb",
|
25
|
+
"lib/remailer/connection/smtp_interpreter.rb",
|
26
|
+
"lib/remailer/connection/socks5_interpreter.rb",
|
27
|
+
"lib/remailer/interpreter.rb",
|
28
|
+
"lib/remailer/interpreter/state_proxy.rb",
|
29
|
+
"remailer.gemspec",
|
30
|
+
"test/config.example.rb",
|
31
|
+
"test/helper.rb",
|
32
|
+
"test/unit/remailer_connection_smtp_interpreter_test.rb",
|
33
|
+
"test/unit/remailer_connection_socks5_interpreter_test.rb",
|
34
|
+
"test/unit/remailer_connection_test.rb",
|
35
|
+
"test/unit/remailer_interpreter_state_proxy_test.rb",
|
36
|
+
"test/unit/remailer_interpreter_test.rb",
|
37
|
+
"test/unit/remailer_test.rb"
|
39
38
|
]
|
40
39
|
s.homepage = %q{http://github.com/twg/remailer}
|
41
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
42
40
|
s.require_paths = ["lib"]
|
43
41
|
s.rubygems_version = %q{1.3.7}
|
44
42
|
s.summary = %q{Reactor-Ready SMTP Mailer}
|
45
43
|
s.test_files = [
|
46
44
|
"test/config.example.rb",
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
"test/helper.rb",
|
46
|
+
"test/unit/remailer_connection_smtp_interpreter_test.rb",
|
47
|
+
"test/unit/remailer_connection_socks5_interpreter_test.rb",
|
48
|
+
"test/unit/remailer_connection_test.rb",
|
49
|
+
"test/unit/remailer_interpreter_state_proxy_test.rb",
|
50
|
+
"test/unit/remailer_interpreter_test.rb",
|
51
|
+
"test/unit/remailer_test.rb"
|
54
52
|
]
|
55
53
|
|
56
54
|
if s.respond_to? :specification_version then
|
@@ -22,6 +22,24 @@ class AutomaticDelegate
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
class LineInterpreter < Remailer::Interpreter
|
26
|
+
attr_reader :lines
|
27
|
+
|
28
|
+
state :initialized do
|
29
|
+
enter do
|
30
|
+
@lines = [ ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
parse(/^.*?\r?\n/) do |data|
|
35
|
+
data.chomp
|
36
|
+
end
|
37
|
+
|
38
|
+
default do |line|
|
39
|
+
@lines << line
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
25
43
|
class ExampleInterpreter < Remailer::Interpreter
|
26
44
|
include TestTriggerHelper
|
27
45
|
|
@@ -65,7 +83,7 @@ end
|
|
65
83
|
|
66
84
|
class RemailerInterpreterTest < Test::Unit::TestCase
|
67
85
|
def test_default_state
|
68
|
-
assert_equal [ :initialized, :terminated ], Remailer::Interpreter.states_defined
|
86
|
+
assert_equal [ :initialized, :terminated ], Remailer::Interpreter.states_defined.collect { |s| s.to_s }.sort.collect { |s| s.to_sym }
|
69
87
|
assert_equal true, Remailer::Interpreter.state_defined?(:initialized)
|
70
88
|
assert_equal true, Remailer::Interpreter.state_defined?(:terminated)
|
71
89
|
assert_equal false, Remailer::Interpreter.state_defined?(:unknown)
|
@@ -121,6 +139,55 @@ class RemailerInterpreterTest < Test::Unit::TestCase
|
|
121
139
|
assert_equal 'Stop message', interpreter.message
|
122
140
|
assert_equal :terminated, interpreter.state
|
123
141
|
end
|
142
|
+
|
143
|
+
def test_interpreter_can_process
|
144
|
+
interpreter = LineInterpreter.new
|
145
|
+
|
146
|
+
assert_equal [ ], interpreter.lines
|
147
|
+
|
148
|
+
line = "EXAMPLE LINE\n"
|
149
|
+
|
150
|
+
interpreter.process(line)
|
151
|
+
|
152
|
+
assert_equal 'EXAMPLE LINE', interpreter.lines[-1]
|
153
|
+
assert_equal '', line
|
154
|
+
|
155
|
+
line << "ANOTHER EXAMPLE LINE\r\n"
|
156
|
+
|
157
|
+
interpreter.process(line)
|
158
|
+
|
159
|
+
assert_equal 'ANOTHER EXAMPLE LINE', interpreter.lines[-1]
|
160
|
+
assert_equal '', line
|
161
|
+
|
162
|
+
line << "LINE ONE\r\nLINE TWO\r\n"
|
163
|
+
|
164
|
+
interpreter.process(line)
|
165
|
+
|
166
|
+
assert_equal 'LINE ONE', interpreter.lines[-2]
|
167
|
+
assert_equal 'LINE TWO', interpreter.lines[-1]
|
168
|
+
assert_equal '', line
|
169
|
+
|
170
|
+
line << "INCOMPLETE LINE"
|
171
|
+
|
172
|
+
interpreter.process(line)
|
173
|
+
|
174
|
+
assert_equal 'LINE TWO', interpreter.lines[-1]
|
175
|
+
assert_equal "INCOMPLETE LINE", line
|
176
|
+
|
177
|
+
line << "\r"
|
178
|
+
|
179
|
+
interpreter.process(line)
|
180
|
+
|
181
|
+
assert_equal 'LINE TWO', interpreter.lines[-1]
|
182
|
+
assert_equal "INCOMPLETE LINE\r", line
|
183
|
+
|
184
|
+
line << "\n"
|
185
|
+
|
186
|
+
interpreter.process(line)
|
187
|
+
|
188
|
+
assert_equal 'INCOMPLETE LINE', interpreter.lines[-1]
|
189
|
+
assert_equal '', line
|
190
|
+
end
|
124
191
|
|
125
192
|
def test_default_handler_for_interpreter
|
126
193
|
interpreter = ExampleInterpreter.new
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 8
|
9
|
+
version: 0.3.8
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Scott Tadman
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-12 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
21
|
-
description: EventMachine
|
21
|
+
description: EventMachine SMTP Mail User Agent
|
22
22
|
email: scott@twg.ca
|
23
23
|
executables: []
|
24
24
|
|
@@ -28,7 +28,6 @@ extra_rdoc_files:
|
|
28
28
|
- README.rdoc
|
29
29
|
files:
|
30
30
|
- .document
|
31
|
-
- .gitignore
|
32
31
|
- README.rdoc
|
33
32
|
- Rakefile
|
34
33
|
- VERSION
|
@@ -52,8 +51,8 @@ homepage: http://github.com/twg/remailer
|
|
52
51
|
licenses: []
|
53
52
|
|
54
53
|
post_install_message:
|
55
|
-
rdoc_options:
|
56
|
-
|
54
|
+
rdoc_options: []
|
55
|
+
|
57
56
|
require_paths:
|
58
57
|
- lib
|
59
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
data/.gitignore
DELETED