malm 0.0.4 → 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.
- data/Gemfile +5 -0
- data/Gemfile.lock +24 -0
- data/README.md +37 -0
- data/VERSION +1 -1
- data/bin/malm +31 -35
- data/lib/malm/message_db.rb +33 -0
- data/lib/malm/smtp_server.rb +95 -0
- data/lib/malm/web.rb +63 -0
- data/lib/malm.rb +42 -0
- data/malm.gemspec +34 -8
- data/spec/bin/malm_test_message +206 -9
- data/web/static/css/style.css +136 -0
- data/web/static/favicon.ico +0 -0
- data/web/static/index.html +35 -0
- data/web/static/js/backbone-min.js +32 -0
- data/web/static/js/backbone.js +1149 -0
- data/web/static/js/jquery-1.6.2.js +8981 -0
- data/web/static/js/jquery-1.6.2.min.js +18 -0
- data/web/views/hello_world.coffee +2 -0
- metadata +152 -135
- data/lib/malm_smtp_server.rb +0 -93
- data/lib/malm_web.rb +0 -20
- data/lib/message_db.rb +0 -31
data/Gemfile
CHANGED
@@ -4,6 +4,11 @@ gem "json", "1.5.3"
|
|
4
4
|
gem "clamp", "0.2.1"
|
5
5
|
gem "sinatra", "1.2.6"
|
6
6
|
gem "thin", "1.2.11"
|
7
|
+
gem "mail", "2.3.0"
|
8
|
+
gem "therubyracer", "0.9.2"
|
9
|
+
gem "execjs", "1.2.0"
|
10
|
+
gem "coffee-script", "2.2.0"
|
11
|
+
gem "daemons", "1.1.4"
|
7
12
|
|
8
13
|
group :development do
|
9
14
|
gem "rspec", "~> 2.3.0"
|
data/Gemfile.lock
CHANGED
@@ -2,15 +2,30 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
clamp (0.2.1)
|
5
|
+
coffee-script (2.2.0)
|
6
|
+
coffee-script-source
|
7
|
+
execjs
|
8
|
+
coffee-script-source (1.1.1)
|
5
9
|
daemons (1.1.4)
|
6
10
|
diff-lcs (1.1.2)
|
7
11
|
eventmachine (0.12.10)
|
12
|
+
execjs (1.2.0)
|
13
|
+
multi_json (~> 1.0)
|
8
14
|
git (1.2.5)
|
15
|
+
i18n (0.6.0)
|
9
16
|
jeweler (1.6.4)
|
10
17
|
bundler (~> 1.0)
|
11
18
|
git (>= 1.2.5)
|
12
19
|
rake
|
13
20
|
json (1.5.3)
|
21
|
+
libv8 (3.3.10.2)
|
22
|
+
mail (2.3.0)
|
23
|
+
i18n (>= 0.4.0)
|
24
|
+
mime-types (~> 1.16)
|
25
|
+
treetop (~> 1.4.8)
|
26
|
+
mime-types (1.16)
|
27
|
+
multi_json (1.0.3)
|
28
|
+
polyglot (0.3.1)
|
14
29
|
rack (1.3.1)
|
15
30
|
rake (0.9.2)
|
16
31
|
rcov (0.9.9)
|
@@ -25,11 +40,15 @@ GEM
|
|
25
40
|
sinatra (1.2.6)
|
26
41
|
rack (~> 1.1)
|
27
42
|
tilt (< 2.0, >= 1.2.2)
|
43
|
+
therubyracer (0.9.2)
|
44
|
+
libv8 (~> 3.3.10)
|
28
45
|
thin (1.2.11)
|
29
46
|
daemons (>= 1.0.9)
|
30
47
|
eventmachine (>= 0.12.6)
|
31
48
|
rack (>= 1.0.0)
|
32
49
|
tilt (1.3.2)
|
50
|
+
treetop (1.4.9)
|
51
|
+
polyglot (>= 0.3.1)
|
33
52
|
|
34
53
|
PLATFORMS
|
35
54
|
ruby
|
@@ -37,9 +56,14 @@ PLATFORMS
|
|
37
56
|
DEPENDENCIES
|
38
57
|
bundler (~> 1.0.0)
|
39
58
|
clamp (= 0.2.1)
|
59
|
+
coffee-script (= 2.2.0)
|
60
|
+
daemons (= 1.1.4)
|
61
|
+
execjs (= 1.2.0)
|
40
62
|
jeweler (~> 1.6.2)
|
41
63
|
json (= 1.5.3)
|
64
|
+
mail (= 2.3.0)
|
42
65
|
rcov
|
43
66
|
rspec (~> 2.3.0)
|
44
67
|
sinatra (= 1.2.6)
|
68
|
+
therubyracer (= 0.9.2)
|
45
69
|
thin (= 1.2.11)
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Malm
|
2
|
+
====
|
3
|
+
Easy SMTP server for local development
|
4
|
+
--------------------------------------
|
5
|
+
Malm is a super simple SMTP trap that will catch everything sent to it, not forward it on, but instead display on a local web server.
|
6
|
+
|
7
|
+
This is useful for when you're doing local development that requires your app to send mail, but you don't want to go through all the hassle of setting up a full featured mail server (and then pointing your mail client at it).
|
8
|
+
|
9
|
+
Install
|
10
|
+
-------
|
11
|
+
gem install malm
|
12
|
+
|
13
|
+
Basic Usage
|
14
|
+
-----------
|
15
|
+
The following command starts Malm up. Running on it's defaults of listening for SMTP on port 2525, client web app running on port 4567, and starting as a process in the foreground
|
16
|
+
|
17
|
+
malm
|
18
|
+
|
19
|
+
If you want to start up on regular SMTP port 25, you'll probably need to run it as sudo
|
20
|
+
|
21
|
+
sudo malm -p 25
|
22
|
+
|
23
|
+
For more info try
|
24
|
+
|
25
|
+
sudo malm --help
|
26
|
+
|
27
|
+
Viewing Messages
|
28
|
+
----------------
|
29
|
+
Once it's up and running, it works just like any other SMTP server - your app sends it mail, then happily goes about it's business. To view the mail messages Malm has picked up, point your web browser at [http://localhost:4567](http://localhost:4567)
|
30
|
+
|
31
|
+
Who the hell?
|
32
|
+
-------------
|
33
|
+
I blame [@madlep](https://twitter.com/#!/madlep)
|
34
|
+
|
35
|
+
Contributing
|
36
|
+
------------
|
37
|
+
Fork + pull request. Nice and easy.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
data/bin/malm
CHANGED
@@ -1,52 +1,48 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'message_db'
|
3
|
+
require 'malm'
|
4
|
+
require 'clamp'
|
5
|
+
require 'daemons'
|
7
6
|
|
8
7
|
class MalmCommand < Clamp::Command
|
8
|
+
option "--start", :flag, "Start malm as a daemon process. PID will be written to '<PID DIRECTORY>/malm-<SMTP PORT>-<WEB PORT>.pid'"
|
9
|
+
option "--stop", :flag, "Stop malm running as a daemon process. Process id '<PID DIRECTORY>/malm-<SMTP PORT>-<WEB PORT>.pid' will be stopped"
|
10
|
+
option "--restart", :flag, "Restart malm running as a daemon process"
|
11
|
+
option "--piddir", "PID DIRECTORY", "Where to put pids", :default => "/var/run"
|
9
12
|
option ["-l", "--log"], "FILE", "file to log mail messages to (optional)"
|
10
|
-
|
11
|
-
option ["-p", "--stmpport"], "STMP PORT", "SMTP port to listen on", :default => 2525 do |port|
|
13
|
+
option ["-p", "--smtpport"], "SMTP PORT", "SMTP port to listen on", :default => 2525 do |port|
|
12
14
|
Integer(port)
|
13
15
|
end
|
14
|
-
|
15
16
|
option ["-w", "--webport"], "WEB PORT", "Port for client web app to view malmed messages", :default => 4567 do |port|
|
16
17
|
Integer(port)
|
17
18
|
end
|
18
19
|
|
19
|
-
def execute
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
private
|
26
|
-
def create_db
|
27
|
-
MessageDb.new
|
28
|
-
end
|
29
|
-
|
30
|
-
def run_smtp!(db)
|
31
|
-
smtp_server = MalmSMTPServer.new(stmpport)
|
32
|
-
smtp_server.mail_log = log
|
33
|
-
smtp_server.message_db = db
|
20
|
+
def execute
|
21
|
+
malm_proc = proc{
|
22
|
+
malm = Malm.new(:log => log, :smtpport => smtpport, :webport => webport)
|
23
|
+
malm.run!
|
24
|
+
}
|
34
25
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
if start? || stop? || restart?
|
27
|
+
mode = nil
|
28
|
+
mode ||= start? ? "start" : nil
|
29
|
+
mode ||= stop? ? "stop" : nil
|
30
|
+
mode ||= restart? ? "restart" : nil
|
31
|
+
|
32
|
+
daemon_options = {
|
33
|
+
:ARGV => [mode],
|
34
|
+
:dir_mode => :normal,
|
35
|
+
:dir => piddir,
|
36
|
+
:multiple => true,
|
37
|
+
:monitor => true,
|
38
|
+
:app_name => "malm-#{smtpport}-#{webport}"
|
39
|
+
}
|
40
|
+
|
41
|
+
Daemons.run_proc("malm-#{smtpport}-#{webport}", daemon_options, &malm_proc)
|
42
|
+
else
|
43
|
+
malm_proc.call
|
40
44
|
end
|
41
|
-
smtp_server
|
42
|
-
end
|
43
|
-
|
44
|
-
def run_web!(db)
|
45
|
-
MalmWeb.set :port, webport
|
46
|
-
MalmWeb.set :message_db, db
|
47
|
-
MalmWeb.run!
|
48
45
|
end
|
49
46
|
end
|
50
|
-
|
51
47
|
MalmCommand.run
|
52
48
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
class Malm
|
4
|
+
class MessageDb
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@sempahore = Mutex.new
|
8
|
+
|
9
|
+
@message_db = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(message)
|
13
|
+
@sempahore.synchronize do
|
14
|
+
message[:id] = @message_db.size
|
15
|
+
@message_db << message
|
16
|
+
@message_db.size
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_all
|
21
|
+
@sempahore.synchronize do
|
22
|
+
@message_db.dup
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def find(id)
|
27
|
+
@sempahore.synchronize do
|
28
|
+
@message_db[id].dup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# based on copy + paste from http://snippets.dzone.com/posts/show/5152
|
2
|
+
require 'gserver'
|
3
|
+
|
4
|
+
class Malm
|
5
|
+
class SMTPServer < GServer
|
6
|
+
|
7
|
+
attr_accessor :mail_log
|
8
|
+
attr_accessor :message_db
|
9
|
+
|
10
|
+
class Session
|
11
|
+
attr_accessor :data_mode, :data_mode, :email_body, :mail_from, :rcpt_to, :subject
|
12
|
+
alias :data_mode? :data_mode
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@data_mode = false
|
16
|
+
@email_body = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def serve(io)
|
22
|
+
session = Session.new
|
23
|
+
puts "Connected"
|
24
|
+
io.print "220 hello\r\n"
|
25
|
+
loop do
|
26
|
+
data = io.gets
|
27
|
+
puts ">>" + data
|
28
|
+
ok, op = process_line(data, session)
|
29
|
+
puts "<<" + op
|
30
|
+
io.print op
|
31
|
+
break unless ok
|
32
|
+
break if io.closed?
|
33
|
+
end
|
34
|
+
begin
|
35
|
+
io.close
|
36
|
+
db_insert(session)
|
37
|
+
rescue => e
|
38
|
+
log "something screwed up..."
|
39
|
+
log e.backtrace
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_line(line, session)
|
44
|
+
if (session.data_mode?) && (line.chomp =~ /^\.$/)
|
45
|
+
session.data_mode = false
|
46
|
+
return true, "250 OK\r\n"
|
47
|
+
elsif session.data_mode?
|
48
|
+
session.email_body += line
|
49
|
+
return true, ""
|
50
|
+
elsif (line =~ /^(HELO|EHLO)/)
|
51
|
+
return true, "250 and..?\r\n"
|
52
|
+
elsif (line =~ /^QUIT/)
|
53
|
+
return false, "221 bye\r\n"
|
54
|
+
elsif (line =~ /^MAIL FROM\:/)
|
55
|
+
session.mail_from = (/^MAIL FROM\:<(.+)>.*$/).match(line)[1]
|
56
|
+
return true, "250 OK\r\n"
|
57
|
+
elsif (line =~ /^RCPT TO\:/)
|
58
|
+
session.rcpt_to = (/^RCPT TO\:<(.+)>.*$/).match(line)[1]
|
59
|
+
return true, "250 OK\r\n"
|
60
|
+
elsif (line =~ /^DATA/)
|
61
|
+
session.data_mode = true
|
62
|
+
return true, "354 Enter message, ending with \".\" on a line by itself\r\n"
|
63
|
+
else
|
64
|
+
return true, "500 ERROR\r\n"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def db_insert(session)
|
69
|
+
subject_regex = /^Subject\: (.+)$/
|
70
|
+
|
71
|
+
subject_match = subject_regex.match(session.email_body)
|
72
|
+
subject = subject_match ? subject_match[1] : ""
|
73
|
+
subject.strip!
|
74
|
+
|
75
|
+
message = {:subject => subject, :from => session.mail_from, :to => session.rcpt_to, :body => session.email_body}
|
76
|
+
|
77
|
+
@mail_log_fd.puts(message.inspect) if @mail_log_fd
|
78
|
+
@message_db.create(message) if @message_db
|
79
|
+
|
80
|
+
log("Message received: #{message.inspect}")
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
def starting
|
85
|
+
@mail_log_fd = File.open(@mail_log, "a") if @mail_log
|
86
|
+
super
|
87
|
+
end
|
88
|
+
|
89
|
+
def stopping
|
90
|
+
@mail_log_fd.close if @mail_log_fd
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
data/lib/malm/web.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'json'
|
4
|
+
require 'v8'
|
5
|
+
require 'execjs'
|
6
|
+
require 'coffee_script'
|
7
|
+
require 'mail'
|
8
|
+
|
9
|
+
class Malm
|
10
|
+
class Web < Sinatra::Base
|
11
|
+
|
12
|
+
set :public, File.join(File.dirname(__FILE__), "..", "..", "web", "static")
|
13
|
+
set :views, File.join(File.dirname(__FILE__), "..", "..", "web", "views")
|
14
|
+
|
15
|
+
get "/messages.json" do
|
16
|
+
content_type :json
|
17
|
+
settings.message_db.find_all.map{|m|
|
18
|
+
m = m.dup
|
19
|
+
m.delete(:body)
|
20
|
+
m[:body_urls] = {:html => url("/messages/#{m[:id]}/body.html"), :text => url("/messages/#{m[:id]}/body.text")}
|
21
|
+
m
|
22
|
+
}.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
get "/messages/:id.json" do
|
26
|
+
content_type :json
|
27
|
+
find_message(params[:id]).to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
get "/messages/:id/body.:type" do
|
31
|
+
render_message(params[:id], params[:type])
|
32
|
+
end
|
33
|
+
|
34
|
+
get "/coffee/:script.coffee" do
|
35
|
+
content_type "text/javascript"
|
36
|
+
coffee params[:script].to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def find_message(id)
|
41
|
+
id = Integer(id)
|
42
|
+
settings.message_db.find(id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_message(id, type)
|
46
|
+
content_type type
|
47
|
+
|
48
|
+
supported = ["text", "html"]
|
49
|
+
unless supported.include?(type.to_s)
|
50
|
+
halt 415, "don't know how to display message #{id} as #{type}. Try one of #{supported.join(",")}"
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
msg_obj = find_message(id)
|
55
|
+
if msg_obj
|
56
|
+
Mail::Message.new(msg_obj[:body]).send("#{type}_part".to_sym).body.to_s
|
57
|
+
else
|
58
|
+
status 404
|
59
|
+
"don't know about message #{id}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/malm.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'malm/message_db'
|
2
|
+
require 'malm/smtp_server'
|
3
|
+
require 'malm/web'
|
4
|
+
|
5
|
+
class Malm
|
6
|
+
attr_accessor :log, :smtpport, :webport
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
options.each{|k,v| send("#{k}=", v)}
|
10
|
+
end
|
11
|
+
|
12
|
+
def run!
|
13
|
+
create_db
|
14
|
+
run_smtp!
|
15
|
+
run_web!
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def create_db
|
20
|
+
@db = Malm::MessageDb.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_smtp!
|
24
|
+
smtp_server = Malm::SMTPServer.new(@smtpport)
|
25
|
+
smtp_server.mail_log = @log
|
26
|
+
smtp_server.message_db = @db
|
27
|
+
|
28
|
+
begin
|
29
|
+
smtp_server.start
|
30
|
+
rescue Errno::EACCES
|
31
|
+
STDERR.puts("Don't have permission to start SMTP server on port #{smtpport}. Maybe run with sudo?")
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
smtp_server
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_web!
|
38
|
+
Malm::Web.set :port, @webport
|
39
|
+
Malm::Web.set :message_db, @db
|
40
|
+
Malm::Web.run!
|
41
|
+
end
|
42
|
+
end
|
data/malm.gemspec
CHANGED
@@ -5,17 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{malm}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["madlep"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-23}
|
13
13
|
s.default_executable = %q{malm}
|
14
14
|
s.description = %q{SMTP server with web interface for easy local development. Sets up a little mail server that you can send messages to, and provides a web front end to let you see what your app did.}
|
15
15
|
s.email = %q{julian.doherty.ml@gmail.com}
|
16
16
|
s.executables = ["malm"]
|
17
17
|
s.extra_rdoc_files = [
|
18
|
-
"LICENSE.txt"
|
18
|
+
"LICENSE.txt",
|
19
|
+
"README.md"
|
19
20
|
]
|
20
21
|
s.files = [
|
21
22
|
".document",
|
@@ -23,21 +24,31 @@ Gem::Specification.new do |s|
|
|
23
24
|
"Gemfile",
|
24
25
|
"Gemfile.lock",
|
25
26
|
"LICENSE.txt",
|
27
|
+
"README.md",
|
26
28
|
"Rakefile",
|
27
29
|
"VERSION",
|
28
30
|
"bin/malm",
|
29
|
-
"lib/
|
30
|
-
"lib/
|
31
|
-
"lib/
|
31
|
+
"lib/malm.rb",
|
32
|
+
"lib/malm/message_db.rb",
|
33
|
+
"lib/malm/smtp_server.rb",
|
34
|
+
"lib/malm/web.rb",
|
32
35
|
"malm.gemspec",
|
33
36
|
"spec/bin/malm_test_message",
|
34
37
|
"spec/help_spec.rb",
|
35
|
-
"spec/spec_helper.rb"
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"web/static/css/style.css",
|
40
|
+
"web/static/favicon.ico",
|
41
|
+
"web/static/index.html",
|
42
|
+
"web/static/js/backbone-min.js",
|
43
|
+
"web/static/js/backbone.js",
|
44
|
+
"web/static/js/jquery-1.6.2.js",
|
45
|
+
"web/static/js/jquery-1.6.2.min.js",
|
46
|
+
"web/views/hello_world.coffee"
|
36
47
|
]
|
37
48
|
s.homepage = %q{http://github.com/madlep/malm}
|
38
49
|
s.licenses = ["MIT"]
|
39
50
|
s.require_paths = ["lib"]
|
40
|
-
s.rubygems_version = %q{1.
|
51
|
+
s.rubygems_version = %q{1.6.2}
|
41
52
|
s.summary = %q{Easy SMTP server for local development}
|
42
53
|
|
43
54
|
if s.respond_to? :specification_version then
|
@@ -48,6 +59,11 @@ Gem::Specification.new do |s|
|
|
48
59
|
s.add_runtime_dependency(%q<clamp>, ["= 0.2.1"])
|
49
60
|
s.add_runtime_dependency(%q<sinatra>, ["= 1.2.6"])
|
50
61
|
s.add_runtime_dependency(%q<thin>, ["= 1.2.11"])
|
62
|
+
s.add_runtime_dependency(%q<mail>, ["= 2.3.0"])
|
63
|
+
s.add_runtime_dependency(%q<therubyracer>, ["= 0.9.2"])
|
64
|
+
s.add_runtime_dependency(%q<execjs>, ["= 1.2.0"])
|
65
|
+
s.add_runtime_dependency(%q<coffee-script>, ["= 2.2.0"])
|
66
|
+
s.add_runtime_dependency(%q<daemons>, ["= 1.1.4"])
|
51
67
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
52
68
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
69
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
@@ -57,6 +73,11 @@ Gem::Specification.new do |s|
|
|
57
73
|
s.add_dependency(%q<clamp>, ["= 0.2.1"])
|
58
74
|
s.add_dependency(%q<sinatra>, ["= 1.2.6"])
|
59
75
|
s.add_dependency(%q<thin>, ["= 1.2.11"])
|
76
|
+
s.add_dependency(%q<mail>, ["= 2.3.0"])
|
77
|
+
s.add_dependency(%q<therubyracer>, ["= 0.9.2"])
|
78
|
+
s.add_dependency(%q<execjs>, ["= 1.2.0"])
|
79
|
+
s.add_dependency(%q<coffee-script>, ["= 2.2.0"])
|
80
|
+
s.add_dependency(%q<daemons>, ["= 1.1.4"])
|
60
81
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
61
82
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
83
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
@@ -67,6 +88,11 @@ Gem::Specification.new do |s|
|
|
67
88
|
s.add_dependency(%q<clamp>, ["= 0.2.1"])
|
68
89
|
s.add_dependency(%q<sinatra>, ["= 1.2.6"])
|
69
90
|
s.add_dependency(%q<thin>, ["= 1.2.11"])
|
91
|
+
s.add_dependency(%q<mail>, ["= 2.3.0"])
|
92
|
+
s.add_dependency(%q<therubyracer>, ["= 0.9.2"])
|
93
|
+
s.add_dependency(%q<execjs>, ["= 1.2.0"])
|
94
|
+
s.add_dependency(%q<coffee-script>, ["= 2.2.0"])
|
95
|
+
s.add_dependency(%q<daemons>, ["= 1.1.4"])
|
70
96
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
71
97
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
98
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|