post_office 0.1.0 → 0.2.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/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