post_office 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,10 +1,66 @@
1
1
  PostOffice mock SMTP/POP3 server
2
2
  ================================
3
3
 
4
+ https://github.com/bluerail/post_office
5
+
4
6
  By Rene van Lieshout <rene@bluerail.nl>
5
7
 
6
- Usage:
8
+ Description
9
+ -----------
10
+
11
+ PostOffice is a mock SMTP/POP3 server to accept mails sent from your Rails application when it's running in development. The messages can be retrieved using a standard POP3 client, such as mail.app. Just connect to localhost with any username and password.
12
+
13
+ Note: Received messages are **not** sent to their final recipient and will remain available until deleted or when the process is quit.
14
+
15
+ Installation
16
+ ------------
17
+
18
+ sudo gem install post_office
19
+
20
+ Usage
21
+ -----
22
+
23
+ sudo post_office [options]
24
+
25
+ -v, --verbose Output more information
26
+ -l, --logfile FILE Write log to FILE. Outputs to STDOUT (or /var/log/post_office.log when daemonized) by default.
27
+ -h, --help Display this screen
28
+
29
+ This starts the service and listens on port 25 and 110. Configure your POP3 client with any username and password.
30
+
31
+ Daemon
32
+ ------
33
+
34
+ It's possible to start PostOffice as a daemon using post_officed:
35
+
36
+ Usage: post_officed <command> <options> -- <application options>
37
+
38
+ * where <command> is one of:
39
+ start start an instance of the application
40
+ stop stop all instances of the application
41
+ restart stop all instances and restart them afterwards
42
+ reload send a SIGHUP to all instances of the application
43
+ run start the application and stay on top
44
+ zap set the application to a stopped state
45
+ status show status (PID) of application instances
46
+
47
+ * and where <options> may contain several of the following:
48
+
49
+ -t, --ontop Stay on top (does not daemonize)
50
+ -f, --force Force operation
51
+ -n, --no_wait Do not wait for processes to stop
52
+
53
+ Common options:
54
+ -h, --help Show this message
55
+ --version Show version
56
+
57
+ Planned features
58
+ ----------------
7
59
 
8
- sudo post_office
60
+ * Ability to use custom ports for SMTP and POP
61
+ * Growl notifications
62
+ * Mac OS X Startup Item / launchctl service
63
+ * Store mail in tempfiles instead of in-memory array
64
+ * Tests :)
9
65
 
10
- Listens on port 25 and 110. Configure your POP3 client with any username and password.
66
+ Contributions are welcome! Feel free to fork and send a pull request through Github.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "post_office"
8
+ gemspec.summary = "PostOffice mock SMTP/POP3 server"
9
+ gemspec.description = "PostOffice mock SMTP/POP3 server"
10
+ gemspec.email = "rene@bluerail.nl"
11
+ gemspec.homepage = "http://github.com/bluerail/post_office"
12
+ gemspec.description = "A mock SMTP/POP3 server to aid in the development of applications with mail functionality."
13
+ gemspec.authors = ["Rene van Lieshout"]
14
+ gemspec.bindir = "bin"
15
+ gemspec.executables = ['post_office', 'post_officed']
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
19
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/bin/post_office CHANGED
@@ -1,10 +1,44 @@
1
1
  #!/usr/bin/env ruby
2
2
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
3
 
4
+ require 'optparse'
5
+ require 'logger'
4
6
  require 'thread'
5
7
  require 'smtp_server.rb'
6
8
  require 'pop_server.rb'
7
9
 
