fakesmtpd 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,6 +26,7 @@
26
26
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
27
 
28
28
  require 'fileutils'
29
+ require 'gserver'
29
30
  require 'json'
30
31
  require 'logger'
31
32
  require 'optparse'
@@ -33,48 +34,45 @@ require 'socket'
33
34
  require 'thread'
34
35
 
35
36
  module FakeSMTPd
36
- class HTTPServer
37
- attr_reader :server, :port, :smtpd, :log
37
+ class HTTPServer < GServer
38
+ attr_reader :server, :port, :smtpd
38
39
 
39
40
  def initialize(options = {})
40
41
  @port = options.fetch(:port)
41
42
  @smtpd = options.fetch(:smtpd)
42
- @log = Logger.new(options[:logfile]).tap do |l|
43
- l.formatter = proc do |severity, datetime, _, msg|
44
- "[fakesmtpd-http] #{severity} #{datetime} - #{msg}\n"
45
- end
46
- end
43
+ super(
44
+ @port,
45
+ options[:host] || '0.0.0.0',
46
+ options[:max_connections] || 4,
47
+ options[:logfile],
48
+ options[:audit] || !!ENV['FAKESMTPD_AUDIT'] || false,
49
+ options[:debug] || !!ENV['FAKESMTPD_DEBUG'] || false
50
+ )
47
51
  end
48
52
 
49
- def start
50
- @server = Thread.new do
51
- httpd = TCPServer.new(port)
52
- log.info "FakeSMTPd HTTP server serving on #{port}"
53
- log.info "PID=#{$$} Thread=#{Thread.current.inspect}"
54
- loop do
55
- client = httpd.accept
56
- begin
57
- request_line = client.gets
58
- path = request_line.split[1]
59
- handle_client(request_line, path, client)
60
- rescue => e
61
- handle_500(path, client, e)
62
- end
63
- end
64
- end
53
+ def start(*args)
54
+ super(*args)
55
+ log "FakeSMTPd HTTP server serving on #{port}"
56
+ log "PID=#{$$} Thread=#{Thread.current.inspect}"
65
57
  end
66
58
 
67
- def kill!
68
- if @server
69
- log.info "FakeSMTPd HTTP server stopping"
70
- @server.kill
71
- end
59
+ def stop(*args)
60
+ log "FakeSMTPd HTTP server stopping"
61
+ super(*args)
62
+ end
63
+
64
+ def serve(io)
65
+ request_line = io.gets
66
+ path = request_line.split[1]
67
+ handle_client(request_line, path, io)
68
+ rescue => e
69
+ handle_500(path, io, e)
72
70
  end
73
71
 
74
72
  private
75
73
 
76
74
  def handle_client(request_line, path, client)
77
- log.info request_line.chomp
75
+ log request_line.chomp
78
76
  case request_line
79
77
  when /^GET \/ /
80
78
  handle_get_root(path, client)
@@ -87,7 +85,6 @@ module FakeSMTPd
87
85
  else
88
86
  handle_404(path, client)
89
87
  end
90
- client.close
91
88
  end
92
89
 
93
90
  def handle_get_root(path, client)
@@ -184,8 +181,8 @@ module FakeSMTPd
184
181
  end
185
182
  end
186
183
 
187
- class Server
188
- VERSION = '0.2.0'
184
+ class Server < GServer
185
+ VERSION = '0.3.0'
189
186
  USAGE = <<-EOU.gsub(/^ {6}/, '')
190
187
  Usage: #{File.basename($0)} <smtp-port> <message-dir> [options]
191
188
 
@@ -195,9 +192,11 @@ module FakeSMTPd
195
192
  transaction), the sender, recipients, and combined headers and body as
196
193
  an array of strings.
197
194
 
195
+ Version: #{VERSION}
196
+
198
197
  EOU
199
198
 
200
- attr_reader :port, :message_dir, :log, :logfile, :pidfile
199
+ attr_reader :port, :message_dir, :logfile, :pidfile
201
200
  attr_reader :messages
202
201
 
203
202
  class << self
@@ -220,7 +219,7 @@ module FakeSMTPd
220
219
  opts.on('-l LOGFILE', '--logfile LOGFILE',
221
220
  'Optional file where all log messages will be written ' <<
222
221
  '(default $stderr)') do |logfile|
223
- options[:logfile] = logfile
222
+ options[:logfile] = File.open(logfile, 'a')
224
223
  end
225
224
  end.parse!(argv)
226
225
 
@@ -242,13 +241,13 @@ module FakeSMTPd
242
241
 
243
242
  @httpd.start
244
243
  @smtpd.start
245
- loop { sleep 1 }
244
+ @httpd.join && @smtpd.join
246
245
  rescue Exception => e
247
- if @httpd
248
- @httpd.kill!
246
+ if @httpd && !@httpd.stopped?
247
+ @httpd.stop
249
248
  end
