mail_sandbox 0.0.7 → 0.1.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.
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
- script: "bundle exec turn -Itest test/mail_sandbox"
2
+ script: "bundle exec turn -Itest test/integration test/unit"
3
3
  rvm:
4
4
  - 1.9.3
5
5
  branches:
@@ -10,6 +10,8 @@ module MailSandbox
10
10
  # :config_file:String - path to yaml config file
11
11
  # :http_observe?:Boolean - subscribe Observer::Http to receive new messages and push them by http protocol
12
12
  # :http_observe_url:String - url for push on receive new messages, use by Observer::Http
13
+ # :daemonize:Bool - run daemonized in the background
14
+ # :pidfile:String - PATH to pid file
13
15
  #
14
16
  def initialize
15
17
  @config = {
@@ -1,5 +1,6 @@
1
1
  require "eventmachine"
2
2
  require 'optparse'
3
+ require 'simple_pid'
3
4
  require 'fileutils'
4
5
 
5
6
  module MailSandbox
@@ -22,6 +23,14 @@ module MailSandbox
22
23
  config.environment = f
23
24
  end
24
25
 
26
+ opts.on("-D", "--daemonize", "Run daemonized") do |f|
27
+ config.daemonize = f
28
+ end
29
+
30
+ opts.on("-P", "--pid FILE", "File to store PID") do |f|
31
+ config.pidfile = ::File.expand_path(f)
32
+ end
33
+
25
34
  end.parse!
26
35
  end
27
36
 
@@ -39,13 +48,16 @@ module MailSandbox
39
48
  when :debug then Logger::DEBUG
40
49
  end
41
50
  STDOUT.sync = true
42
- MailSandbox::Signals.trap
51
+ MailSandbox::Signals.trap(self)
43
52
  MailSandbox::Server.parms = config.server_params
44
53
  end
45
54
 
46
55
  def start
47
56
  configure
48
57
 
58
+ Process.daemon if config.daemonize
59
+ write_pidfile if config.pidfile
60
+
49
61
  MailSandbox.logger.info "Start MailSandbox::Server on #{config.listen}:#{config.port}"
50
62
 
51
63
  EventMachine::run {
@@ -57,6 +69,26 @@ module MailSandbox
57
69
  config.environment || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || :development
58
70
  end
59
71
 
72
+ def write_pidfile
73
+ @simple_pid = SimplePid.new(config.pidfile)
74
+
75
+ if @simple_pid.exists?
76
+ unless @simple_pid.running?
77
+ @simple_pid.cleanup
78
+ @simple_pid.write!
79
+ end
80
+ else
81
+ @simple_pid.write!
82
+ end
83
+
84
+ end
85
+
86
+ def terminate
87
+ MailSandbox.logger.info "Got quit/terminate signal. Bye."
88
+ @simple_pid.cleanup if @simple_pid
89
+ exit
90
+ end
91
+
60
92
  end
61
93
 
62
94
  end
@@ -20,7 +20,7 @@ module MailSandbox
20
20
 
21
21
  def receive_message
22
22
  message.completed_at = Time.now
23
- Subscribe.notify(message)
23
+ MailSandbox.subscriber.notify(message)
24
24
  true
25
25
  end
26
26
 
@@ -1,14 +1,14 @@
1
1
  module MailSandbox
2
2
  class Signals
3
3
 
4
- def self.trap
4
+ def self.trap(server)
5
+
5
6
  %w'TERM QUIT'.each do |signal|
6
7
  Signal.trap(signal) do
7
- MailSandbox.logger.info "Got #{signal} signal. Bye."
8
- exit
8
+ server.terminate
9
9
  end
10
-
11
10
  end
11
+
12
12
  end
13
13
 
14
14
  end
@@ -0,0 +1,35 @@
1
+ module MailSandbox
2
+ class Subscriber
3
+
4
+ def subscribe(observer)
5
+ observers[observer] ||= observer
6
+ end
7
+
8
+ def unsubscribe(observer)
9
+ observers.delete(observer)
10
+ end
11
+
12
+ def notify(message)
13
+ observers.each_value do |observer|
14
+
15
+ thread = Thread.new do
16
+ mutex.synchronize do
17
+ observer.update(message)
18
+ end
19
+ end
20
+
21
+ thread.abort_on_exception = true
22
+ #thread.run
23
+ end
24
+ end
25
+
26
+ def observers
27
+ @observers ||= {}
28
+ end
29
+
30
+ def mutex
31
+ @mutex ||= Mutex.new
32
+ end
33
+
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module MailSandbox
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/mail_sandbox.rb CHANGED
@@ -6,21 +6,25 @@ module MailSandbox
6
6
  autoload :Server, 'mail_sandbox/server'
7
7
  autoload :Message, 'mail_sandbox/message'
8
8
  autoload :Observer, 'mail_sandbox/observer'
9
- autoload :Subscribe, 'mail_sandbox/subscribe'
9
+ autoload :Subscriber, 'mail_sandbox/subscriber'
10
10
  autoload :Config, 'mail_sandbox/config'
11
11
  autoload :Runner, 'mail_sandbox/runner'
12
12
  autoload :Signals, 'mail_sandbox/signals'
13
13
 
14
14
  def self.subscribe(observer)
15
- Subscribe.subscribe observer
15
+ subscriber.subscribe observer
16
16
  end
17
17
 
18
18
  def self.unsubscribe(observer)
19
- Subscribe.unsubscribe observer
19
+ subscriber.unsubscribe observer
20
20
  end
21
21
 
22
22
  def self.logger
23
23
  @logger ||= Logger.new(STDOUT)
24
24
  end
25
25
 
26
+ def self.subscriber
27
+ @subscriber ||= Subscriber.new
28
+ end
29
+
26
30
  end
data/mail_sandbox.gemspec CHANGED
@@ -19,8 +19,10 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency('em-http-request', '~> 0.3.0')
20
20
  gem.add_dependency('OptionParser')
21
21
  gem.add_dependency('file-utils')
22
+ gem.add_dependency('simple_pid')
22
23
 
23
24
  gem.add_development_dependency('rake')
24
25
  gem.add_development_dependency('minitest')
25
26
  gem.add_development_dependency('turn')
27
+ gem.add_development_dependency('mocha', '>= 0.13.1')
26
28
  end
@@ -0,0 +1,9 @@
1
+ HTTP/1.0 200 OK
2
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
3
+ Expires: -1
4
+ Cache-Control: private, max-age=0
5
+ Content-Type: text/html; charset=ISO-8859-1
6
+ Via: 1.0 .:80 (squid)
7
+ Connection: close
8
+
9
+ Success
@@ -0,0 +1,7 @@
1
+ From: Private Person <me@fromdomain.com>
2
+ To: A Test User <test@todomain.com>
3
+ Subject: SMTP e-mail test
4
+
5
+ 1 This is a test e-mail message.
6
+ 2 This is a test e-mail message.
7
+ 3 This is a test e-mail message.
@@ -0,0 +1,24 @@
1
+ require "test_helper"
2
+
3
+ class DaemonizeTest < MiniTest::Unit::TestCase
4
+ include SpawnHelper
5
+
6
+ def teardown
7
+ kill_server
8
+ end
9
+
10
+ def test_daemonize
11
+ pid = spawn command("-D -P #{PID_FILE}")
12
+
13
+ assert wait_pid_file, "Pid file doesn't exist."
14
+ assert !alive?, "Server didn't daemonize."
15
+
16
+ real_pid = File.read(PID_FILE).to_i
17
+ assert pid != real_pid
18
+
19
+ @pid = real_pid
20
+ assert alive?, "Real server doesn't alive."
21
+ end
22
+
23
+
24
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ class PidfileTest < MiniTest::Unit::TestCase
4
+ include SpawnHelper
5
+
6
+ def teardown
7
+ kill_server
8
+ end
9
+
10
+ def test_pidfile
11
+ pid = spawn_server "-P #{PID_FILE}"
12
+ assert wait_pid_file, "Pid file doesn't exist."
13
+
14
+ pidfile_pid = File.read(PID_FILE).to_i
15
+ assert_equal pid, pidfile_pid
16
+
17
+ kill_server
18
+ assert !File.exist?(PID_FILE)
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,60 @@
1
+ require "test_helper"
2
+
3
+ class ServerTest < MiniTest::Unit::TestCase
4
+ include SpawnHelper
5
+
6
+ def setup
7
+ spawn_server
8
+ end
9
+
10
+ def teardown
11
+ kill_server
12
+ end
13
+
14
+ def test_server_run
15
+ assert alive?, "Server not alive."
16
+ end
17
+
18
+ def test_server_bind_port
19
+ assert wait_bind, "Server doesn't bind."
20
+ end
21
+
22
+ def test_server_helo
23
+ wait_bind
24
+
25
+ bye, helo = nil
26
+ Socket.tcp('127.0.0.1', 2525) do |socket|
27
+ helo = socket.readline
28
+ socket.print "EHLO localhost.localdomain\r\n"
29
+ socket.readpartial(65536)
30
+ socket.print "QUIT\r\n"
31
+ bye = socket.readline
32
+ socket.close_write
33
+ socket.close_read
34
+ end
35
+
36
+ assert_match /^220 .*/, helo
37
+ assert_match /^221 .*/, bye
38
+ end
39
+
40
+ def test_server_auth
41
+ wait_bind
42
+
43
+ user = 'app_user'
44
+ password = 'KnesSGaF9TQ9wOOdXd2m'
45
+
46
+ @message = File.read(File.expand_path("../../fixtures/message.txt", __FILE__))
47
+
48
+ smtp = Net::SMTP.new('localhost', 2525)
49
+ smtp.start do |smtp|
50
+ smtp.auth_plain(user, password)
51
+ smtp.send_message @message, 'me@fromdomain.com', 'test@todomain.com'
52
+ end
53
+
54
+ assert alive?
55
+ end
56
+
57
+
58
+
59
+
60
+ end
File without changes
File without changes
data/test/test_helper.rb CHANGED
@@ -1,12 +1,58 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
1
+ require "bundler/setup"
2
+ Bundler.require(:default, :test)
3
3
 
4
- require 'test/unit'
5
-
6
- require 'mail_sandbox'
7
4
  require 'em-http-request'
8
-
9
5
  require "socket"
6
+ require 'support/my_observer'
10
7
  require 'net/smtp'
11
- require 'my_observer'
8
+ require 'mocha'
9
+
10
+ module SpawnHelper
11
+ PID_FILE = "/tmp/mail_sandbox.#{rand*1000.to_i}.pid"
12
+
13
+ def spawn_server(options = "")
14
+ @pid = spawn command(options)
15
+ sleep 0.1 until alive?
16
+ Process.detach @pid
17
+ sleep 1
18
+ @pid
19
+ end
20
+
21
+ def command(options)
22
+ "bundle exec mail_sandbox #{options}"
23
+ end
24
+
25
+ def kill_server(pid = nil)
26
+ pid ||= @pid
27
+ Process.kill "QUIT", pid rescue false
28
+ sleep 0.1 while alive?(pid)
29
+ end
30
+
31
+ def alive?(pid = nil)
32
+ pid ||= @pid
33
+ Process.kill 0, pid rescue false
34
+ end
35
+
36
+ def wait_pid_file
37
+ 50.times do
38
+ return true if File.exist?(PID_FILE)
39
+ sleep 0.1
40
+ end
41
+ false
42
+ end
43
+
44
+ def wait_bind
45
+ 50.times do
46
+ begin
47
+ Socket.tcp('127.0.0.1', 2525)
48
+ rescue
49
+ sleep 0.1
50
+ next
51
+ end
52
+ return true
53
+ end
54
+ false
55
+ end
56
+
12
57
 
58
+ end
@@ -13,14 +13,14 @@ class ConfigTest < MiniTest::Unit::TestCase
13
13
  end
14
14
 
15
15
  def test_load_from_yml_file
16
- @config.load_from_yml_file(:development, 'test/config.yml')
16
+ @config.load_from_yml_file(:development, 'test/support/config.yml')
17
17
 
18
18
  assert @config.test_key
19
19
  assert_equal 'development value', @config.test_key
20
20
  end
21
21
 
22
22
  def test_load_file
23
- @config.config_file = 'test/config.yml'
23
+ @config.config_file = 'test/support/config.yml'
24
24
 
25
25
  @config.load_from_yml_file(:production)
26
26
 
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ class SubscribeTest < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @message = MailSandbox::Message.new
7
+ @subscriber = MailSandbox::Subscriber.new
8
+ @observer = MyObserver.new
9
+ end
10
+
11
+ def test_subscribe
12
+ @subscriber.subscribe @observer
13
+
14
+ assert_equal 1, @subscriber.observers.count
15
+ end
16
+
17
+ def test_observer_notify
18
+ @subscriber.subscribe @observer
19
+
20
+ @subscriber.notify @message and sleep 1
21
+ assert_equal @message, @observer.message
22
+ end
23
+
24
+ def test_http_observer
25
+ url = "http://localhost/api"
26
+ body = {:body => {:message => @message.to_a}}
27
+
28
+ http_mock = mock()
29
+ http_mock.stubs(:callback)
30
+ http_mock.stubs(:errback)
31
+
32
+ EventMachine::HttpRequest.any_instance.expects(:post).with(body).returns(http_mock)
33
+
34
+ @observer = MailSandbox::Observer::Http.new url
35
+ @subscriber.subscribe @observer
36
+
37
+ @subscriber.notify @message and sleep 1
38
+
39
+ assert true
40
+ end
41
+
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail_sandbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.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: 2012-10-27 00:00:00.000000000 Z
12
+ date: 2012-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: simple_pid
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
78
94
  - !ruby/object:Gem::Dependency
79
95
  name: rake
80
96
  requirement: !ruby/object:Gem::Requirement
@@ -123,6 +139,22 @@ dependencies:
123
139
  - - ! '>='
124
140
  - !ruby/object:Gem::Version
125
141
  version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: mocha
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: 0.13.1
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: 0.13.1
126
158
  description: Gem has run SMTP server and manipulate letters received. Using the Observer
127
159
  pattern you can subscribe to the event server.
128
160
  email:
@@ -147,14 +179,19 @@ files:
147
179
  - lib/mail_sandbox/runner.rb
148
180
  - lib/mail_sandbox/server.rb
149
181
  - lib/mail_sandbox/signals.rb
150
- - lib/mail_sandbox/subscribe.rb
182
+ - lib/mail_sandbox/subscriber.rb
151
183
  - lib/mail_sandbox/version.rb
152
184
  - mail_sandbox.gemspec
153
- - test/config.yml
154
- - test/mail_sandbox/config_test.rb
155
- - test/mail_sandbox/server_test.rb
156
- - test/my_observer.rb
185
+ - test/fixtures/http_response.txt
186
+ - test/fixtures/message.txt
187
+ - test/integration/daemonize_test.rb
188
+ - test/integration/pidfile_test.rb
189
+ - test/integration/spawn_test.rb
190
+ - test/support/config.yml
191
+ - test/support/my_observer.rb
157
192
  - test/test_helper.rb
193
+ - test/unit/config_test.rb
194
+ - test/unit/subscribe_test.rb
158
195
  homepage: https://github.com/kaize/mail_sandbox
159
196
  licenses: []
160
197
  post_install_message:
@@ -167,12 +204,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
204
  - - ! '>='
168
205
  - !ruby/object:Gem::Version
169
206
  version: '0'
207
+ segments:
208
+ - 0
209
+ hash: 501385496686318604
170
210
  required_rubygems_version: !ruby/object:Gem::Requirement
171
211
  none: false
172
212
  requirements:
173
213
  - - ! '>='
174
214
  - !ruby/object:Gem::Version
175
215
  version: '0'
216
+ segments:
217
+ - 0
218
+ hash: 501385496686318604
176
219
  requirements: []
177
220
  rubyforge_project:
178
221
  rubygems_version: 1.8.24
@@ -180,8 +223,13 @@ signing_key:
180
223
  specification_version: 3
181
224
  summary: SMTP server sandbox
182
225
  test_files:
183
- - test/config.yml
184
- - test/mail_sandbox/config_test.rb
185
- - test/mail_sandbox/server_test.rb
186
- - test/my_observer.rb
226
+ - test/fixtures/http_response.txt
227
+ - test/fixtures/message.txt
228
+ - test/integration/daemonize_test.rb
229
+ - test/integration/pidfile_test.rb
230
+ - test/integration/spawn_test.rb
231
+ - test/support/config.yml
232
+ - test/support/my_observer.rb
187
233
  - test/test_helper.rb
234
+ - test/unit/config_test.rb
235
+ - test/unit/subscribe_test.rb
@@ -1,37 +0,0 @@
1
- module MailSandbox
2
- class Subscribe
3
- class<<self
4
-
5
- def subscribe(observer)
6
- observers[observer] ||= observer
7
- end
8
-
9
- def unsubscribe(observer)
10
- observers.delete(observer)
11
- end
12
-
13
- def notify(message)
14
- observers.each_value do |observer|
15
-
16
- thread = Thread.new do
17
- mutex.synchronize do
18
- observer.update(message)
19
- end
20
- end
21
-
22
- thread.abort_on_exception = true
23
- #thread.run
24
- end
25
- end
26
-
27
- def observers
28
- @observers ||= {}
29
- end
30
-
31
- def mutex
32
- @mutex ||= Mutex.new
33
- end
34
-
35
- end
36
- end
37
- end
@@ -1,128 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ServerTest < MiniTest::Unit::TestCase
4
-
5
- def setup
6
- EventMachine::MockHttpRequest.reset_registry!
7
- EventMachine::MockHttpRequest.reset_counts!
8
- EventMachine::MockHttpRequest.pass_through_requests = false
9
-
10
- EventMachine::MockHttpRequest.activate!
11
-
12
- @server = Thread.new do
13
- MailSandbox::Runner.new.start
14
- end
15
-
16
- @server.abort_on_exception = true
17
- @server.run
18
-
19
- @message = <<MESSAGE_END
20
- From: Private Person <me@fromdomain.com>
21
- To: A Test User <test@todomain.com>
22
- Subject: SMTP e-mail test
23
-
24
- 1 This is a test e-mail message.
25
- 2 This is a test e-mail message.
26
- 3 This is a test e-mail message.
27
- MESSAGE_END
28
-
29
- @http_response = <<-RESPONSE.gsub(/^ +/, '')
30
- HTTP/1.0 200 OK
31
- Date: Mon, 16 Nov 2009 20:39:15 GMT
32
- Expires: -1
33
- Cache-Control: private, max-age=0
34
- Content-Type: text/html; charset=ISO-8859-1
35
- Via: 1.0 .:80 (squid)
36
- Connection: close
37
-
38
- Success
39
- RESPONSE
40
-
41
- @url = 'http://localhost:8080/api/mails'
42
-
43
- #wait run server
44
- sleep 0.5
45
- end
46
-
47
- def teardown
48
- EventMachine::MockHttpRequest.deactivate!
49
- MailSandbox::Subscribe.observers.clear
50
- @server.terminate
51
- sleep 0.5
52
- end
53
-
54
- def test_server_run
55
- server_run = @server.alive?
56
- assert server_run, "Server not alive"
57
- end
58
-
59
- def test_server_helo
60
- bye, helo = nil
61
- Socket.tcp('127.0.0.1', 2525) do |socket|
62
- helo = socket.readline
63
- socket.print "EHLO localhost.localdomain\r\n"
64
- socket.readpartial(65536)
65
- socket.print "QUIT\r\n"
66
- bye = socket.readline
67
- socket.close_write
68
- socket.close_read
69
- end
70
- assert_match /^220 .*/, helo
71
- assert_match /^221 .*/, bye
72
- end
73
-
74
- def test_subscribe_mailsandox
75
-
76
- observer = MyObserver.new
77
- MailSandbox.subscribe observer
78
-
79
- Net::SMTP.start('localhost', 2525) do |smtp|
80
- smtp.send_message @message, 'me@fromdomain.com', 'test@todomain.com'
81
- end
82
-
83
- sleep 1
84
-
85
- assert observer.message
86
-
87
- end
88
-
89
- def test_http_observer
90
-
91
- EventMachine::MockHttpRequest.register(@url,:post, nil, @http_response)
92
-
93
- observer = MailSandbox::Observer::Http.new(@url)
94
- MailSandbox.subscribe observer
95
-
96
- Net::SMTP.start('localhost', 2525) do |smtp|
97
- smtp.send_message @message, 'me@fromdomain.com', 'test@todomain.com'
98
- end
99
-
100
- sleep 1
101
-
102
- assert_equal 1, EM::HttpRequest.count(@url, :post)
103
-
104
- end
105
-
106
- def test_auth
107
- user = 'app_user'
108
- password = 'KnesSGaF9TQ9wOOdXd2m'
109
-
110
- observer = MyObserver.new
111
- MailSandbox.subscribe observer
112
-
113
- smtp = Net::SMTP.new('localhost', 2525)
114
- smtp.start do |smtp|
115
- smtp.auth_plain(user, password)
116
- smtp.send_message @message, 'me@fromdomain.com', 'test@todomain.com'
117
- end
118
-
119
- sleep 1
120
-
121
- assert observer.message
122
- assert_equal user, observer.message.user
123
- assert_equal password, observer.message.password
124
-
125
- end
126
-
127
-
128
- end