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