250
- if @smtpd
251
- @smtpd.kill!
249
+ if @smtpd && !@smtpd.stopped?
250
+ @smtpd.stop
252
251
  end
253
252
  unless e.is_a?(Interrupt)
254
253
  raise e
@@ -259,38 +258,32 @@ module FakeSMTPd
259
258
  def initialize(options = {})
260
259
  @port = options.fetch(:port)
261
260
  @message_dir = options.fetch(:dir)
262
- @pidfile = options[:pidfile] || 'fakesmtpd.pid'
263
- @log = Logger.new(options[:logfile]).tap do |l|
264
- l.formatter = proc do |severity, datetime, _, msg|
265
- "[fakesmtpd-smtp] #{severity} #{datetime} - #{msg}\n"
266
- end
267
- end
261
+ @pidfile = options[:pidfile]
268
262
  @messages = MessageStore.new(@message_dir)
263
+
264
+ super(
265
+ @port,
266
+ options[:host] || '0.0.0.0',
267
+ options[:max_connections] || 4,
268
+ options[:logfile],
269
+ options[:audit] || !!ENV['FAKESMTPD_AUDIT'] || false,
270
+ options[:debug] || !!ENV['FAKESMTPD_DEBUG'] || false
271
+ )
269
272
  end
270
273
 
271
- def start
272
- @server = Thread.new do
273
- smtpd = TCPServer.new(port)
274
- log.info "FakeSMTPd SMTP server serving on #{port}, " <<
275
- "writing messages to #{message_dir.inspect}"
276
- log.info "PID=#{$$}, Thread=#{Thread.current.inspect}"
274
+ def start(*args)
275
+ super(*args)
276
+ if pidfile
277
277
  File.open(pidfile, 'w') { |f| f.puts($$) }
278
-
279
- loop do
280
- begin
281
- serve(smtpd.accept)
282
- rescue => e
283
- log.error "WAT: #{e.class.name} #{e.message}"
284
- end
285
- end
286
278
  end
279
+ log "FakeSMTPd SMTP server serving on #{port}, writing messages to " <<
280
+ "#{message_dir.inspect}"
281
+ log "PID=#{$$} Thread=#{Thread.current.inspect}"
287
282
  end
288
283
 
289
- def kill!
290
- if @server
291
- log.info "FakeSMTPd SMTP server stopping"
292
- @server.kill
293
- end
284
+ def stop(*args)
285
+ log "FakeSMTPd SMTP server stopping"
286
+ super(*args)
294
287
  end
295
288
 
296
289
  def serve(client)
@@ -311,17 +304,17 @@ module FakeSMTPd
311
304
 
312
305
  client.puts '220 localhost fakesmtpd ready ESMTP'
313
306
  helo = client.getline
314
- log.info "#{client} Helo: #{helo.inspect}"
307
+ log "#{client} Helo: #{helo.inspect}"
315
308
 
316
309
  if helo =~ /^EHLO\s+/
317
- log.info "#{client} Seen an EHLO"
310
+ log "#{client} Seen an EHLO"
318
311
  client.puts '250-localhost only has this one extension'
319
312
  client.puts '250 HELP'
320
313
  end
321
314
 
322
315
  from = client.getline
323
316
  client.puts '250 OK'
324
- log.info "#{client} From: #{from.inspect}"
317
+ log "#{client} From: #{from.inspect}"
325
318
 
326
319
  recipients = []
327
320
  loop do
@@ -332,7 +325,7 @@ module FakeSMTPd
332
325
  client.puts '354 Lemme have it'
333
326
  break
334
327
  else
335
- log.info "#{client} To: #{to.inspect}"
328
+ log "#{client} To: #{to.inspect}"
336
329
  recipients << to
337
330
  client.puts '250 OK'
338
331
  end
@@ -343,14 +336,14 @@ module FakeSMTPd
343
336
  line = client.getline
344
337
  break if line.nil? || line == '.'
345
338
  lines << line
346
- log.debug "#{client} + #{line}"
339
+ log "#{client} + #{line}"
347
340
  end
348
341
 
349
342
  client.puts '250 OK'
350
343
  client.gets
351
344
  client.puts '221 Buhbye'
352
345
  client.close
353
- log.info "#{client} ding!"
346
+ log "#{client} ding!"
354
347
 
355
348
  record(client, from, recipients, lines)
356
349
  end
@@ -1,3 +1,3 @@
1
1
  module FakeSMTPd
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fakesmtpd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-12 00:00:00.000000000 Z
12
+ date: 2013-08-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -80,7 +80,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
80
  version: '0'
81
81
  segments:
82
82
  - 0
83
- hash: 2803386961380935915
83
+ hash: -2619994145312715398
84
84
  required_rubygems_version: !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
89
  version: '0'
90
90
  segments:
91
91
  - 0
92
- hash: 2803386961380935915
92
+ hash: -2619994145312715398
93
93
  requirements: []
94
94
  rubyforge_project:
95
95
  rubygems_version: 1.8.23