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 +59 -3
- data/Rakefile +19 -0
- data/VERSION +1 -1
- data/bin/post_office +36 -2
- data/bin/post_officed +13 -0
- data/lib/generic_server.rb +8 -5
- data/lib/smtp_server.rb +3 -2
- data/pkg/post_office-0.1.0.gem +0 -0
- data/post_office.gemspec +46 -0
- metadata +13 -8
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
|
-
|
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
|
-
|
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
|
-
|
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.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
|
-
|
49
|
+
$log.info "Interrupt..."
|
16
50
|
rescue Errno::EACCES
|
17
|
-
|
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')
|
data/lib/generic_server.rb
CHANGED
@@ -25,12 +25,14 @@ class GenericServer
|
|
25
25
|
def initialize(options)
|
26
26
|
@port = options[:port]
|
27
27
|
server = TCPServer.open(@port)
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
60
|
+
$log.debug "#{client.object_id}:#{@port} > #{text}"
|
58
61
|
client.puts text
|
59
62
|
rescue
|
60
|
-
|
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
|
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
|
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
|
data/post_office.gemspec
ADDED
@@ -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:
|
5
|
-
prerelease:
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 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-
|
19
|
-
default_executable:
|
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
|
-
-
|
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.
|
73
|
+
rubygems_version: 1.5.0
|
69
74
|
signing_key:
|
70
75
|
specification_version: 3
|
71
76
|
summary: PostOffice mock SMTP/POP3 server
|