fakesmtpd 0.2.0 → 0.3.0

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.
@@ -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