remailer 0.5.2 → 0.9.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.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +19 -0
- data/{README.rdoc → README.md} +12 -11
- data/Rakefile +21 -11
- data/VERSION +1 -1
- data/lib/remailer/abstract_connection.rb +36 -20
- data/lib/remailer/imap/client.rb +1 -1
- data/lib/remailer/interpreter.rb +40 -19
- data/lib/remailer/interpreter/state_proxy.rb +1 -1
- data/lib/remailer/smtp/client.rb +20 -26
- data/lib/remailer/smtp/client/interpreter.rb +85 -12
- data/lib/remailer/smtp/server.rb +9 -4
- data/lib/remailer/smtp/server/interpreter.rb +16 -15
- data/lib/remailer/smtp/server/transaction.rb +9 -2
- data/lib/remailer/socks5/client/interpreter.rb +18 -13
- data/remailer.gemspec +33 -23
- data/test/bin/exercise +115 -0
- data/test/config.example.yml +15 -0
- data/test/config.rb +41 -0
- data/test/helper.rb +42 -23
- data/test/unit/remailer_imap_client_interpreter_test.rb +2 -2
- data/test/unit/remailer_imap_client_test.rb +10 -12
- data/test/unit/remailer_interpreter_state_proxy_test.rb +14 -14
- data/test/unit/remailer_interpreter_test.rb +36 -28
- data/test/unit/remailer_smtp_client_interpreter_test.rb +80 -33
- data/test/unit/remailer_smtp_client_test.rb +53 -55
- data/test/unit/remailer_smtp_server_test.rb +24 -18
- data/test/unit/remailer_socks5_client_interpreter_test.rb +71 -10
- data/test/unit/remailer_test.rb +2 -2
- metadata +66 -24
- data/test/config.example.rb +0 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c66f7fc5cd78fcb8115342274f77169e4658cfb575d6b2609d2ae07bbd7278a0
|
4
|
+
data.tar.gz: 277347ffde8646bb32f6dc01cddca71be940c21fc46f5cfe32ecb4d02c849065
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6352a8dddf0f8cf1cd16cb810af0993a7bbd3386fe0ccc28c20fc9d891a9a9d4ae69e98b106f6d3a31933620364bb88f77217c2db1103400607333e9f5bcec71
|
7
|
+
data.tar.gz: 3b935c992a65b812b268cd616353886b104ba7c3cb97009c6234bae1e57d685d381c466219dd357542d6a424ddfe643f9648a8a644797f35806170e166cdfdd8
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010-2019 Scott Tadman, PostageApp Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# remailer
|
2
2
|
|
3
3
|
Client/Server Mail Networking Library for SMTP and IMAP
|
4
4
|
|
5
|
-
|
5
|
+
## Overview
|
6
6
|
|
7
7
|
This is an EventMachine Connection implementation of a high-performance
|
8
8
|
asynchronous SMTP client. Although EventMachine ships with a built-in SMTP
|
@@ -10,7 +10,7 @@ client, that version is limited to sending a single email per client,
|
|
10
10
|
and since establishing a client can be the majority of the time required
|
11
11
|
to send email, this limits throughput considerably.
|
12
12
|
|
13
|
-
|
13
|
+
## Use
|
14
14
|
|
15
15
|
The Remailer system consists of the Remailer::Connection class which works
|
16
16
|
within the EventMachine environment. To use it, create a client and then
|
@@ -21,7 +21,7 @@ make one or more requests to send email messages.
|
|
21
21
|
# messages to STDERR.
|
22
22
|
client = Remailer::SMTP::Client.open(
|
23
23
|
'smtp.google.com',
|
24
|
-
:
|
24
|
+
debug: STDERR
|
25
25
|
)
|
26
26
|
|
27
27
|
# Send a single email message through the client at the earliest
|
@@ -51,7 +51,7 @@ example is given here where the information is simply dumped on STDOUT:
|
|
51
51
|
|
52
52
|
client = Remailer::SMTP::Client.open(
|
53
53
|
'smtp.google.com',
|
54
|
-
:
|
54
|
+
debug: lambda { |type, message|
|
55
55
|
puts "#{type}> #{message.inspect}"
|
56
56
|
}
|
57
57
|
)
|
@@ -90,18 +90,19 @@ server. Success is defined as 250, errors vary:
|
|
90
90
|
|
91
91
|
A status code of nil is sent if the server timed out or the connection failed.
|
92
92
|
|
93
|
-
|
93
|
+
## Tests
|
94
94
|
|
95
|
-
In order to run tests, copy `test/config.example.
|
95
|
+
In order to run tests, copy `test/config.example.yml` to `test/config.yml` and
|
96
96
|
adjust as required. For obvious reasons, passwords to SMTP test accounts are
|
97
|
-
not included in the source code of this library.
|
97
|
+
not included in the source code of this library. Any Gmail-type account should
|
98
|
+
serve as a useful test target.
|
98
99
|
|
99
|
-
|
100
|
+
## Status
|
100
101
|
|
101
102
|
This software is currently experimental and is not recommended for production
|
102
103
|
use. Many of the internals may change significantly before a proper beta
|
103
104
|
release is made.
|
104
105
|
|
105
|
-
|
106
|
+
## Copyright
|
106
107
|
|
107
|
-
Copyright (c) 2010-
|
108
|
+
Copyright (c) 2010-2019 Scott Tadman, PostageApp Ltd.
|
data/Rakefile
CHANGED
@@ -1,29 +1,39 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
+
require 'bundler/setup'
|
5
|
+
|
6
|
+
Bundler.require
|
7
|
+
|
4
8
|
begin
|
5
|
-
require '
|
6
|
-
|
9
|
+
require 'juwelier'
|
10
|
+
|
11
|
+
Juwelier::Tasks.new do |gem|
|
7
12
|
gem.name = "remailer"
|
8
13
|
gem.summary = %Q{Reactor-Ready SMTP Mailer}
|
9
|
-
gem.description = %Q{EventMachine SMTP
|
10
|
-
gem.email = "
|
11
|
-
gem.homepage = "http://github.com/
|
14
|
+
gem.description = %Q{EventMachine Mail Agent for SMTP and IMAP}
|
15
|
+
gem.email = "tadman@postageapp.com"
|
16
|
+
gem.homepage = "http://github.com/postageapp/remailer"
|
12
17
|
gem.authors = [ "Scott Tadman" ]
|
13
|
-
|
18
|
+
|
19
|
+
gem.files.exclude(
|
20
|
+
'.travis.yml',
|
21
|
+
'test/config.yml.enc'
|
22
|
+
)
|
14
23
|
end
|
15
|
-
|
24
|
+
|
25
|
+
Juwelier::GemcutterTasks.new
|
26
|
+
|
16
27
|
rescue LoadError
|
17
|
-
puts "
|
28
|
+
puts "Juwelier (or a dependency) not available. Install it with: gem install Juwelier"
|
18
29
|
end
|
19
30
|
|
20
31
|
require 'rake/testtask'
|
32
|
+
|
21
33
|
Rake::TestTask.new(:test) do |test|
|
22
34
|
test.libs << 'lib' << 'test'
|
23
35
|
test.pattern = 'test/**/*_test.rb'
|
24
36
|
test.verbose = true
|
25
37
|
end
|
26
38
|
|
27
|
-
task :
|
28
|
-
|
29
|
-
task :default => :test
|
39
|
+
task default: :test
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.1
|
@@ -83,7 +83,7 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
83
83
|
EventMachine.connect(host_name, host_port, self, options)
|
84
84
|
|
85
85
|
rescue EventMachine::ConnectionError => e
|
86
|
-
report_exception(e, options)
|
86
|
+
self.report_exception(e, options)
|
87
87
|
|
88
88
|
false
|
89
89
|
end
|
@@ -133,6 +133,14 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
133
133
|
@options = options
|
134
134
|
@hostname = @options[:hostname] || Socket.gethostname
|
135
135
|
@timeout = @options[:timeout] || self.class.default_timeout
|
136
|
+
@timed_out = false
|
137
|
+
|
138
|
+
@active_message = nil
|
139
|
+
@established = false
|
140
|
+
@connected = false
|
141
|
+
@closed = false
|
142
|
+
@unbound = false
|
143
|
+
@connecting_to_proxy = false
|
136
144
|
|
137
145
|
@messages = [ ]
|
138
146
|
|
@@ -151,9 +159,19 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
151
159
|
self.after_initialize
|
152
160
|
|
153
161
|
rescue Object => e
|
154
|
-
|
162
|
+
self.class.report_exception(e, @options)
|
163
|
+
|
164
|
+
STDERR.puts "#{e.class}: #{e}" rescue nil
|
155
165
|
end
|
156
|
-
|
166
|
+
|
167
|
+
def after_complete(&block)
|
168
|
+
if (block_given?)
|
169
|
+
@options[:after_complete] = block
|
170
|
+
elsif (@options[:after_complete])
|
171
|
+
@options[:after_complete].call
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
157
175
|
# Returns true if the connection requires TLS support, or false otherwise.
|
158
176
|
def use_tls?
|
159
177
|
!!@options[:use_tls]
|
@@ -166,9 +184,15 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
166
184
|
end
|
167
185
|
|
168
186
|
# Returns true if the connection has advertised authentication support, or
|
169
|
-
# false if not availble or could not be detected.
|
170
|
-
|
171
|
-
|
187
|
+
# false if not availble or could not be detected. If type is specified,
|
188
|
+
# returns true only if that type is supported, false otherwise.
|
189
|
+
def auth_support?(type = nil)
|
190
|
+
case (type)
|
191
|
+
when nil
|
192
|
+
!!@auth_support
|
193
|
+
else
|
194
|
+
!!(@auth_support&.include?(type))
|
195
|
+
end
|
172
196
|
end
|
173
197
|
|
174
198
|
# Returns true if the connection will be using a proxy to connect, false
|
@@ -229,11 +253,11 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
229
253
|
|
230
254
|
# This implements the EventMachine::Connection#receive_data method that
|
231
255
|
# is called each time new data is received from the socket.
|
232
|
-
def receive_data(data)
|
256
|
+
def receive_data(data = nil)
|
233
257
|
reset_timeout!
|
234
258
|
|
235
259
|
@buffer ||= ''
|
236
|
-
@buffer << data
|
260
|
+
@buffer << data if (data)
|
237
261
|
|
238
262
|
if (interpreter = @interpreter)
|
239
263
|
interpreter.process(@buffer) do |reply|
|
@@ -244,7 +268,10 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
244
268
|
end
|
245
269
|
|
246
270
|
rescue Object => e
|
247
|
-
|
271
|
+
self.class.report_exception(e, @options)
|
272
|
+
STDERR.puts("[#{e.class}] #{e}") rescue nil
|
273
|
+
|
274
|
+
raise e
|
248
275
|
end
|
249
276
|
|
250
277
|
def post_init
|
@@ -368,12 +395,6 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
368
395
|
def error?
|
369
396
|
!!@error
|
370
397
|
end
|
371
|
-
|
372
|
-
# EventMachine: Enables TLS support on the connection.
|
373
|
-
def start_tls
|
374
|
-
debug_notification(:tls, "Started")
|
375
|
-
super
|
376
|
-
end
|
377
398
|
|
378
399
|
# EventMachine: Closes down the connection.
|
379
400
|
def close_connection
|
@@ -399,11 +420,6 @@ class Remailer::AbstractConnection < EventMachine::Connection
|
|
399
420
|
|
400
421
|
reset_timeout!
|
401
422
|
end
|
402
|
-
|
403
|
-
# Switches to use the SOCKS5 interpreter for all subsequent communication
|
404
|
-
def use_socks5_interpreter!
|
405
|
-
@interpreter = Remailer::SOCKS5::Client::Interpreter.new(:delegate => self)
|
406
|
-
end
|
407
423
|
|
408
424
|
# -- Callbacks and Notifications ------------------------------------------
|
409
425
|
|
data/lib/remailer/imap/client.rb
CHANGED
@@ -192,7 +192,7 @@ class Remailer::IMAP::Client < Remailer::AbstractConnection
|
|
192
192
|
protected
|
193
193
|
# Switches to use the IMAP interpreter for all subsequent communication
|
194
194
|
def use_imap_interpreter!
|
195
|
-
@interpreter = Interpreter.new(:
|
195
|
+
@interpreter = Interpreter.new(delegate: self)
|
196
196
|
end
|
197
197
|
|
198
198
|
def next_tag
|
data/lib/remailer/interpreter.rb
CHANGED
@@ -19,7 +19,7 @@ class Remailer::Interpreter
|
|
19
19
|
|
20
20
|
# Defines the initial state for objects of this class.
|
21
21
|
def self.initial_state
|
22
|
-
@initial_state
|
22
|
+
@initial_state ||= :initialized
|
23
23
|
end
|
24
24
|
|
25
25
|
# Can be used to reassign the initial state for this class. May be easier
|
@@ -27,21 +27,37 @@ class Remailer::Interpreter
|
|
27
27
|
def self.initial_state=(state)
|
28
28
|
@initial_state = state
|
29
29
|
end
|
30
|
+
|
31
|
+
def self.config
|
32
|
+
{
|
33
|
+
states: @states,
|
34
|
+
default_interpreter: @default,
|
35
|
+
default_parser: @parser,
|
36
|
+
on_error_handler: @on_error
|
37
|
+
}
|
38
|
+
end
|
30
39
|
|
40
|
+
def self.states_default
|
41
|
+
{
|
42
|
+
:initialized => { },
|
43
|
+
:terminated => { }
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
31
47
|
# Returns the states that are defined as a has with their associated
|
32
48
|
# options. The default keys are :initialized and :terminated.
|
33
49
|
def self.states
|
34
50
|
@states ||=
|
35
|
-
|
36
|
-
when true
|
51
|
+
if (superclass.respond_to?(:states))
|
37
52
|
superclass.states.dup
|
38
53
|
else
|
39
|
-
|
40
|
-
:initialized => { },
|
41
|
-
:terminated => { }
|
42
|
-
}
|
54
|
+
self.states_default
|
43
55
|
end
|
44
56
|
end
|
57
|
+
|
58
|
+
def self.states_empty?
|
59
|
+
self.states == self.states_default
|
60
|
+
end
|
45
61
|
|
46
62
|
# Returns true if a given state is defined, false otherwise.
|
47
63
|
def self.state_defined?(state)
|
@@ -66,15 +82,15 @@ class Remailer::Interpreter
|
|
66
82
|
end
|
67
83
|
|
68
84
|
# This is a method to convert a spec and a block into a proper parser
|
69
|
-
# method. If spec is specified, it should be a
|
70
|
-
#
|
85
|
+
# method. If spec is specified, it should be a Integer, or a Regexp. A
|
86
|
+
# Integer defines a minimum size to process, useful for packed binary
|
71
87
|
# streams, while a Regexp defines a pattern that must match before the
|
72
88
|
# parser is engaged.
|
73
89
|
def self.create_parser_for_spec(spec, &block)
|
74
90
|
case (spec)
|
75
91
|
when nil
|
76
92
|
block
|
77
|
-
when
|
93
|
+
when Integer
|
78
94
|
lambda do |s|
|
79
95
|
if (s.length >= spec)
|
80
96
|
part = s.slice!(0, spec)
|
@@ -114,8 +130,7 @@ class Remailer::Interpreter
|
|
114
130
|
# Returns the parser used when no state-specific parser has been defined.
|
115
131
|
def self.default_parser
|
116
132
|
@parser ||=
|
117
|
-
|
118
|
-
when true
|
133
|
+
if (superclass.respond_to?(:default_parser))
|
119
134
|
superclass.default_parser
|
120
135
|
else
|
121
136
|
lambda { |s| _s = s.dup; s.replace(''); _s }
|
@@ -125,8 +140,7 @@ class Remailer::Interpreter
|
|
125
140
|
# Returns the current default_interpreter.
|
126
141
|
def self.default_interpreter
|
127
142
|
@default ||=
|
128
|
-
|
129
|
-
when true
|
143
|
+
if (superclass.respond_to?(:default_interpreter))
|
130
144
|
superclass.default_interpreter
|
131
145
|
else
|
132
146
|
nil
|
@@ -136,8 +150,7 @@ class Remailer::Interpreter
|
|
136
150
|
# Returns the defined error handler
|
137
151
|
def self.on_error_handler
|
138
152
|
@on_error ||=
|
139
|
-
|
140
|
-
when true
|
153
|
+
if (superclass.respond_to?(:on_error_handler))
|
141
154
|
superclass.on_error_handler
|
142
155
|
else
|
143
156
|
nil
|
@@ -155,6 +168,8 @@ class Remailer::Interpreter
|
|
155
168
|
# before the first state is entered.
|
156
169
|
def initialize(options = nil)
|
157
170
|
@delegate = (options and options[:delegate])
|
171
|
+
@state = nil
|
172
|
+
@error = nil
|
158
173
|
|
159
174
|
yield(self) if (block_given?)
|
160
175
|
|
@@ -212,8 +227,8 @@ class Remailer::Interpreter
|
|
212
227
|
yield(parsed) if (block_given?)
|
213
228
|
|
214
229
|
interpret(*parsed)
|
215
|
-
|
216
|
-
break if (s.empty?)
|
230
|
+
|
231
|
+
break if (s.empty? or self.finished?)
|
217
232
|
end
|
218
233
|
end
|
219
234
|
|
@@ -245,7 +260,7 @@ class Remailer::Interpreter
|
|
245
260
|
match_result = match_result.to_a
|
246
261
|
|
247
262
|
if (match_result.length > 1)
|
248
|
-
|
263
|
+
match_result.shift
|
249
264
|
args[0, 1] = match_result
|
250
265
|
else
|
251
266
|
args[0].sub!(match_result[0], '')
|
@@ -290,6 +305,12 @@ class Remailer::Interpreter
|
|
290
305
|
def will_interpret?(proc, args)
|
291
306
|
true
|
292
307
|
end
|
308
|
+
|
309
|
+
# Should return true if this interpreter no longer wants any data, false
|
310
|
+
# otherwise. Subclasses should implement their own behavior here.
|
311
|
+
def finished?
|
312
|
+
false
|
313
|
+
end
|
293
314
|
|
294
315
|
# Returns true if an error has been generated, false otherwise. The error
|
295
316
|
# content can be retrived by calling error.
|
@@ -14,7 +14,7 @@ class Remailer::Interpreter::StateProxy
|
|
14
14
|
|
15
15
|
# Defines a parser specification.
|
16
16
|
def parse(spec = nil, &block)
|
17
|
-
@options[:parser] = Remailer::Interpreter.
|
17
|
+
@options[:parser] = Remailer::Interpreter.create_parser_for_spec(spec, &block)
|
18
18
|
end
|
19
19
|
|
20
20
|
# Defines a block that will execute when the state is entered.
|
data/lib/remailer/smtp/client.rb
CHANGED
@@ -60,6 +60,8 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
60
60
|
# Called by AbstractConnection at the end of the initialize procedure
|
61
61
|
def after_initialize
|
62
62
|
@protocol = :smtp
|
63
|
+
@error = nil
|
64
|
+
@tls_support = nil
|
63
65
|
|
64
66
|
if (using_proxy?)
|
65
67
|
proxy_connection_initiated!
|
@@ -69,6 +71,11 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
74
|
+
# Switches to use the SOCKS5 interpreter for all subsequent communication
|
75
|
+
def use_socks5_interpreter!
|
76
|
+
@interpreter = Remailer::SOCKS5::Client::Interpreter.new(delegate: self)
|
77
|
+
end
|
78
|
+
|
72
79
|
# Closes the connection after all of the queued messages have been sent.
|
73
80
|
def close_when_complete!
|
74
81
|
@options[:close] = true
|
@@ -83,10 +90,10 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
83
90
|
end
|
84
91
|
|
85
92
|
message = {
|
86
|
-
:
|
87
|
-
:
|
88
|
-
:
|
89
|
-
:
|
93
|
+
from: from,
|
94
|
+
to: to,
|
95
|
+
data: data,
|
96
|
+
callback: block
|
90
97
|
}
|
91
98
|
|
92
99
|
@messages << message
|
@@ -108,10 +115,10 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
108
115
|
end
|
109
116
|
|
110
117
|
message = {
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
118
|
+
from: from,
|
119
|
+
to: to,
|
120
|
+
test: true,
|
121
|
+
callback: block
|
115
122
|
}
|
116
123
|
|
117
124
|
@messages << message
|
@@ -146,23 +153,6 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
146
153
|
def unbound?
|
147
154
|
!!@unbound
|
148
155
|
end
|
149
|
-
|
150
|
-
# This implements the EventMachine::Connection#receive_data method that
|
151
|
-
# is called each time new data is received from the socket.
|
152
|
-
def receive_data(data)
|
153
|
-
reset_timeout!
|
154
|
-
|
155
|
-
@buffer ||= ''
|
156
|
-
@buffer << data
|
157
|
-
|
158
|
-
if (interpreter = @interpreter)
|
159
|
-
interpreter.process(@buffer) do |reply|
|
160
|
-
debug_notification(:receive, "[#{interpreter.label}] #{reply.inspect}")
|
161
|
-
end
|
162
|
-
else
|
163
|
-
error_notification(:out_of_band, "Receiving data before a protocol has been established.")
|
164
|
-
end
|
165
|
-
end
|
166
156
|
|
167
157
|
# Returns the current state of the active interpreter, or nil if no state
|
168
158
|
# is assigned.
|
@@ -227,7 +217,11 @@ class Remailer::SMTP::Client < Remailer::AbstractConnection
|
|
227
217
|
|
228
218
|
# Switches to use the SMTP interpreter for all subsequent communication
|
229
219
|
def use_smtp_interpreter!
|
230
|
-
@interpreter = Interpreter.new(:
|
220
|
+
@interpreter = Interpreter.new(delegate: self)
|
221
|
+
|
222
|
+
# Trigger processing using the new interpreter as some SMTP data might
|
223
|
+
# already be buffered by this point.
|
224
|
+
receive_data
|
231
225
|
end
|
232
226
|
|
233
227
|
# Callback receiver for when the proxy connection has been completed.
|