malm 0.0.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "json", "1.5.3"
4
+ gem "clamp", "0.2.1"
5
+ gem "sinatra", "1.2.6"
6
+ gem "thin", "1.2.11"
7
+
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ clamp (0.2.1)
5
+ daemons (1.1.4)
6
+ diff-lcs (1.1.2)
7
+ eventmachine (0.12.10)
8
+ git (1.2.5)
9
+ jeweler (1.6.4)
10
+ bundler (~> 1.0)
11
+ git (>= 1.2.5)
12
+ rake
13
+ json (1.5.3)
14
+ rack (1.3.1)
15
+ rake (0.9.2)
16
+ rcov (0.9.9)
17
+ rspec (2.3.0)
18
+ rspec-core (~> 2.3.0)
19
+ rspec-expectations (~> 2.3.0)
20
+ rspec-mocks (~> 2.3.0)
21
+ rspec-core (2.3.1)
22
+ rspec-expectations (2.3.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.3.0)
25
+ sinatra (1.2.6)
26
+ rack (~> 1.1)
27
+ tilt (< 2.0, >= 1.2.2)
28
+ thin (1.2.11)
29
+ daemons (>= 1.0.9)
30
+ eventmachine (>= 0.12.6)
31
+ rack (>= 1.0.0)
32
+ tilt (1.3.2)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 1.0.0)
39
+ clamp (= 0.2.1)
40
+ jeweler (~> 1.6.2)
41
+ json (= 1.5.3)
42
+ rcov
43
+ rspec (~> 2.3.0)
44
+ sinatra (= 1.2.6)
45
+ thin (= 1.2.11)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 madlep
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "malm"
18
+ gem.homepage = "http://github.com/madlep/malm"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Easy SMTP server for local development}
21
+ gem.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.}
22
+ gem.email = "julian.doherty.ml@gmail.com"
23
+ gem.authors = ["madlep"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/malm ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+ require "malm_smtp_server"
4
+ require "malm_web"
5
+ require "clamp"
6
+ require 'message_db'
7
+
8
+ class MalmCommand < Clamp::Command
9
+ 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|
12
+ Integer(port)
13
+ end
14
+
15
+ option ["-w", "--webport"], "WEB PORT", "Port for client web app to view malmed messages", :default => 4567 do |port|
16
+ Integer(port)
17
+ end
18
+
19
+ def execute
20
+ db = create_db
21
+ smtp = run_smtp!(db)
22
+ web = run_web!(db)
23
+ end
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
34
+
35
+ begin
36
+ smtp_server.start
37
+ rescue Errno::EACCES
38
+ STDERR.puts("Don't have permission to start SMTP server on port #{stmpport}. Maybe run with sudo?")
39
+ exit 1
40
+ 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
+ end
49
+ end
50
+
51
+ MalmCommand.run
52
+
@@ -0,0 +1,89 @@
1
+ # based on copy + paste from http://snippets.dzone.com/posts/show/5152
2
+ require 'gserver'
3
+
4
+ class MalmSMTPServer < GServer
5
+
6
+ attr_accessor :mail_log
7
+ attr_accessor :message_db
8
+
9
+ class Session
10
+ attr_accessor :data_mode, :data_mode, :email_body, :mail_from, :rcpt_to, :subject
11
+ alias :data_mode? :data_mode
12
+
13
+ def initialize
14
+ @data_mode = false
15
+ @email_body = ""
16
+ end
17
+
18
+ end
19
+
20
+ def serve(io)
21
+ session = Session.new
22
+ puts "Connected"
23
+ io.print "220 hello\r\n"
24
+ loop do
25
+ if IO.select([io], nil, nil, 0.1)
26
+ data = io.readpartial(4096)
27
+ puts ">>" + data
28
+ ok, op = process_line(data, session)
29
+ break unless ok
30
+ puts "<<" + op
31
+ io.print op
32
+ end
33
+ break if io.closed?
34
+ end
35
+ db_insert(session)
36
+ io.print "221 bye\r\n"
37
+ io.close
38
+ end
39
+
40
+ def process_line(line, session)
41
+ if (session.data_mode?) && (line.chomp =~ /^\.$/)
42
+ session.data_mode = false
43
+ return true, "250 OK\r\n"
44
+ elsif session.data_mode?
45
+ session.email_body += line
46
+ return true, ""
47
+ elsif (line =~ /^(HELO|EHLO)/)
48
+ return true, "250 and..?\r\n"
49
+ elsif (line =~ /^QUIT/)
50
+ return false, "bye\r\n"
51
+ elsif (line =~ /^MAIL FROM\:/)
52
+ session.mail_from = (/^MAIL FROM\:<(.+)>.*$/).match(line)[1]
53
+ return true, "250 OK\r\n"
54
+ elsif (line =~ /^RCPT TO\:/)
55
+ session.rcpt_to = (/^RCPT TO\:<(.+)>.*$/).match(line)[1]
56
+ return true, "250 OK\r\n"
57
+ elsif (line =~ /^DATA/)
58
+ session.data_mode = true
59
+ return true, "354 Enter message, ending with \".\" on a line by itself\r\n"
60
+ else
61
+ return true, "500 ERROR\r\n"
62
+ end
63
+ end
64
+
65
+ def db_insert(session)
66
+ subject_regex = /^Subject\: (.+)$/
67
+
68
+ subject = subject_regex.match(session.email_body)[1] || ""
69
+ subject.strip!
70
+
71
+ message = {:subject => subject, :from => session.mail_from, :to => session.rcpt_to, :body => session.email_body}
72
+
73
+ @mail_log_fd.puts(message.inspect) if @mail_log_fd
74
+ @message_db.create(message) if @message_db
75
+
76
+ log("Message received: #{message.inspect}")
77
+ end
78
+
79
+ protected
80
+ def starting
81
+ @mail_log_fd = File.open(@mail_log, "a") if @mail_log
82
+ super
83
+ end
84
+
85
+ def stopping
86
+ @mail_log_fd.close if @mail_log_fd
87
+ super
88
+ end
89
+ end
data/lib/malm_web.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'thin'
2
+ require 'sinatra/base'
3
+ require 'json'
4
+
5
+ class MalmWeb < Sinatra::Base
6
+ get("/") do
7
+ "Hello World\n"
8
+ end
9
+
10
+ get ("/messages") do
11
+ content_type :json
12
+ settings.message_db.find_all.to_json
13
+ end
14
+ end
data/lib/message_db.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'thread'
2
+
3
+ class MessageDb
4
+
5
+ def initialize
6
+ @sempahore = Mutex.new
7
+
8
+ @message_db = []
9
+ end
10
+
11
+ def create(message)
12
+ @sempahore.synchronize do
13
+ @message_db << message
14
+ @message_db.size
15
+ end
16
+ end
17
+
18
+ def find_all
19
+ @sempahore.synchronize do
20
+ @message_db.dup
21
+ end
22
+ end
23
+
24
+ end
data/malm.gemspec ADDED
@@ -0,0 +1,74 @@
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{malm}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{madlep}]
12
+ s.date = %q{2011-07-14}
13
+ 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.}
14
+ s.email = %q{julian.doherty.ml@gmail.com}
15
+ s.executables = [%q{malm}]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/malm",
28
+ "lib/malm_smtp_server.rb",
29
+ "lib/malm_web.rb",
30
+ "lib/message_db.rb",
31
+ "malm.gemspec",
32
+ "spec/help_spec.rb",
33
+ "spec/spec_helper.rb"
34
+ ]
35
+ s.homepage = %q{http://github.com/madlep/malm}
36
+ s.licenses = [%q{MIT}]
37
+ s.require_paths = [%q{lib}]
38
+ s.rubygems_version = %q{1.8.5}
39
+ s.summary = %q{Easy SMTP server for local development}
40
+
41
+ if s.respond_to? :specification_version then
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ s.add_runtime_dependency(%q<json>, ["= 1.5.3"])
46
+ s.add_runtime_dependency(%q<clamp>, ["= 0.2.1"])
47
+ s.add_runtime_dependency(%q<sinatra>, ["= 1.2.6"])
48
+ s.add_runtime_dependency(%q<thin>, ["= 1.2.11"])
49
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
52
+ s.add_development_dependency(%q<rcov>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<json>, ["= 1.5.3"])
55
+ s.add_dependency(%q<clamp>, ["= 0.2.1"])
56
+ s.add_dependency(%q<sinatra>, ["= 1.2.6"])
57
+ s.add_dependency(%q<thin>, ["= 1.2.11"])
58
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<json>, ["= 1.5.3"])
65
+ s.add_dependency(%q<clamp>, ["= 0.2.1"])
66
+ s.add_dependency(%q<sinatra>, ["= 1.2.6"])
67
+ s.add_dependency(%q<thin>, ["= 1.2.11"])
68
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
69
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
70
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
71
+ s.add_dependency(%q<rcov>, [">= 0"])
72
+ end
73
+ end
74
+
data/spec/help_spec.rb ADDED
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Help" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'help'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: malm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - madlep
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &2155923580 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 1.5.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2155923580
25
+ - !ruby/object:Gem::Dependency
26
+ name: clamp
27
+ requirement: &2155917200 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.1
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2155917200
36
+ - !ruby/object:Gem::Dependency
37
+ name: sinatra
38
+ requirement: &2153512200 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - =
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.6
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2153512200
47
+ - !ruby/object:Gem::Dependency
48
+ name: thin
49
+ requirement: &2153511600 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - =
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.11
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *2153511600
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &2153511100 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.3.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2153511100
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: &2153510460 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.0.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *2153510460
80
+ - !ruby/object:Gem::Dependency
81
+ name: jeweler
82
+ requirement: &2153509960 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.6.2
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *2153509960
91
+ - !ruby/object:Gem::Dependency
92
+ name: rcov
93
+ requirement: &2153509300 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *2153509300
102
+ description: SMTP server with web interface for easy local development. Sets up a
103
+ little mail server that you can send messages to, and provides a web front end to
104
+ let you see what your app did.
105
+ email: julian.doherty.ml@gmail.com
106
+ executables:
107
+ - malm
108
+ extensions: []
109
+ extra_rdoc_files:
110
+ - LICENSE.txt
111
+ files:
112
+ - .document
113
+ - .rspec
114
+ - Gemfile
115
+ - Gemfile.lock
116
+ - LICENSE.txt
117
+ - Rakefile
118
+ - VERSION
119
+ - bin/malm
120
+ - lib/malm_smtp_server.rb
121
+ - lib/malm_web.rb
122
+ - lib/message_db.rb
123
+ - malm.gemspec
124
+ - spec/help_spec.rb
125
+ - spec/spec_helper.rb
126
+ homepage: http://github.com/madlep/malm
127
+ licenses:
128
+ - MIT
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ segments:
140
+ - 0
141
+ hash: -4176688025386378385
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 1.8.5
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: Easy SMTP server for local development
154
+ test_files: []