boomerang-mocksmtpd 0.0.3 → 0.0.5
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.
- checksums.yaml +7 -0
- data/ChangeLog +26 -17
- data/README +59 -59
- data/Rakefile +13 -144
- data/bin/mocksmtpd +5 -5
- data/lib/mocksmtpd.rb +13 -8
- data/lib/smtpserver.rb +257 -257
- data/templates/html/index.erb +46 -46
- data/templates/html/index_entry.erb +8 -8
- data/templates/html/mail.erb +16 -16
- data/templates/mocksmtpd.conf.erb +10 -10
- data/test/mocksmtpd_test.rb +5 -5
- data/test/test_helper.rb +3 -3
- metadata +56 -65
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b4b799bb74fb8ad18780af6399f27c310c8af6ae485b3469f386159458220f45
|
4
|
+
data.tar.gz: f82c8d20b990ab736f7f0358e966567acd992dad168aeacc997ea39f3a405df2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7e47d1f2fb10e10a46a3bf9bb223736b883c387cfdfd677e9daef97c88ee14b3cd0c183075cec641ef9bc50df2b4608eacc389ace87ae314ee6d957a7f0b4482
|
7
|
+
data.tar.gz: 17f782d77ced0a5cb46edec9b23072d1de80b766a9871af114b97c81f190cff379a1f272de1d3afbfb636c54834f561efa989b25def214eaaa43525321bb69ad
|
data/ChangeLog
CHANGED
@@ -1,17 +1,26 @@
|
|
1
|
-
== 0.0.
|
2
|
-
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
*
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
*
|
16
|
-
*
|
17
|
-
|
1
|
+
== 0.0.5 / 2025-07-31
|
2
|
+
|
3
|
+
* Passing trim_mode with the 3rd argument of ERB.new is deprecated
|
4
|
+
|
5
|
+
== 0.0.4 / 2022-06-17
|
6
|
+
|
7
|
+
* support for pid file in windows/linux
|
8
|
+
* added --silent option
|
9
|
+
|
10
|
+
== 0.0.3 / 2008-11-08
|
11
|
+
|
12
|
+
* rescue Process.eid NotImplementedError.
|
13
|
+
* warn when Process.eid can't be changed.
|
14
|
+
* read log level from config file.
|
15
|
+
* change param name from Loglevel to LogLevel
|
16
|
+
* add debug log.
|
17
|
+
|
18
|
+
== 0.0.2 / 2008-11-03
|
19
|
+
|
20
|
+
* release gem version.
|
21
|
+
|
22
|
+
== 0.0.1 / 2008-11-03
|
23
|
+
|
24
|
+
* moved into github
|
25
|
+
* initial release
|
26
|
+
|
data/README
CHANGED
@@ -1,59 +1,59 @@
|
|
1
|
-
|
2
|
-
= mocksmtpd
|
3
|
-
|
4
|
-
|
5
|
-
== Description
|
6
|
-
|
7
|
-
Mocksmtpd is a SMTP server for developping and testing web application. This SMTP server does not send mail anywhere. Otherwise, save all mails as HTML format.
|
8
|
-
|
9
|
-
You can test mail using browser testing tools like Selenium.
|
10
|
-
|
11
|
-
=== Screenshot
|
12
|
-
|
13
|
-
http://koseki2.tumblr.com/post/57148631
|
14
|
-
http://koseki2.tumblr.com/post/57148564
|
15
|
-
|
16
|
-
== Installation
|
17
|
-
|
18
|
-
=== Archive Installation
|
19
|
-
|
20
|
-
rake install
|
21
|
-
|
22
|
-
=== Gem Installation
|
23
|
-
|
24
|
-
gem sources -a http://gems.github.com
|
25
|
-
gem install koseki-mocksmtpd
|
26
|
-
|
27
|
-
== Quick Start
|
28
|
-
|
29
|
-
$ mocksmtpd init
|
30
|
-
$ cd ./mocksmtpd
|
31
|
-
$ sudo mocksmtpd
|
32
|
-
|
33
|
-
== Usaage
|
34
|
-
|
35
|
-
mocksmtpd init [dirname] ... create log,inbox dir and config file.
|
36
|
-
mocksmtpd ... start as console mode.
|
37
|
-
mocksmtpd start ... start as daemon.
|
38
|
-
mocksmtpd stop ... stop running daemon.
|
39
|
-
|
40
|
-
=== Options
|
41
|
-
|
42
|
-
The default config file is ./mocksmtpd.conf, but you can specify any other file using -f option.
|
43
|
-
|
44
|
-
-f / --config=FILE ... Specify config file.
|
45
|
-
--help ... Show help.
|
46
|
-
--silent ... Disable console output.
|
47
|
-
--version ... Show version.
|
48
|
-
|
49
|
-
== Features/Problems
|
50
|
-
|
51
|
-
|
52
|
-
== Synopsis
|
53
|
-
|
54
|
-
|
55
|
-
== Copyright
|
56
|
-
|
57
|
-
Author:: KOSEKI Kengo <koseki@gmail.com>
|
58
|
-
Copyright:: Copyright (c) 2008
|
59
|
-
License:: Ruby Licence
|
1
|
+
|
2
|
+
= mocksmtpd
|
3
|
+
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
Mocksmtpd is a SMTP server for developping and testing web application. This SMTP server does not send mail anywhere. Otherwise, save all mails as HTML format.
|
8
|
+
|
9
|
+
You can test mail using browser testing tools like Selenium.
|
10
|
+
|
11
|
+
=== Screenshot
|
12
|
+
|
13
|
+
http://koseki2.tumblr.com/post/57148631
|
14
|
+
http://koseki2.tumblr.com/post/57148564
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
=== Archive Installation
|
19
|
+
|
20
|
+
rake install
|
21
|
+
|
22
|
+
=== Gem Installation
|
23
|
+
|
24
|
+
gem sources -a http://gems.github.com
|
25
|
+
gem install koseki-mocksmtpd
|
26
|
+
|
27
|
+
== Quick Start
|
28
|
+
|
29
|
+
$ mocksmtpd init
|
30
|
+
$ cd ./mocksmtpd
|
31
|
+
$ sudo mocksmtpd
|
32
|
+
|
33
|
+
== Usaage
|
34
|
+
|
35
|
+
mocksmtpd init [dirname] ... create log,inbox dir and config file.
|
36
|
+
mocksmtpd ... start as console mode.
|
37
|
+
mocksmtpd start ... start as daemon.
|
38
|
+
mocksmtpd stop ... stop running daemon.
|
39
|
+
|
40
|
+
=== Options
|
41
|
+
|
42
|
+
The default config file is ./mocksmtpd.conf, but you can specify any other file using -f option.
|
43
|
+
|
44
|
+
-f / --config=FILE ... Specify config file.
|
45
|
+
--help ... Show help.
|
46
|
+
--silent ... Disable console output.
|
47
|
+
--version ... Show version.
|
48
|
+
|
49
|
+
== Features/Problems
|
50
|
+
|
51
|
+
|
52
|
+
== Synopsis
|
53
|
+
|
54
|
+
|
55
|
+
== Copyright
|
56
|
+
|
57
|
+
Author:: KOSEKI Kengo <koseki@gmail.com>
|
58
|
+
Copyright:: Copyright (c) 2008
|
59
|
+
License:: Ruby Licence
|
data/Rakefile
CHANGED
@@ -1,144 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
NAME = "mocksmtpd"
|
15
|
-
AUTHOR = "KOSEKI Kengo"
|
16
|
-
EMAIL = "koseki@gmail.com"
|
17
|
-
DESCRIPTION = "Mock SMTP server for development/testing."
|
18
|
-
RUBYFORGE_PROJECT = "mocksmtpd"
|
19
|
-
HOMEPATH = "http://github.com/koseki/mocksmtpd/"
|
20
|
-
BIN_FILES = %w(mocksmtpd)
|
21
|
-
|
22
|
-
VERS = Mocksmtpd::VERSION
|
23
|
-
REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
24
|
-
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
25
|
-
RDOC_OPTS = [
|
26
|
-
'--title', "#{NAME} documentation",
|
27
|
-
"--charset", "utf-8",
|
28
|
-
"--opname", "index.html",
|
29
|
-
"--line-numbers",
|
30
|
-
"--main", "README",
|
31
|
-
"--inline-source",
|
32
|
-
]
|
33
|
-
|
34
|
-
task :default => [:test]
|
35
|
-
task :package => [:clean]
|
36
|
-
|
37
|
-
Rake::TestTask.new("test") do |t|
|
38
|
-
t.libs << "test"
|
39
|
-
t.pattern = "test/**/*_test.rb"
|
40
|
-
t.verbose = true
|
41
|
-
end
|
42
|
-
|
43
|
-
spec = Gem::Specification.new do |s|
|
44
|
-
s.name = NAME
|
45
|
-
s.version = VERS
|
46
|
-
s.platform = Gem::Platform::RUBY
|
47
|
-
s.has_rdoc = true
|
48
|
-
s.extra_rdoc_files = ["README", "ChangeLog"]
|
49
|
-
s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
|
50
|
-
s.summary = DESCRIPTION
|
51
|
-
s.description = DESCRIPTION
|
52
|
-
s.author = AUTHOR
|
53
|
-
s.email = EMAIL
|
54
|
-
s.homepage = HOMEPATH
|
55
|
-
s.executables = BIN_FILES
|
56
|
-
s.rubyforge_project = RUBYFORGE_PROJECT
|
57
|
-
s.bindir = "bin"
|
58
|
-
s.require_path = "lib"
|
59
|
-
#s.autorequire = ""
|
60
|
-
s.test_files = Dir["test/*_test.rb"]
|
61
|
-
|
62
|
-
#s.add_dependency('activesupport', '>=1.3.1')
|
63
|
-
#s.required_ruby_version = '>= 1.8.2'
|
64
|
-
|
65
|
-
s.files = %w(README ChangeLog Rakefile) +
|
66
|
-
Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
|
67
|
-
Dir.glob("ext/**/*.{h,c,rb}") +
|
68
|
-
Dir.glob("examples/**/*.rb") +
|
69
|
-
Dir.glob("tools/*.rb") +
|
70
|
-
Dir.glob("rails/*.rb")
|
71
|
-
|
72
|
-
s.extensions = FileList["ext/**/extconf.rb"].to_a
|
73
|
-
end
|
74
|
-
|
75
|
-
Rake::GemPackageTask.new(spec) do |p|
|
76
|
-
p.need_tar = true
|
77
|
-
p.gem_spec = spec
|
78
|
-
end
|
79
|
-
|
80
|
-
task :install do
|
81
|
-
name = "#{NAME}-#{VERS}.gem"
|
82
|
-
sh %{rake package}
|
83
|
-
sh %{sudo gem install pkg/#{name}}
|
84
|
-
end
|
85
|
-
|
86
|
-
task :uninstall => [:clean] do
|
87
|
-
sh %{sudo gem uninstall #{NAME}}
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
Rake::RDocTask.new do |rdoc|
|
92
|
-
rdoc.rdoc_dir = 'html'
|
93
|
-
rdoc.options += RDOC_OPTS
|
94
|
-
rdoc.template = "resh"
|
95
|
-
#rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
96
|
-
if ENV['DOC_FILES']
|
97
|
-
rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
|
98
|
-
else
|
99
|
-
rdoc.rdoc_files.include('README', 'ChangeLog')
|
100
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
101
|
-
rdoc.rdoc_files.include('ext/**/*.c')
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
desc "Publish to RubyForge"
|
106
|
-
task :rubyforge => [:rdoc, :package] do
|
107
|
-
require 'rubyforge'
|
108
|
-
Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, '').upload
|
109
|
-
end
|
110
|
-
|
111
|
-
desc 'Package and upload the release to rubyforge.'
|
112
|
-
task :release => [:clean, :package] do |t|
|
113
|
-
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
|
114
|
-
abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
|
115
|
-
pkg = "pkg/#{NAME}-#{VERS}"
|
116
|
-
|
117
|
-
require 'rubyforge'
|
118
|
-
rf = RubyForge.new.configure
|
119
|
-
puts "Logging in"
|
120
|
-
rf.login
|
121
|
-
|
122
|
-
c = rf.userconfig
|
123
|
-
# c["release_notes"] = description if description
|
124
|
-
# c["release_changes"] = changes if changes
|
125
|
-
c["preformatted"] = true
|
126
|
-
|
127
|
-
files = [
|
128
|
-
"#{pkg}.tgz",
|
129
|
-
"#{pkg}.gem"
|
130
|
-
].compact
|
131
|
-
|
132
|
-
puts "Releasing #{NAME} v. #{VERS}"
|
133
|
-
rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
|
134
|
-
end
|
135
|
-
|
136
|
-
desc 'Show information about the gem.'
|
137
|
-
task :debug_gem do
|
138
|
-
puts spec.to_ruby
|
139
|
-
end
|
140
|
-
|
141
|
-
desc 'Update gem spec'
|
142
|
-
task :gemspec do
|
143
|
-
open("#{NAME}.gemspec", 'w').write spec.to_ruby
|
144
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require_relative 'lib/mocksmtpd'
|
6
|
+
|
7
|
+
task :default => [:test]
|
8
|
+
|
9
|
+
Rake::TestTask.new("test") do |t|
|
10
|
+
t.libs << "test"
|
11
|
+
t.pattern = "test/**/*_test.rb"
|
12
|
+
t.verbose = true
|
13
|
+
end
|
data/bin/mocksmtpd
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
|
-
require "rubygems"
|
4
|
-
require "mocksmtpd"
|
5
|
-
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "mocksmtpd"
|
5
|
+
|
6
6
|
Mocksmtpd.new(ARGV).run
|
data/lib/mocksmtpd.rb
CHANGED
@@ -8,7 +8,7 @@ require 'nkf'
|
|
8
8
|
require 'smtpserver'
|
9
9
|
|
10
10
|
class Mocksmtpd
|
11
|
-
VERSION = '0.0.
|
11
|
+
VERSION = '0.0.5'
|
12
12
|
TEMPLATE_DIR = Pathname.new(File.dirname(__FILE__)) + "../templates"
|
13
13
|
|
14
14
|
include ERB::Util
|
@@ -101,7 +101,7 @@ class Mocksmtpd
|
|
101
101
|
def template(name)
|
102
102
|
path = TEMPLATE_DIR + "#{name}.erb"
|
103
103
|
src = path.read
|
104
|
-
return ERB.new(src,
|
104
|
+
return ERB.new(src, trim_mode: "%-")
|
105
105
|
end
|
106
106
|
|
107
107
|
def init
|
@@ -132,8 +132,13 @@ class Mocksmtpd
|
|
132
132
|
|
133
133
|
pid = File.read(@pidfile)
|
134
134
|
print "Stopping #{pid}..." unless @silent
|
135
|
-
|
136
|
-
|
135
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
136
|
+
system "taskkill /F /PID #{pid} 1>NUL"
|
137
|
+
else
|
138
|
+
system "sudo kill -TERM #{pid} 1>NUL"
|
139
|
+
end
|
140
|
+
sleep(1)
|
141
|
+
File.delete(@pidfile) if File.exist?(@pidfile)
|
137
142
|
puts "done" unless @silent
|
138
143
|
end
|
139
144
|
|
@@ -177,7 +182,7 @@ class Mocksmtpd
|
|
177
182
|
end
|
178
183
|
|
179
184
|
def delete_pid_file
|
180
|
-
File.delete(@pidfile)
|
185
|
+
File.delete(@pidfile) if File.exist?(@pidfile)
|
181
186
|
@logger.debug("pid file deleted: file=#{@pidfile}")
|
182
187
|
end
|
183
188
|
|
@@ -253,9 +258,9 @@ class Mocksmtpd
|
|
253
258
|
subject = src.match(/^Subject:\s*(.+)/i).to_a[1].to_s.strip
|
254
259
|
date = src.match(/^Date:\s*(.+)/i).to_a[1].to_s.strip
|
255
260
|
|
256
|
-
src = ERB::Util.h(src)
|
257
|
-
src = src.gsub(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
|
258
|
-
src = src.gsub(/(?:\r\n|\r|\n)/, "<br />\n")
|
261
|
+
# src = ERB::Util.h(src)
|
262
|
+
# src = src.gsub(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
|
263
|
+
# src = src.gsub(/(?:\r\n|\r|\n)/, "<br />\n")
|
259
264
|
|
260
265
|
if date.empty?
|
261
266
|
date = Time.now
|
data/lib/smtpserver.rb
CHANGED
@@ -1,257 +1,257 @@
|
|
1
|
-
# http://tmtm.org/ja/ruby/smtpd/
|
2
|
-
# http://rubyist.g.hatena.ne.jp/muscovyduck/20070707/p1
|
3
|
-
|
4
|
-
require 'webrick'
|
5
|
-
require 'tempfile'
|
6
|
-
|
7
|
-
module GetsSafe
|
8
|
-
def gets_safe(rs = nil, timeout = @timeout, maxlength = @maxlength)
|
9
|
-
rs = $/ unless rs
|
10
|
-
f = self.kind_of?(IO) ? self : STDIN
|
11
|
-
@gets_safe_buf = '' unless @gets_safe_buf
|
12
|
-
until @gets_safe_buf.include? rs do
|
13
|
-
if maxlength and @gets_safe_buf.length > maxlength then
|
14
|
-
raise Errno::E2BIG, 'too long'
|
15
|
-
end
|
16
|
-
if IO.select([f], nil, nil, timeout) == nil then
|
17
|
-
raise Errno::ETIMEDOUT, 'timeout exceeded'
|
18
|
-
end
|
19
|
-
begin
|
20
|
-
@gets_safe_buf << f.sysread(4096)
|
21
|
-
rescue EOFError, Errno::ECONNRESET
|
22
|
-
return @gets_safe_buf.empty? ? nil : @gets_safe_buf.slice!(0..-1)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
p = @gets_safe_buf.index rs
|
26
|
-
if maxlength and p > maxlength then
|
27
|
-
raise Errno::E2BIG, 'too long'
|
28
|
-
end
|
29
|
-
return @gets_safe_buf.slice!(0, p+rs.length)
|
30
|
-
end
|
31
|
-
attr_accessor :timeout, :maxlength
|
32
|
-
end
|
33
|
-
|
34
|
-
class SMTPD
|
35
|
-
class Error < StandardError; end
|
36
|
-
|
37
|
-
def initialize(sock, domain)
|
38
|
-
@sock = sock
|
39
|
-
@domain = domain
|
40
|
-
@error_interval = 5
|
41
|
-
class << @sock
|
42
|
-
include GetsSafe
|
43
|
-
end
|
44
|
-
@helo_hook = nil
|
45
|
-
@mail_hook = nil
|
46
|
-
@rcpt_hook = nil
|
47
|
-
@data_hook = nil
|
48
|
-
@data_each_line = nil
|
49
|
-
@rset_hook = nil
|
50
|
-
@noop_hook = nil
|
51
|
-
@quit_hook = nil
|
52
|
-
end
|
53
|
-
attr_writer :helo_hook, :mail_hook, :rcpt_hook, :data_hook,
|
54
|
-
:data_each_line, :rset_hook, :noop_hook, :quit_hook
|
55
|
-
|
56
|
-
def start
|
57
|
-
@helo_name = nil
|
58
|
-
@sender = nil
|
59
|
-
@recipients = []
|
60
|
-
catch(:close) do
|
61
|
-
puts_safe "220 #{@domain} service ready"
|
62
|
-
while comm = @sock.gets_safe do
|
63
|
-
catch :next_comm do
|
64
|
-
comm.sub!(/\r?\n/, '')
|
65
|
-
comm, arg = comm.split(/\s+/,2)
|
66
|
-
break if comm == nil
|
67
|
-
case comm.upcase
|
68
|
-
when 'EHLO' then comm_helo arg
|
69
|
-
when 'HELO' then comm_helo arg
|
70
|
-
when 'MAIL' then comm_mail arg
|
71
|
-
when 'RCPT' then comm_rcpt arg
|
72
|
-
when 'DATA' then comm_data arg
|
73
|
-
when 'RSET' then comm_rset arg
|
74
|
-
when 'NOOP' then comm_noop arg
|
75
|
-
when 'QUIT' then comm_quit arg
|
76
|
-
else
|
77
|
-
error '502 Error: command not implemented'
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def line_length_limit=(n)
|
85
|
-
@sock.maxlength = n
|
86
|
-
end
|
87
|
-
|
88
|
-
def input_timeout=(n)
|
89
|
-
@sock.timeout = n
|
90
|
-
end
|
91
|
-
|
92
|
-
attr_reader :line_length_limit, :input_timeout
|
93
|
-
attr_accessor :error_interval
|
94
|
-
attr_accessor :use_file, :max_size
|
95
|
-
|
96
|
-
private
|
97
|
-
def comm_helo(arg)
|
98
|
-
if arg == nil or arg.split.size != 1 then
|
99
|
-
error '501 Syntax: HELO hostname'
|
100
|
-
end
|
101
|
-
@helo_hook.call(arg) if @helo_hook
|
102
|
-
@helo_name = arg
|
103
|
-
reply "250 #{@domain}"
|
104
|
-
end
|
105
|
-
|
106
|
-
def comm_mail(arg)
|
107
|
-
if @sender != nil then
|
108
|
-
error '503 Error: nested MAIL command'
|
109
|
-
end
|
110
|
-
if arg !~ /^FROM:/i then
|
111
|
-
error '501 Syntax: MAIL FROM: <address>'
|
112
|
-
end
|
113
|
-
sender = parse_addr $'
|
114
|
-
if sender == nil then
|
115
|
-
error '501 Syntax: MAIL FROM: <address>'
|
116
|
-
end
|
117
|
-
@mail_hook.call(sender) if @mail_hook
|
118
|
-
@sender = sender
|
119
|
-
reply '250 Ok'
|
120
|
-
end
|
121
|
-
|
122
|
-
def comm_rcpt(arg)
|
123
|
-
if @sender == nil then
|
124
|
-
error '503 Error: need MAIL command'
|
125
|
-
end
|
126
|
-
if arg !~ /^TO:/i then
|
127
|
-
error '501 Syntax: RCPT TO: <address>'
|
128
|
-
end
|
129
|
-
rcpt = parse_addr $'
|
130
|
-
if rcpt == nil then
|
131
|
-
error '501 Syntax: RCPT TO: <address>'
|
132
|
-
end
|
133
|
-
@rcpt_hook.call(rcpt) if @rcpt_hook
|
134
|
-
@recipients << rcpt
|
135
|
-
reply '250 Ok'
|
136
|
-
end
|
137
|
-
|
138
|
-
def comm_data(arg)
|
139
|
-
if @recipients.size == 0 then
|
140
|
-
error '503 Error: need RCPT command'
|
141
|
-
end
|
142
|
-
if arg != nil then
|
143
|
-
error '501 Syntax: DATA'
|
144
|
-
end
|
145
|
-
reply '354 End data with <CR><LF>.<CR><LF>'
|
146
|
-
if @data_hook
|
147
|
-
tmpf = @use_file ? Tempfile.new('smtpd') : ''
|
148
|
-
end
|
149
|
-
size = 0
|
150
|
-
loop do
|
151
|
-
l = @sock.gets_safe
|
152
|
-
if l == nil then
|
153
|
-
raise SMTPD::Error, 'unexpected EOF'
|
154
|
-
end
|
155
|
-
if l.chomp == '.' then break end
|
156
|
-
if l[0] == ?. then
|
157
|
-
l[0,1] = ''
|
158
|
-
end
|
159
|
-
size += l.size
|
160
|
-
if @max_size and @max_size < size then
|
161
|
-
error '552 Error: message too large'
|
162
|
-
end
|
163
|
-
@data_each_line.call(l) if @data_each_line
|
164
|
-
tmpf << l if @data_hook
|
165
|
-
end
|
166
|
-
if @data_hook then
|
167
|
-
if @use_file then
|
168
|
-
tmpf.pos = 0
|
169
|
-
@data_hook.call(tmpf, @sender, @recipients)
|
170
|
-
tmpf.close(true)
|
171
|
-
else
|
172
|
-
@data_hook.call(tmpf, @sender, @recipients)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
reply '250 Ok'
|
176
|
-
@sender = nil
|
177
|
-
@recipients = []
|
178
|
-
end
|
179
|
-
|
180
|
-
def comm_rset(arg)
|
181
|
-
if arg != nil then
|
182
|
-
error '501 Syntax: RSET'
|
183
|
-
end
|
184
|
-
@rset_hook.call(@sender, @recipients) if @rset_hook
|
185
|
-
reply '250 Ok'
|
186
|
-
@sender = nil
|
187
|
-
@recipients = []
|
188
|
-
end
|
189
|
-
|
190
|
-
def comm_noop(arg)
|
191
|
-
if arg != nil then
|
192
|
-
error '501 Syntax: NOOP'
|
193
|
-
end
|
194
|
-
@noop_hook.call(@sender, @recipients) if @noop_hook
|
195
|
-
reply '250 Ok'
|
196
|
-
end
|
197
|
-
|
198
|
-
def comm_quit(arg)
|
199
|
-
if arg != nil then
|
200
|
-
error '501 Syntax: QUIT'
|
201
|
-
end
|
202
|
-
@quit_hook.call(@sender, @recipients) if @quit_hook
|
203
|
-
reply '221 Bye'
|
204
|
-
throw :close
|
205
|
-
end
|
206
|
-
|
207
|
-
def parse_addr(str)
|
208
|
-
str = str.strip
|
209
|
-
if str == '' then
|
210
|
-
return nil
|
211
|
-
end
|
212
|
-
if str =~ /^<(.*)>$/ then
|
213
|
-
return $1.gsub(/\s+/, '')
|
214
|
-
end
|
215
|
-
if str =~ /\s/ then
|
216
|
-
return nil
|
217
|
-
end
|
218
|
-
str
|
219
|
-
end
|
220
|
-
|
221
|
-
def reply(msg)
|
222
|
-
puts_safe msg
|
223
|
-
end
|
224
|
-
|
225
|
-
def error(msg)
|
226
|
-
sleep @error_interval if @error_interval
|
227
|
-
puts_safe msg
|
228
|
-
throw :next_comm
|
229
|
-
end
|
230
|
-
|
231
|
-
def puts_safe(str)
|
232
|
-
begin
|
233
|
-
@sock.puts str + "\r\n"
|
234
|
-
rescue
|
235
|
-
raise SMTPD::Error, "cannot send to client: '#{str.gsub(/\s+/," ")}': #{$!.to_s}"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
SMTPDError = SMTPD::Error
|
241
|
-
|
242
|
-
class SMTPServer < WEBrick::GenericServer
|
243
|
-
def run(sock)
|
244
|
-
server = SMTPD.new(sock, @config[:ServerName])
|
245
|
-
server.input_timeout = @config[:RequestTimeout]
|
246
|
-
server.line_length_limit = @config[:LineLengthLimit]
|
247
|
-
server.helo_hook = @config[:HeloHook]
|
248
|
-
server.mail_hook = @config[:MailHook]
|
249
|
-
server.rcpt_hook = @config[:RcptHook]
|
250
|
-
server.data_hook = @config[:DataHook]
|
251
|
-
server.data_each_line = @config[:DataEachLine]
|
252
|
-
server.rset_hook = @config[:RsetHook]
|
253
|
-
server.noop_hook = @config[:NoopHook]
|
254
|
-
server.quit_hook = @config[:QuitHook]
|
255
|
-
server.start
|
256
|
-
end
|
257
|
-
end
|
1
|
+
# http://tmtm.org/ja/ruby/smtpd/
|
2
|
+
# http://rubyist.g.hatena.ne.jp/muscovyduck/20070707/p1
|
3
|
+
|
4
|
+
require 'webrick'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
module GetsSafe
|
8
|
+
def gets_safe(rs = nil, timeout = @timeout, maxlength = @maxlength)
|
9
|
+
rs = $/ unless rs
|
10
|
+
f = self.kind_of?(IO) ? self : STDIN
|
11
|
+
@gets_safe_buf = '' unless @gets_safe_buf
|
12
|
+
until @gets_safe_buf.include? rs do
|
13
|
+
if maxlength and @gets_safe_buf.length > maxlength then
|
14
|
+
raise Errno::E2BIG, 'too long'
|
15
|
+
end
|
16
|
+
if IO.select([f], nil, nil, timeout) == nil then
|
17
|
+
raise Errno::ETIMEDOUT, 'timeout exceeded'
|
18
|
+
end
|
19
|
+
begin
|
20
|
+
@gets_safe_buf << f.sysread(4096)
|
21
|
+
rescue EOFError, Errno::ECONNRESET
|
22
|
+
return @gets_safe_buf.empty? ? nil : @gets_safe_buf.slice!(0..-1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
p = @gets_safe_buf.index rs
|
26
|
+
if maxlength and p > maxlength then
|
27
|
+
raise Errno::E2BIG, 'too long'
|
28
|
+
end
|
29
|
+
return @gets_safe_buf.slice!(0, p+rs.length)
|
30
|
+
end
|
31
|
+
attr_accessor :timeout, :maxlength
|
32
|
+
end
|
33
|
+
|
34
|
+
class SMTPD
|
35
|
+
class Error < StandardError; end
|
36
|
+
|
37
|
+
def initialize(sock, domain)
|
38
|
+
@sock = sock
|
39
|
+
@domain = domain
|
40
|
+
@error_interval = 5
|
41
|
+
class << @sock
|
42
|
+
include GetsSafe
|
43
|
+
end
|
44
|
+
@helo_hook = nil
|
45
|
+
@mail_hook = nil
|
46
|
+
@rcpt_hook = nil
|
47
|
+
@data_hook = nil
|
48
|
+
@data_each_line = nil
|
49
|
+
@rset_hook = nil
|
50
|
+
@noop_hook = nil
|
51
|
+
@quit_hook = nil
|
52
|
+
end
|
53
|
+
attr_writer :helo_hook, :mail_hook, :rcpt_hook, :data_hook,
|
54
|
+
:data_each_line, :rset_hook, :noop_hook, :quit_hook
|
55
|
+
|
56
|
+
def start
|
57
|
+
@helo_name = nil
|
58
|
+
@sender = nil
|
59
|
+
@recipients = []
|
60
|
+
catch(:close) do
|
61
|
+
puts_safe "220 #{@domain} service ready"
|
62
|
+
while comm = @sock.gets_safe do
|
63
|
+
catch :next_comm do
|
64
|
+
comm.sub!(/\r?\n/, '')
|
65
|
+
comm, arg = comm.split(/\s+/,2)
|
66
|
+
break if comm == nil
|
67
|
+
case comm.upcase
|
68
|
+
when 'EHLO' then comm_helo arg
|
69
|
+
when 'HELO' then comm_helo arg
|
70
|
+
when 'MAIL' then comm_mail arg
|
71
|
+
when 'RCPT' then comm_rcpt arg
|
72
|
+
when 'DATA' then comm_data arg
|
73
|
+
when 'RSET' then comm_rset arg
|
74
|
+
when 'NOOP' then comm_noop arg
|
75
|
+
when 'QUIT' then comm_quit arg
|
76
|
+
else
|
77
|
+
error '502 Error: command not implemented'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def line_length_limit=(n)
|
85
|
+
@sock.maxlength = n
|
86
|
+
end
|
87
|
+
|
88
|
+
def input_timeout=(n)
|
89
|
+
@sock.timeout = n
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :line_length_limit, :input_timeout
|
93
|
+
attr_accessor :error_interval
|
94
|
+
attr_accessor :use_file, :max_size
|
95
|
+
|
96
|
+
private
|
97
|
+
def comm_helo(arg)
|
98
|
+
if arg == nil or arg.split.size != 1 then
|
99
|
+
error '501 Syntax: HELO hostname'
|
100
|
+
end
|
101
|
+
@helo_hook.call(arg) if @helo_hook
|
102
|
+
@helo_name = arg
|
103
|
+
reply "250 #{@domain}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def comm_mail(arg)
|
107
|
+
if @sender != nil then
|
108
|
+
error '503 Error: nested MAIL command'
|
109
|
+
end
|
110
|
+
if arg !~ /^FROM:/i then
|
111
|
+
error '501 Syntax: MAIL FROM: <address>'
|
112
|
+
end
|
113
|
+
sender = parse_addr $'
|
114
|
+
if sender == nil then
|
115
|
+
error '501 Syntax: MAIL FROM: <address>'
|
116
|
+
end
|
117
|
+
@mail_hook.call(sender) if @mail_hook
|
118
|
+
@sender = sender
|
119
|
+
reply '250 Ok'
|
120
|
+
end
|
121
|
+
|
122
|
+
def comm_rcpt(arg)
|
123
|
+
if @sender == nil then
|
124
|
+
error '503 Error: need MAIL command'
|
125
|
+
end
|
126
|
+
if arg !~ /^TO:/i then
|
127
|
+
error '501 Syntax: RCPT TO: <address>'
|
128
|
+
end
|
129
|
+
rcpt = parse_addr $'
|
130
|
+
if rcpt == nil then
|
131
|
+
error '501 Syntax: RCPT TO: <address>'
|
132
|
+
end
|
133
|
+
@rcpt_hook.call(rcpt) if @rcpt_hook
|
134
|
+
@recipients << rcpt
|
135
|
+
reply '250 Ok'
|
136
|
+
end
|
137
|
+
|
138
|
+
def comm_data(arg)
|
139
|
+
if @recipients.size == 0 then
|
140
|
+
error '503 Error: need RCPT command'
|
141
|
+
end
|
142
|
+
if arg != nil then
|
143
|
+
error '501 Syntax: DATA'
|
144
|
+
end
|
145
|
+
reply '354 End data with <CR><LF>.<CR><LF>'
|
146
|
+
if @data_hook
|
147
|
+
tmpf = @use_file ? Tempfile.new('smtpd') : ''
|
148
|
+
end
|
149
|
+
size = 0
|
150
|
+
loop do
|
151
|
+
l = @sock.gets_safe
|
152
|
+
if l == nil then
|
153
|
+
raise SMTPD::Error, 'unexpected EOF'
|
154
|
+
end
|
155
|
+
if l.chomp == '.' then break end
|
156
|
+
if l[0] == ?. then
|
157
|
+
l[0,1] = ''
|
158
|
+
end
|
159
|
+
size += l.size
|
160
|
+
if @max_size and @max_size < size then
|
161
|
+
error '552 Error: message too large'
|
162
|
+
end
|
163
|
+
@data_each_line.call(l) if @data_each_line
|
164
|
+
tmpf << l if @data_hook
|
165
|
+
end
|
166
|
+
if @data_hook then
|
167
|
+
if @use_file then
|
168
|
+
tmpf.pos = 0
|
169
|
+
@data_hook.call(tmpf, @sender, @recipients)
|
170
|
+
tmpf.close(true)
|
171
|
+
else
|
172
|
+
@data_hook.call(tmpf, @sender, @recipients)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
reply '250 Ok'
|
176
|
+
@sender = nil
|
177
|
+
@recipients = []
|
178
|
+
end
|
179
|
+
|
180
|
+
def comm_rset(arg)
|
181
|
+
if arg != nil then
|
182
|
+
error '501 Syntax: RSET'
|
183
|
+
end
|
184
|
+
@rset_hook.call(@sender, @recipients) if @rset_hook
|
185
|
+
reply '250 Ok'
|
186
|
+
@sender = nil
|
187
|
+
@recipients = []
|
188
|
+
end
|
189
|
+
|
190
|
+
def comm_noop(arg)
|
191
|
+
if arg != nil then
|
192
|
+
error '501 Syntax: NOOP'
|
193
|
+
end
|
194
|
+
@noop_hook.call(@sender, @recipients) if @noop_hook
|
195
|
+
reply '250 Ok'
|
196
|
+
end
|
197
|
+
|
198
|
+
def comm_quit(arg)
|
199
|
+
if arg != nil then
|
200
|
+
error '501 Syntax: QUIT'
|
201
|
+
end
|
202
|
+
@quit_hook.call(@sender, @recipients) if @quit_hook
|
203
|
+
reply '221 Bye'
|
204
|
+
throw :close
|
205
|
+
end
|
206
|
+
|
207
|
+
def parse_addr(str)
|
208
|
+
str = str.strip
|
209
|
+
if str == '' then
|
210
|
+
return nil
|
211
|
+
end
|
212
|
+
if str =~ /^<(.*)>$/ then
|
213
|
+
return $1.gsub(/\s+/, '')
|
214
|
+
end
|
215
|
+
if str =~ /\s/ then
|
216
|
+
return nil
|
217
|
+
end
|
218
|
+
str
|
219
|
+
end
|
220
|
+
|
221
|
+
def reply(msg)
|
222
|
+
puts_safe msg
|
223
|
+
end
|
224
|
+
|
225
|
+
def error(msg)
|
226
|
+
sleep @error_interval if @error_interval
|
227
|
+
puts_safe msg
|
228
|
+
throw :next_comm
|
229
|
+
end
|
230
|
+
|
231
|
+
def puts_safe(str)
|
232
|
+
begin
|
233
|
+
@sock.puts str + "\r\n"
|
234
|
+
rescue
|
235
|
+
raise SMTPD::Error, "cannot send to client: '#{str.gsub(/\s+/," ")}': #{$!.to_s}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
SMTPDError = SMTPD::Error
|
241
|
+
|
242
|
+
class SMTPServer < WEBrick::GenericServer
|
243
|
+
def run(sock)
|
244
|
+
server = SMTPD.new(sock, @config[:ServerName])
|
245
|
+
server.input_timeout = @config[:RequestTimeout]
|
246
|
+
server.line_length_limit = @config[:LineLengthLimit]
|
247
|
+
server.helo_hook = @config[:HeloHook]
|
248
|
+
server.mail_hook = @config[:MailHook]
|
249
|
+
server.rcpt_hook = @config[:RcptHook]
|
250
|
+
server.data_hook = @config[:DataHook]
|
251
|
+
server.data_each_line = @config[:DataEachLine]
|
252
|
+
server.rset_hook = @config[:RsetHook]
|
253
|
+
server.noop_hook = @config[:NoopHook]
|
254
|
+
server.quit_hook = @config[:QuitHook]
|
255
|
+
server.start
|
256
|
+
end
|
257
|
+
end
|
data/templates/html/index.erb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
-
<head>
|
5
|
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
-
<link rel="index" href="./index.html" />
|
7
|
-
<title>Inbox</title>
|
8
|
-
<style type="text/css">
|
9
|
-
body {
|
10
|
-
background:#eee;
|
11
|
-
}
|
12
|
-
table {
|
13
|
-
border: 1px #999 solid;
|
14
|
-
border-collapse: collapse;
|
15
|
-
}
|
16
|
-
th, td {
|
17
|
-
border: 1px #999 solid;
|
18
|
-
padding: 6px 12px;
|
19
|
-
}
|
20
|
-
th {
|
21
|
-
background: #ccc;
|
22
|
-
}
|
23
|
-
td {
|
24
|
-
background: white;
|
25
|
-
}
|
26
|
-
</style>
|
27
|
-
</head>
|
28
|
-
<body>
|
29
|
-
<h1>Inbox</h1>
|
30
|
-
<table>
|
31
|
-
<thead>
|
32
|
-
<tr>
|
33
|
-
<th>Date</th>
|
34
|
-
<th>Subject</th>
|
35
|
-
<th>From</th>
|
36
|
-
<th>To</th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
|
40
|
-
<tbody>
|
41
|
-
<!-- ADD -->
|
42
|
-
|
43
|
-
</tbody>
|
44
|
-
</table>
|
45
|
-
</body>
|
46
|
-
</html>
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<link rel="index" href="./index.html" />
|
7
|
+
<title>Inbox</title>
|
8
|
+
<style type="text/css">
|
9
|
+
body {
|
10
|
+
background:#eee;
|
11
|
+
}
|
12
|
+
table {
|
13
|
+
border: 1px #999 solid;
|
14
|
+
border-collapse: collapse;
|
15
|
+
}
|
16
|
+
th, td {
|
17
|
+
border: 1px #999 solid;
|
18
|
+
padding: 6px 12px;
|
19
|
+
}
|
20
|
+
th {
|
21
|
+
background: #ccc;
|
22
|
+
}
|
23
|
+
td {
|
24
|
+
background: white;
|
25
|
+
}
|
26
|
+
</style>
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
<h1>Inbox</h1>
|
30
|
+
<table>
|
31
|
+
<thead>
|
32
|
+
<tr>
|
33
|
+
<th>Date</th>
|
34
|
+
<th>Subject</th>
|
35
|
+
<th>From</th>
|
36
|
+
<th>To</th>
|
37
|
+
</tr>
|
38
|
+
</thead>
|
39
|
+
|
40
|
+
<tbody>
|
41
|
+
<!-- ADD -->
|
42
|
+
|
43
|
+
</tbody>
|
44
|
+
</table>
|
45
|
+
</body>
|
46
|
+
</html>
|
@@ -1,8 +1,8 @@
|
|
1
|
-
<!-- ADD -->
|
2
|
-
|
3
|
-
<tr>
|
4
|
-
<td><%= mail[:date].strftime("%Y-%m-%d %H:%M:%S") %></td>
|
5
|
-
<td><a href="<%=h mail[:file] %>"><%=h mail[:subject] %></a></td>
|
6
|
-
<td><%=h mail[:sender] %></td>
|
7
|
-
<td><%=h mail[:recipients].to_a.join(",") %></td>
|
8
|
-
</tr>
|
1
|
+
<!-- ADD -->
|
2
|
+
|
3
|
+
<tr>
|
4
|
+
<td><%= mail[:date].strftime("%Y-%m-%d %H:%M:%S") %></td>
|
5
|
+
<td><a href="<%=h mail[:file] %>"><%=h mail[:subject] %></a></td>
|
6
|
+
<td><%=h mail[:sender] %></td>
|
7
|
+
<td><%=h mail[:recipients].to_a.join(",") %></td>
|
8
|
+
</tr>
|
data/templates/html/mail.erb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
-
<head>
|
5
|
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
-
<link rel="index" href="./index.html" />
|
7
|
-
<title><%=h mail[:subject] %> (<%= mail[:date].to_s %>)</title>
|
8
|
-
</head>
|
9
|
-
<body style="background:#eee">
|
10
|
-
<h1 id="subject"><%=h mail[:subject] %></h1>
|
11
|
-
<div><p id="date" style="font-size:0.8em;"><%= mail[:date].to_s %></div>
|
12
|
-
<div id="source" style="border: solid 1px #666; background:white; padding:2em;">
|
13
|
-
<p><%= mail[:source] %></p>
|
14
|
-
</div>
|
15
|
-
</body>
|
16
|
-
</html>
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<link rel="index" href="./index.html" />
|
7
|
+
<title><%=h mail[:subject] %> (<%= mail[:date].to_s %>)</title>
|
8
|
+
</head>
|
9
|
+
<body style="background:#eee">
|
10
|
+
<h1 id="subject"><%=h mail[:subject] %></h1>
|
11
|
+
<div><p id="date" style="font-size:0.8em;"><%= mail[:date].to_s %></div>
|
12
|
+
<div id="source" style="border: solid 1px #666; background:white; padding:2em;">
|
13
|
+
<p><%= mail[:source] %></p>
|
14
|
+
</div>
|
15
|
+
</body>
|
16
|
+
</html>
|
@@ -1,10 +1,10 @@
|
|
1
|
-
ServerName: mocksmtpd
|
2
|
-
Port: 25
|
3
|
-
RequestTimeout: 120
|
4
|
-
LineLengthLimit: 1024
|
5
|
-
LogLevel: INFO
|
6
|
-
|
7
|
-
LogFile: ./log/mocksmtpd.log
|
8
|
-
PidFile: ./log/mocksmtpd.pid
|
9
|
-
InboxDir: ./inbox
|
10
|
-
Umask: 2
|
1
|
+
ServerName: mocksmtpd
|
2
|
+
Port: 25
|
3
|
+
RequestTimeout: 120
|
4
|
+
LineLengthLimit: 1024
|
5
|
+
LogLevel: INFO
|
6
|
+
|
7
|
+
LogFile: ./log/mocksmtpd.log
|
8
|
+
PidFile: ./log/mocksmtpd.pid
|
9
|
+
InboxDir: ./inbox
|
10
|
+
Umask: 2
|
data/test/mocksmtpd_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
-
|
3
|
-
require "test/unit"
|
4
|
-
class MocksmtpdTest < Test::Unit::TestCase
|
5
|
-
end
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
class MocksmtpdTest < Test::Unit::TestCase
|
5
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require File.dirname(__FILE__) + '/../lib/mocksmtpd'
|
3
|
-
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/mocksmtpd'
|
3
|
+
|
metadata
CHANGED
@@ -1,78 +1,69 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: boomerang-mocksmtpd
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
7
|
-
|
8
|
-
autorequire:
|
6
|
+
authors:
|
7
|
+
- BB
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
|
12
|
-
date: 2008-11-08 00:00:00 +01:00
|
13
|
-
default_executable: mocksmtpd
|
11
|
+
date: 2008-11-08 00:00:00.000000000 Z
|
14
12
|
dependencies: []
|
15
|
-
|
16
13
|
description: Mock SMTP server for development/testing.
|
17
14
|
email: b@gmail.com
|
18
|
-
executables:
|
19
|
-
|
15
|
+
executables:
|
16
|
+
- mocksmtpd
|
20
17
|
extensions: []
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
- templates/mocksmtpd.conf.erb
|
38
|
-
has_rdoc: true
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README
|
20
|
+
- ChangeLog
|
21
|
+
files:
|
22
|
+
- ChangeLog
|
23
|
+
- README
|
24
|
+
- Rakefile
|
25
|
+
- bin/mocksmtpd
|
26
|
+
- lib/mocksmtpd.rb
|
27
|
+
- lib/smtpserver.rb
|
28
|
+
- templates/html/index.erb
|
29
|
+
- templates/html/index_entry.erb
|
30
|
+
- templates/html/mail.erb
|
31
|
+
- templates/mocksmtpd.conf.erb
|
32
|
+
- test/mocksmtpd_test.rb
|
33
|
+
- test/test_helper.rb
|
39
34
|
homepage: http://github.com/boomerang/mocksmtpd/
|
40
35
|
licenses: []
|
41
|
-
|
42
|
-
post_install_message:
|
43
|
-
rdoc_options:
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
require_paths:
|
57
|
-
|
58
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
-
requirements:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
-
|
67
|
-
|
68
|
-
version: "0"
|
69
|
-
version:
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- "--title"
|
40
|
+
- mocksmtpd documentation
|
41
|
+
- "--charset"
|
42
|
+
- utf-8
|
43
|
+
- "--opname"
|
44
|
+
- index.html
|
45
|
+
- "--line-numbers"
|
46
|
+
- "--main"
|
47
|
+
- README
|
48
|
+
- "--inline-source"
|
49
|
+
- "--exclude"
|
50
|
+
- "^(examples|extras)/"
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
70
63
|
requirements: []
|
71
|
-
|
72
|
-
|
73
|
-
rubygems_version: 1.3.5
|
74
|
-
signing_key:
|
64
|
+
rubygems_version: 3.3.26
|
65
|
+
signing_key:
|
75
66
|
specification_version: 2
|
76
67
|
summary: Mock SMTP server for development/testing.
|
77
|
-
test_files:
|
78
|
-
|
68
|
+
test_files:
|
69
|
+
- test/mocksmtpd_test.rb
|