better_opener 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in better_opener.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,34 @@
1
+ = Better Opener
2
+
3
+ Preview mails and other notifications (sms for instance) in your browser
4
+ instead of actually sending them out. Inspired and almost similar to the
5
+ Letter Opener by Ryan Bates Better Opener this gem tries to be *better* by being
6
+ more universal and displaying desktop notifications (with the chrome plugin).
7
+
8
+ == Setup
9
+
10
+ Add the gem to your development environment and run the <tt>bundle install</tt> command to install it.
11
+
12
+ gem "better_opener", :group => :development
13
+
14
+ Set the delivery method in <tt>config/environments/development.rb</tt>
15
+
16
+ config.action_mailer.delivery_method = :letter_opener
17
+
18
+ Finally install the bundled Sinatra app as a subdirectory of your app by editing your <tt>config.ru</tt>:
19
+
20
+ map "/notification" do
21
+ run BetterOpener::Server
22
+ end
23
+
24
+
25
+
26
+ == Chrome Plugin
27
+
28
+ To take full advantage and get actual notifications, you will want to install
29
+ the accompanying chrome plugin. Just point it to the notification address you
30
+ set up above.
31
+
32
+
33
+
34
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "better_opener/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "better_opener"
7
+ s.version = BetterOpener::VERSION
8
+ s.authors = ["Kai Rubarth"]
9
+ s.email = ["kai@doxter.de"]
10
+ s.homepage = "http://github.com/learnjin/better_opener"
11
+ s.summary = %q{A better way of Previewing mail in your browser instead of sending it.}
12
+ s.description = %q{When mails or messages are sent from your application, Better Opener lets you preview the rendered messages in your browser instead of delivering them.}
13
+
14
+ s.rubyforge_project = "better_opener"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "sinatra-contrib"
23
+
24
+ s.add_dependency "data_mapper", ">= 1.2"
25
+ s.add_dependency "dm-sqlite-adapter"
26
+ s.add_dependency "tilt"
27
+ s.add_dependency "haml"
28
+
29
+ end
30
+
31
+
32
+
data/config.ru ADDED
@@ -0,0 +1,4 @@
1
+ require 'better_opener'
2
+
3
+ run BetterOpener::Server
4
+
@@ -0,0 +1,87 @@
1
+ require "better_opener/version"
2
+
3
+ require 'data_mapper'
4
+ require 'time'
5
+ require 'tilt'
6
+ require 'rack/mime'
7
+
8
+ module BetterOpener
9
+
10
+ class Notification
11
+ include DataMapper::Resource
12
+ property :id, Serial
13
+ property :subject, String
14
+ property :body, Text
15
+ property :created_at, DateTime
16
+ property :category, String
17
+ end
18
+
19
+ extend self
20
+
21
+ def db=(server)
22
+ @db = server
23
+ end
24
+
25
+ def db
26
+ return @db if @db
27
+ self.db = DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/development.db")
28
+ DataMapper.auto_upgrade!
29
+ self.db
30
+ end
31
+
32
+ def get_all_notifications
33
+ db && BetterOpener::Notification.all(:order => [:id.desc])
34
+ end
35
+
36
+ def get_notification(id)
37
+ db && BetterOpener::Notification.get(id)
38
+ end
39
+
40
+
41
+ def add_notification(category, subject, body)
42
+ db
43
+ n = BetterOpener::Notification.new :category => category, :subject => subject, :body => body, :created_at => Time.now
44
+ n.save
45
+ end
46
+
47
+ def email_template_path
48
+ File.expand_path('../better_opener/email.html.erb', __FILE__)
49
+ end
50
+
51
+ def email_template
52
+ Tilt.new(email_template_path)
53
+ end
54
+
55
+ def render_email(name, mail, format = nil)
56
+ body_part = mail
57
+
58
+ if mail.multipart?
59
+ content_type = Rack::Mime.mime_type(format)
60
+ body_part = mail.parts.find { |part| part.content_type.match(content_type) } || mail.parts.first
61
+ end
62
+
63
+ email_template.render(Object.new, :name => name, :mail => mail, :body_part => body_part)
64
+ end
65
+
66
+
67
+ def sms_template_path
68
+ File.expand_path('../better_opener/sms.html.erb', __FILE__)
69
+ end
70
+
71
+ def sms_template
72
+ Tilt.new(sms_template_path)
73
+ end
74
+
75
+ def render_sms(name, sms, format = nil)
76
+ sms_template.render(Object.new, :name => name, :sms => sms)
77
+ end
78
+
79
+
80
+ end
81
+
82
+ require 'better_opener/delivery_method'
83
+ require 'better_opener/server'
84
+ require "better_opener/railtie" if defined? Rails
85
+ require "better_opener/sms_gateway_adapter" if defined? SmsGateway
86
+
87
+
@@ -0,0 +1,13 @@
1
+ module BetterOpener
2
+ class DeliveryMethod
3
+
4
+ def initialize(options = {})
5
+ end
6
+
7
+ def deliver!(mail)
8
+ BetterOpener.add_notification("email", mail.subject, BetterOpener.render_email('NAME', mail))
9
+ end
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,88 @@
1
+ <head>
2
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= body_part.charset %>" />
3
+ </head>
4
+ <style type="text/css">
5
+ #message_headers {
6
+ position: absolute;
7
+ top: 0px;
8
+ left: 0;
9
+ width: 100%;
10
+ height: 85px;
11
+ padding: 10px 0 0 0;
12
+ margin: 0;
13
+ background: #fff;
14
+ font-size: 12px;
15
+ font-family: "Lucida Grande";
16
+ border-bottom: 1px solid #dedede;
17
+ overflow: hidden;
18
+ }
19
+
20
+ #message_headers dl {
21
+ margin: 0;
22
+ padding: 0;
23
+ }
24
+
25
+ #message_headers dt {
26
+ width: 60px;
27
+ padding: 1px;
28
+ float: left;
29
+ text-align: right;
30
+ font-weight: bold;
31
+ color: #7f7f7f;
32
+ }
33
+
34
+ #message_headers dd {
35
+ margin-left: 70px;
36
+ padding: 1px;
37
+ }
38
+
39
+ #message_headers p.alternate {
40
+ position: absolute;
41
+ top: 0;
42
+ right: 15px;
43
+ }
44
+
45
+ #message_headers p.alternate a {
46
+ color: #09c;
47
+ }
48
+
49
+ pre#message_body {
50
+ padding: 10px;
51
+ white-space: pre-wrap;
52
+ }
53
+
54
+ body {
55
+ margin-top: 96px;
56
+ }
57
+ </style>
58
+ <div id="message_headers">
59
+ <dl>
60
+ <dt>From:</dt>
61
+ <dd><%= mail.from %></dd>
62
+
63
+ <dt>Subject:</dt>
64
+ <dd><strong><%= mail.subject %></strong></dd>
65
+
66
+ <dt>Date:</dt>
67
+ <dd><%= Time.now.strftime("%b %e, %Y %I:%M:%S %p %Z") %></dd>
68
+
69
+ <dt>To:</dt>
70
+ <dd><%= mail.to %></dd>
71
+ </dl>
72
+
73
+ <% if mail.multipart? %>
74
+ <p class="alternate">
75
+ <% if body_part.content_type && body_part.content_type.match(/text\/html/) %>
76
+ <a href="<%= name %>.txt">View plain text version</a>
77
+ <% else %>
78
+ <a href="<%= name %>.html">View HTML version</a>
79
+ <% end %>
80
+ </p>
81
+ <% end %>
82
+ </div>
83
+
84
+ <% if body_part.content_type && body_part.content_type.match(/text\/html/) %>
85
+ <%= body_part.body %>
86
+ <% else %>
87
+ <pre id="message_body"><%= body_part.body %></pre>
88
+ <% end %>
@@ -0,0 +1,8 @@
1
+ module BetterOpener
2
+ class Railtie < Rails::Railtie
3
+ initializer "better_opener.add_delivery_method" do
4
+ ActionMailer::Base.add_delivery_method :better_opener, BetterOpener::DeliveryMethod
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,60 @@
1
+ require 'rubygems' if RUBY_VERSION < '1.9'
2
+ require 'sinatra'
3
+ #require 'sinatra/reloader' if development?
4
+ require 'haml'
5
+ require 'data_mapper'
6
+ require 'better_opener'
7
+
8
+ module BetterOpener
9
+
10
+ class Server < Sinatra::Base
11
+ #configure :development do
12
+ # register Sinatra::Reloader
13
+ #nd
14
+
15
+ helpers do
16
+ include Rack::Utils
17
+ alias_method :h, :escape_html
18
+
19
+ def url_path(*path_parts)
20
+ path = [ path_prefix, path_parts ].join("/").squeeze('/')
21
+ request.scheme + "://" + request.host_with_port + path
22
+ end
23
+ alias_method :u, :url_path
24
+
25
+ def path_prefix
26
+ request.script_name
27
+ end
28
+
29
+ end
30
+
31
+ dir = File.dirname(File.expand_path(__FILE__))
32
+
33
+ set :views, "#{dir}/server/views"
34
+ set :public, "#{dir}/server/public"
35
+ set :static, true
36
+
37
+ get "/" do
38
+ @messages = BetterOpener.get_all_notifications
39
+ haml :index
40
+ end
41
+
42
+ get "/purge" do
43
+ BetterOpener::Notification.all.destroy
44
+ redirect u('/')
45
+ end
46
+
47
+ get "/:id" do
48
+ @message = BetterOpener.get_notification(params[:id])
49
+ @message.body
50
+ end
51
+
52
+ get "/feed/atom", :provides => [:atom] do
53
+ @messages = BetterOpener.get_all_notifications
54
+ content_type 'application/rss+xml'
55
+ haml(:atom, :format => :xhtml, :escape_html => true, :layout => false)
56
+ end
57
+
58
+ end
59
+ end
60
+
@@ -0,0 +1,17 @@
1
+ !!! XML
2
+ %feed{:version=> "0.3", :xmlns=> "http://purl.org/atom/ns#"}
3
+ %title Notification Outbox
4
+ %tagline Messages in your Outbox
5
+ %fullcount= @messages.size
6
+ %link{:rel=>"alternate", :href => u("/"), :type => "text/html"}
7
+ %modified= @messages.size > 0 ? @messages.first.created_at : Time.now
8
+ - for message in @messages
9
+ %entry
10
+ %title= message.subject
11
+ %summary= "#{message.subject} ..."
12
+ %link{:rel => "alternate", :href => u("/#{message.id}")}
13
+ %modified= message.created_at
14
+ %issued= message.created_at
15
+ %category= message.category
16
+ %id= message.id
17
+
@@ -0,0 +1,14 @@
1
+ %h1= "Outgoing Notifications"
2
+ %p
3
+ %a{:href => u("/purge")}= "Purge All!"
4
+
5
+ %ul
6
+ - for m in @messages
7
+ %li
8
+ = m.category + ": "
9
+ %em
10
+ %a{:href => u("/#{m.id}") }= m.subject
11
+
12
+
13
+
14
+
@@ -0,0 +1,4 @@
1
+ %h1= @message.subject
2
+ %h2= @message.category
3
+ %p= @message.body
4
+
@@ -0,0 +1,99 @@
1
+ <head>
2
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
3
+ </head>
4
+ <style type="text/css">
5
+ #message_headers {
6
+ position: absolute;
7
+ top: 0px;
8
+ left: 0;
9
+ width: 100%;
10
+ height: 65px;
11
+ padding: 10px 0 0 0;
12
+ margin: 0;
13
+ background: #fff;
14
+ font-size: 12px;
15
+ font-family: "Lucida Grande";
16
+ /*border-bottom: 1px solid #dedede;*/
17
+ overflow: hidden;
18
+ }
19
+
20
+ #message_headers dl {
21
+ margin: 0;
22
+ padding: 0;
23
+ }
24
+
25
+ #message_headers dt {
26
+ width: 60px;
27
+ padding: 1px;
28
+ float: left;
29
+ text-align: right;
30
+ font-weight: bold;
31
+ color: #7f7f7f;
32
+ }
33
+
34
+ #message_headers dd {
35
+ margin-left: 70px;
36
+ padding: 1px;
37
+ }
38
+
39
+ #message_headers p.alternate {
40
+ position: absolute;
41
+ top: 0;
42
+ right: 15px;
43
+ }
44
+
45
+ #message_headers p.alternate a {
46
+ color: #09c;
47
+ }
48
+
49
+ pre#message_body {
50
+ padding: 10px;
51
+ white-space: pre-wrap;
52
+ }
53
+
54
+ body {
55
+ margin-top: 96px;
56
+ }
57
+
58
+ #sms_body{
59
+ }
60
+
61
+ div.outcome {
62
+ background-color: #A3E6A5;
63
+ border-top-left-radius: 0;
64
+ -moz-border-radius-topleft: 0;
65
+ margin-left: 2em;
66
+ }
67
+
68
+ .message {
69
+ border: 1px solid #ccc;
70
+ border-radius: 10px;
71
+ -moz-border-radius: 10px;
72
+ padding: .5em;
73
+ margin-bottom: 1em;
74
+ width: 500px;
75
+ }
76
+
77
+ </style>
78
+ <div id="message_headers">
79
+ <dl>
80
+ <dt>From:</dt>
81
+ <dd><%= sms.from %></dd>
82
+
83
+ <dt>To:</dt>
84
+ <dd><%= sms.to %></dd>
85
+
86
+ <dt>Date:</dt>
87
+ <dd><%= Time.now.strftime("%b %e, %Y %I:%M:%S %p %Z") %></dd>
88
+
89
+ </dl>
90
+
91
+ </div>
92
+
93
+ <div id="sms_body">
94
+ <div class="outcome message">
95
+ <%= sms.text %>
96
+ </div>
97
+ </div>
98
+
99
+
@@ -0,0 +1,22 @@
1
+ require 'sms_gateway'
2
+
3
+ module SmsGateway
4
+
5
+ module Adapters
6
+ class BetterOpener
7
+
8
+ def initialize(config={})
9
+ @config = {:from => SmsGateway::Base.from }
10
+ @config.merge!(config)
11
+ end
12
+
13
+ def send_sms(sms)
14
+ options = @config.merge({:to => sms.to, :message => sms.text })
15
+ ::BetterOpener.add_notification("sms", sms.from, ::BetterOpener.render_sms('sms', sms) )
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,3 @@
1
+ module BetterOpener
2
+ VERSION = "0.0.1"
3
+ end
data/lib/test.ru ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'rack'
3
+ require 'better_opener/server'
4
+
5
+ map "/notifications" do
6
+ run BetterOpener::Server
7
+ end
8
+
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_opener
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Kai Rubarth
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-02 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra-contrib
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: data_mapper
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 11
43
+ segments:
44
+ - 1
45
+ - 2
46
+ version: "1.2"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: dm-sqlite-adapter
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: tilt
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :runtime
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: haml
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :runtime
90
+ version_requirements: *id005
91
+ description: When mails or messages are sent from your application, Better Opener lets you preview the rendered messages in your browser instead of delivering them.
92
+ email:
93
+ - kai@doxter.de
94
+ executables: []
95
+
96
+ extensions: []
97
+
98
+ extra_rdoc_files: []
99
+
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - README.rdoc
104
+ - Rakefile
105
+ - better_opener.gemspec
106
+ - config.ru
107
+ - lib/better_opener.rb
108
+ - lib/better_opener/delivery_method.rb
109
+ - lib/better_opener/email.html.erb
110
+ - lib/better_opener/railtie.rb
111
+ - lib/better_opener/server.rb
112
+ - lib/better_opener/server/views/atom.haml
113
+ - lib/better_opener/server/views/index.haml
114
+ - lib/better_opener/server/views/show.haml
115
+ - lib/better_opener/sms.html.erb
116
+ - lib/better_opener/sms_gateway_adapter.rb
117
+ - lib/better_opener/version.rb
118
+ - lib/test.ru
119
+ homepage: http://github.com/learnjin/better_opener
120
+ licenses: []
121
+
122
+ post_install_message:
123
+ rdoc_options: []
124
+
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ hash: 3
142
+ segments:
143
+ - 0
144
+ version: "0"
145
+ requirements: []
146
+
147
+ rubyforge_project: better_opener
148
+ rubygems_version: 1.8.10
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: A better way of Previewing mail in your browser instead of sending it.
152
+ test_files: []
153
+