10
+ #
11
+ # Parse command line arguments
12
+ #
13
+ options = {}
14
+
15
+ optparse = OptionParser.new do |opts|
16
+ opts.banner = "Usage: #{__FILE__} [options]"
17
+
18
+ options[:verbose] = false
19
+ opts.on( '-v', '--verbose', 'Output more information' ) do
20
+ options[:verbose] = true
21
+ end
22
+
23
+ options[:logfile] = nil
24
+ opts.on( '-l', '--logfile FILE', 'Write log to FILE. Outputs to STDOUT (or /var/log/post_office.log when daemonized) by default.' ) do |file|
25
+ options[:logfile] = file
26
+ end
27
+
28
+ opts.on( '-h', '--help', 'Display this screen' ) do
29
+ puts opts
30
+ exit
31
+ end
32
+ end
33
+
34
+ optparse.parse!
35
+
36
+ #
37
+ # Create our logger
38
+ #
39
+ $log = Logger.new(options[:logfile] || STDOUT)
40
+ $log.level = options[:verbose] ? Logger::DEBUG : Logger::INFO
41
+
8
42
  begin
9
43
  smtp_server = Thread.new{ SMTPServer.new }
10
44
  pop_server = Thread.new{ POPServer.new }
@@ -12,7 +46,7 @@ begin
12
46
  smtp_server.join
13
47
  pop_server.join
14
48
  rescue Interrupt
15
- puts "Interrupt..."
49
+ $log.info "Interrupt..."
16
50
  rescue Errno::EACCES
17
- puts "I need root access to open ports 25 and 110. Please sudo #{__FILE__}"
51
+ $log.error "I need root access to open ports 25 and 110. Please sudo #{__FILE__}"
18
52
  end
data/bin/post_officed ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'daemons'
4
+
5
+ # use /var/log/post_office.log as default logger
6
+ # /var/log/post_office.log
7
+ unless ARGV.include?("-l") || ARGV.include?("--logfile")
8
+ ARGV.push "--" unless ARGV.include?("--")
9
+ ARGV.push "--logfile"
10
+ ARGV.push "/var/log/post_office.log"
11
+ end
12
+
13
+ Daemons.run(File.dirname(__FILE__) + '/post_office')
@@ -25,12 +25,14 @@ class GenericServer
25
25
  def initialize(options)
26
26
  @port = options[:port]
27
27
  server = TCPServer.open(@port)
28
- puts "#{self.class.to_s} listening on port #{@port}"
28
+ $log.info "#{self.class.to_s} listening on port #{@port}"
29
29
 
30
30
  # Accept connections until infinity and beyond
31
31
  loop do
32
32
  Thread.start(server.accept) do |client|
33
33
  begin
34
+ client_addr = client.addr
35
+ $log.info "#{self.class.to_s} accepted connection #{client.object_id} from #{client_addr.inspect}"
34
36
  greet client
35
37
 
36
38
  # Keep processing commands until somebody closed the connection
@@ -40,12 +42,13 @@ class GenericServer
40
42
  # The first word of a line should contain the command
41
43
  command = input.to_s.gsub(/ .*/,"").upcase.gsub(/[\r\n]/,"")
42
44
 
43
- puts "#{client.object_id}:#{@port} < #{input}"
45
+ $log.debug "#{client.object_id}:#{@port} < #{input}"
44
46
 
45
47
  process(client, command, input)
46
48
  end until client.closed?
49
+ $log.info "#{self.class.to_s} closed connection #{client.object_id} with #{client_addr.inspect}"
47
50
  rescue => detail
48
- puts "#{client.object_id}:#{@port} ! #{$!}"
51
+ $log.error "#{client.object_id}:#{@port} ! #{$!}"
49
52
  client.close
50
53
  end
51
54
  end
@@ -54,10 +57,10 @@ class GenericServer
54
57
 
55
58
  # Respond to client by sending back text
56
59
  def respond(client, text)
57
- puts "#{client.object_id}:#{@port} > #{text}"
60
+ $log.debug "#{client.object_id}:#{@port} > #{text}"
58
61
  client.puts text
59
62
  rescue
60
- puts "#{client.object_id}:#{@port} ! #{$!}"
63
+ $log.error "#{client.object_id}:#{@port} ! #{$!}"
61
64
  client.close
62
65
  end
63
66
 
data/lib/smtp_server.rb CHANGED
@@ -45,7 +45,7 @@ class SMTPServer < GenericServer
45
45
  # Stores sender address
46
46
  def mail_from(client, full_data)
47
47
  if /^MAIL FROM:/ =~ full_data.upcase
48
- set_client_data(client, :from, full_data.gsub(/^MAIL FROM:/i,""))
48
+ set_client_data(client, :from, full_data.gsub(/^MAIL FROM:\s*/i,"").gsub(/[\r\n]/,""))
49
49
  respond(client, 250)
50
50
  else
51
51
  respond(client, 500)
@@ -55,7 +55,7 @@ class SMTPServer < GenericServer
55
55
  # Stores recepient address
56
56
  def rcpt_to(client, full_data)
57
57
  if /^RCPT TO:/ =~ full_data.upcase
58
- set_client_data(client, :to, full_data.gsub(/^RCPT TO:/i,""))
58
+ set_client_data(client, :to, full_data.gsub(/^RCPT TO:\s*/i,"").gsub(/[\r\n]/,""))
59
59
  respond(client, 250)
60
60
  else
61
61
  respond(client, 500)
@@ -84,6 +84,7 @@ class SMTPServer < GenericServer
84
84
  get_client_data(client, :data).to_s
85
85
  )
86
86
  respond(client, 250)
87
+ $log.info "Received mail from #{get_client_data(client, :from).to_s} with recipient #{get_client_data(client, :to).to_s}"
87
88
  else
88
89
  set_client_data(client, :data, get_client_data(client, :data).to_s + full_data)
89
90
  end
Binary file
@@ -0,0 +1,46 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{post_office}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Rene van Lieshout"]
12
+ s.date = %q{2011-04-19}
13
+ s.description = %q{A mock SMTP/POP3 server to aid in the development of applications with mail functionality.}
14
+ s.email = %q{rene@bluerail.nl}
15
+ s.executables = ["post_office", "post_officed"]
16
+ s.extra_rdoc_files = [
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "README.md",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "bin/post_office",
24
+ "bin/post_officed",
25
+ "lib/generic_server.rb",
26
+ "lib/pop_server.rb",
27
+ "lib/smtp_server.rb",
28
+ "lib/store.rb",
29
+ "pkg/post_office-0.1.0.gem",
30
+ "post_office.gemspec"
31
+ ]
32
+ s.homepage = %q{http://github.com/bluerail/post_office}
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.5.0}
35
+ s.summary = %q{PostOffice mock SMTP/POP3 server}
36
+
37
+ if s.respond_to? :specification_version then
38
+ s.specification_version = 3
39
+
40
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
41
+ else
42
+ end
43
+ else
44
+ end
45
+ end
46
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: post_office
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Rene van Lieshout
@@ -15,26 +15,31 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-18 00:00:00 +02:00
19
- default_executable: post_office
18
+ date: 2011-04-19 00:00:00 +02:00
19
+ default_executable:
20
20
  dependencies: []
21
21
 
22
22
  description: A mock SMTP/POP3 server to aid in the development of applications with mail functionality.
23
23
  email: rene@bluerail.nl
24
24
  executables:
25
25
  - post_office
26
+ - post_officed
26
27
  extensions: []
27
28
 
28
29
  extra_rdoc_files:
29
30
  - README.md
30
31
  files:
31
32
  - README.md
33
+ - Rakefile
32
34
  - VERSION
35
+ - bin/post_office
36
+ - bin/post_officed
33
37
  - lib/generic_server.rb
34
38
  - lib/pop_server.rb
35
39
  - lib/smtp_server.rb
36
40
  - lib/store.rb
37
- - bin/post_office
41
+ - pkg/post_office-0.1.0.gem
42
+ - post_office.gemspec
38
43
  has_rdoc: true
39
44
  homepage: http://github.com/bluerail/post_office
40
45
  licenses: []
@@ -65,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
70
  requirements: []
66
71
 
67
72
  rubyforge_project:
68
- rubygems_version: 1.3.7
73
+ rubygems_version: 1.5.0
69
74
  signing_key:
70
75
  specification_version: 3
71
76
  summary: PostOffice mock SMTP/POP3 server