dead_letter_office 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +85 -0
  3. data/Rakefile +39 -0
  4. data/app/assets/images/dead_letter_office/bootstrap/glyphicons-halflings-white.png +0 -0
  5. data/app/assets/images/dead_letter_office/bootstrap/glyphicons-halflings.png +0 -0
  6. data/app/assets/images/dead_letter_office/datatables/Sorting icons.psd +0 -0
  7. data/app/assets/images/dead_letter_office/datatables/back_disabled.png +0 -0
  8. data/app/assets/images/dead_letter_office/datatables/back_enabled.png +0 -0
  9. data/app/assets/images/dead_letter_office/datatables/back_enabled_hover.png +0 -0
  10. data/app/assets/images/dead_letter_office/datatables/favicon.ico +0 -0
  11. data/app/assets/images/dead_letter_office/datatables/forward_disabled.png +0 -0
  12. data/app/assets/images/dead_letter_office/datatables/forward_enabled.png +0 -0
  13. data/app/assets/images/dead_letter_office/datatables/forward_enabled_hover.png +0 -0
  14. data/app/assets/images/dead_letter_office/datatables/sort_asc.png +0 -0
  15. data/app/assets/images/dead_letter_office/datatables/sort_asc_disabled.png +0 -0
  16. data/app/assets/images/dead_letter_office/datatables/sort_both.png +0 -0
  17. data/app/assets/images/dead_letter_office/datatables/sort_desc.png +0 -0
  18. data/app/assets/images/dead_letter_office/datatables/sort_desc_disabled.png +0 -0
  19. data/app/assets/javascripts/dead_letter_office/application.js +18 -0
  20. data/app/assets/javascripts/dead_letter_office/bootstrap.min.js +7 -0
  21. data/app/assets/javascripts/dead_letter_office/bootstrap_pagination.js +95 -0
  22. data/app/assets/javascripts/dead_letter_office/datatables.js +154 -0
  23. data/app/assets/javascripts/dead_letter_office/dead_letters.js +17 -0
  24. data/app/assets/stylesheets/dead_letter_office/application.css +24 -0
  25. data/app/assets/stylesheets/dead_letter_office/bootstrap.min.css.scss +727 -0
  26. data/app/assets/stylesheets/dead_letter_office/datatables.css.scss +47 -0
  27. data/app/assets/stylesheets/dead_letter_office/dead_letters.css +4 -0
  28. data/app/assets/stylesheets/dead_letter_office/dead_letters.css.scss +13 -0
  29. data/app/controllers/dead_letter_office/application_controller.rb +4 -0
  30. data/app/controllers/dead_letter_office/dead_letters_controller.rb +21 -0
  31. data/app/helpers/dead_letter_office/application_helper.rb +4 -0
  32. data/app/models/dead_letter_office/dead_letter.rb +35 -0
  33. data/app/views/dead_letter_office/dead_letters/_action_links.html.erb +20 -0
  34. data/app/views/dead_letter_office/dead_letters/_dead_letter.html.erb +68 -0
  35. data/app/views/dead_letter_office/dead_letters/_notice.html.erb +5 -0
  36. data/app/views/dead_letter_office/dead_letters/destroy.js.erb +4 -0
  37. data/app/views/dead_letter_office/dead_letters/index.html.erb +38 -0
  38. data/app/views/layouts/dead_letter_office/application.html.erb +43 -0
  39. data/config/initializers/exception_handler.rb +5 -0
  40. data/config/routes.rb +4 -0
  41. data/db/migrate/20120712054220_create_dead_letter_office_dead_letters.rb +19 -0
  42. data/lib/dead_letter_office.rb +4 -0
  43. data/lib/dead_letter_office/engine.rb +5 -0
  44. data/lib/dead_letter_office/version.rb +3 -0
  45. data/lib/tasks/dead_letter_office_tasks.rake +4 -0
  46. metadata +177 -0
@@ -0,0 +1,47 @@
1
+
2
+ div.dataTables_length label {
3
+ float: left;
4
+ text-align: left;
5
+ }
6
+
7
+ div.dataTables_length select {
8
+ width: 75px;
9
+ }
10
+
11
+ div.dataTables_filter label {
12
+ float: right;
13
+ }
14
+
15
+ div.dataTables_info {
16
+ padding-top: 8px;
17
+ }
18
+
19
+ div.dataTables_paginate {
20
+ float: right;
21
+ margin: 0;
22
+ }
23
+
24
+ table.table {
25
+ clear: both;
26
+ margin-bottom: 6px !important;
27
+ }
28
+
29
+ table.table thead .sorting,
30
+ table.table thead .sorting_asc,
31
+ table.table thead .sorting_desc,
32
+ table.table thead .sorting_asc_disabled,
33
+ table.table thead .sorting_desc_disabled {
34
+ cursor: pointer;
35
+ *cursor: hand;
36
+ }
37
+
38
+ table.table thead .sorting { background: image-url('dead_letter_office/datatables/sort_both.png') no-repeat center right; }
39
+ table.table thead .sorting_asc { background: image-url('dead_letter_office/datatables/sort_asc.png') no-repeat center right; }
40
+ table.table thead .sorting_desc { background: image-url('dead_letter_office/datatables/sort_desc.png') no-repeat center right; }
41
+
42
+ table.table thead .sorting_asc_disabled { background: image-url('dead_letter_office/datatables/sort_asc_disabled.png') no-repeat center right; }
43
+ table.table thead .sorting_desc_disabled { background: image-url('dead_letter_office/datatables/sort_desc_disabled.png') no-repeat center right; }
44
+
45
+ table.dataTable th:active {
46
+ outline: none;
47
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,13 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
5
+
6
+ body {
7
+ padding-top: 60px;
8
+ padding-bottom: 40px;
9
+ }
10
+
11
+ h1 {
12
+ margin-bottom: 15px;
13
+ }
@@ -0,0 +1,4 @@
1
+ module DeadLetterOffice
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ require_dependency "dead_letter_office/application_controller"
2
+
3
+ module DeadLetterOffice
4
+ class DeadLettersController < ApplicationController
5
+ def index
6
+ @dead_letters = DeadLetter.scoped
7
+ end
8
+
9
+ def destroy
10
+ @dead_letter = DeadLetter.find(params[:id])
11
+ @dead_letter.destroy
12
+
13
+ respond_to do |wants|
14
+ wants.js
15
+ wants.html do
16
+ redirect_to dead_letters_path, notice: "Dead Letter has been removed."
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module DeadLetterOffice
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,35 @@
1
+ require "mail"
2
+
3
+ module DeadLetterOffice
4
+ class DeadLetter < ActiveRecord::Base
5
+ attr_accessible :mailer, :message_id, :subject, :date, :mail
6
+
7
+ def self.recover_parcel(parcel)
8
+ payload = parcel.dup
9
+ ex_name, ex_message = *payload.delete(:exception)
10
+
11
+ to = format_recipient(payload.delete(:to))
12
+ cc = format_recipient(payload.delete(:cc))
13
+ bcc = format_recipient(payload.delete(:bcc))
14
+ from = format_recipient(payload.delete(:from))
15
+ mail = ::Mail.new(payload.delete(:mail)).body.decoded
16
+ date = payload.delete(:date) || Time.zone.now
17
+
18
+ new(payload) do |dead_letter|
19
+ dead_letter.to = to
20
+ dead_letter.cc = cc
21
+ dead_letter.bcc = bcc
22
+ dead_letter.from = from
23
+ dead_letter.mail = mail
24
+ dead_letter.date = date
25
+ dead_letter.exception_name = ex_name
26
+ dead_letter.exception_message = ex_message
27
+ dead_letter.save
28
+ end
29
+ end
30
+
31
+ def self.format_recipient(recipient)
32
+ Array.wrap(recipient).join(",")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ <div class="btn-group">
2
+ <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
3
+ <i class="icon-cog"></i> Actions
4
+ <span class="caret"></span>
5
+ </a>
6
+ <ul class="dropdown-menu">
7
+ <!-- dropdown menu links -->
8
+ <li>
9
+ <%= link_to "#", data: { message_id: dead_letter.id } do %>
10
+ <i class="icon-envelope"></i> View Details
11
+ <% end %>
12
+ </li>
13
+ <li>
14
+ <%= link_to dead_letter_path(dead_letter), method: :delete,
15
+ remote: true, data: { confirm: "Are you sure?" } do %>
16
+ <i class="icon-trash"></i> Remove
17
+ <% end %>
18
+ </li>
19
+ </ul>
20
+ </div>
@@ -0,0 +1,68 @@
1
+ <div class="modal fade hide" id="<%= dom_id(dead_letter, :details) %>">
2
+ <div class="modal-header">
3
+ <button type="button" class="close" data-dismiss="modal">×</button>
4
+ <h3>Message Details</h3>
5
+ </div>
6
+
7
+ <div class="modal-body">
8
+ <table class="table">
9
+ <tbody>
10
+ <tr>
11
+ <th>Exception:</th>
12
+ <td><%= dead_letter.exception_name %>: <%= dead_letter.exception_message %></td>
13
+ </tr>
14
+ <tr>
15
+ <th>Mailer:</th>
16
+ <td><%= dead_letter.mailer %></td>
17
+ </tr>
18
+ <tr>
19
+ <th>ID:</th>
20
+ <td><%= dead_letter.message_id %></td>
21
+ </tr>
22
+ <tr>
23
+ <th>Subject:</th>
24
+ <td><%= dead_letter.subject %></td>
25
+ </tr>
26
+ <tr>
27
+ <th>From:</th>
28
+ <td><%= dead_letter.from %></td>
29
+ </tr>
30
+ <tr>
31
+ <th>To:</th>
32
+ <td><%= dead_letter.to %></td>
33
+ </tr>
34
+ <tr>
35
+ <th>CC:</th>
36
+ <td><%= dead_letter.cc %></td>
37
+ </tr>
38
+ <tr>
39
+ <th>BCC:</th>
40
+ <td><%= dead_letter.bcc %></td>
41
+ </tr>
42
+ <tr>
43
+ <th>Date:</th>
44
+ <td><%= dead_letter.date.to_s %></td>
45
+ </tr>
46
+ <tr>
47
+ <th>Body:</th>
48
+ <td>
49
+ <pre><%= dead_letter.mail %></pre>
50
+ </td>
51
+ </tr>
52
+ </tbody>
53
+ </table>
54
+ </div>
55
+
56
+ <div class="modal-footer">
57
+ <!-- clear message -->
58
+ <%= link_to dead_letter_path(dead_letter), method: :delete,
59
+ class: "btn btn-danger", data: { confirm: "Are you sure?" } do %>
60
+ <i class="icon-trash icon-white"></i> Remove
61
+ <% end %>
62
+
63
+ <!-- close modal -->
64
+ <a href="#" class="btn" data-dismiss="modal">
65
+ <i class="icon-remove"></i> Close
66
+ </a>
67
+ </div>
68
+ </div>
@@ -0,0 +1,5 @@
1
+ <div id="notice" class="alert alert-success">
2
+ <a class="close" data-dismiss="alert" href="#">×</a>
3
+ <h4 class="alert-heading">Notice:</h4>
4
+ <%= notice %>
5
+ </div>
@@ -0,0 +1,4 @@
1
+ var rowTarget = "<%= dom_id @dead_letter, :row %>";
2
+ $("#" + rowTarget).hide("slow", function() { $("#" + rowTarget).remove(); });
3
+
4
+ $("h1").after("<%=j render "notice", notice: "Dead Letter has been removed." %>");
@@ -0,0 +1,38 @@
1
+ <h1>Undeliverable Mail</h1>
2
+
3
+ <%= render "notice", notice: notice if notice.present? %>
4
+
5
+ <table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="dead_letters">
6
+ <thead>
7
+ <tr>
8
+ <th>Mailer</th>
9
+ <th>To</th>
10
+ <th>Subject</th>
11
+ <th>Date</th>
12
+ <th>&nbsp;</th>
13
+ </tr>
14
+ </thead>
15
+ <tfoot>
16
+ <tr>
17
+ <th>Mailer</th>
18
+ <th>To</th>
19
+ <th>Subject</th>
20
+ <th>Date</th>
21
+ <th>&nbsp;</th>
22
+ </tr>
23
+ </tfoot>
24
+
25
+ <tbody>
26
+ <% @dead_letters.each do |dead_letter| %>
27
+ <tr id="<%= dom_id(dead_letter, :row) %>">
28
+ <td><%= dead_letter.mailer %></td>
29
+ <td><%= dead_letter.to %></td>
30
+ <td><%= dead_letter.subject %></td>
31
+ <td><%= dead_letter.date.to_s %></td>
32
+ <td><%= render "action_links", dead_letter: dead_letter %></td>
33
+ </tr>
34
+ <% end %>
35
+ </tbody>
36
+ </table>
37
+
38
+ <%= render @dead_letters %>
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Dead Letter Office</title>
5
+ <%= stylesheet_link_tag "dead_letter_office/application", :media => "all" %>
6
+ <%= csrf_meta_tags %>
7
+ </head>
8
+ <body>
9
+
10
+ <div class="navbar navbar-fixed-top">
11
+ <div class="navbar-inner">
12
+ <div class="container">
13
+
14
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
15
+ <span class="icon-bar"></span>
16
+ <span class="icon-bar"></span>
17
+ </a>
18
+
19
+ <a class="brand" href="#">Dead Letter Office</a>
20
+
21
+ <div class="nav-collapse">
22
+ <ul class="nav">
23
+ <li class="active"><a href="#">Home</a></li>
24
+ <li><a href="http://phlippers.net/dead_letter_office">About</a></li>
25
+ </ul>
26
+ </div>
27
+
28
+ </div>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="container">
33
+ <%= yield %>
34
+
35
+ <hr>
36
+ <footer>
37
+ <p>&copy; 2012 Phil Cohen - <a href="http://phlippers.net">http://phlippers.net</a></p>
38
+ </footer>
39
+ </div>
40
+
41
+ <%= javascript_include_tag "dead_letter_office/application" %>
42
+ </body>
43
+ </html>
@@ -0,0 +1,5 @@
1
+ ActiveSupport::Notifications.subscribe "deliver.action_mailer" do |name, start, finish, id, payload|
2
+ if payload[:exception]
3
+ DeadLetterOffice::DeadLetter.recover_parcel(payload)
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ DeadLetterOffice::Engine.routes.draw do
2
+ resources :dead_letters, only: [:index, :destroy]
3
+ root to: "dead_letters#index"
4
+ end
@@ -0,0 +1,19 @@
1
+ class CreateDeadLetterOfficeDeadLetters < ActiveRecord::Migration
2
+ def change
3
+ create_table :dead_letter_office_dead_letters do |t|
4
+ t.string :mailer
5
+ t.string :message_id
6
+ t.string :subject
7
+ t.string :to
8
+ t.string :from
9
+ t.string :cc
10
+ t.string :bcc
11
+ t.datetime :date
12
+ t.text :mail
13
+ t.string :exception_name
14
+ t.string :exception_message
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ require "dead_letter_office/engine"
2
+
3
+ module DeadLetterOffice
4
+ end
@@ -0,0 +1,5 @@
1
+ module DeadLetterOffice
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace DeadLetterOffice
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module DeadLetterOffice
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :dead_letter_office do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dead_letter_office
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Phil Cohen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ type: :runtime
16
+ prerelease: false
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.6
22
+ none: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 3.2.6
28
+ none: false
29
+ name: rails
30
+ - !ruby/object:Gem::Dependency
31
+ type: :runtime
32
+ prerelease: false
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.5
38
+ none: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 3.2.5
44
+ none: false
45
+ name: sass-rails
46
+ - !ruby/object:Gem::Dependency
47
+ type: :development
48
+ prerelease: false
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ none: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ none: false
61
+ name: capybara
62
+ - !ruby/object:Gem::Dependency
63
+ type: :development
64
+ prerelease: false
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ none: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ none: false
77
+ name: guard-minitest
78
+ - !ruby/object:Gem::Dependency
79
+ type: :development
80
+ prerelease: false
81
+ requirement: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ none: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ none: false
93
+ name: minitest-rails
94
+ description: Undeliverable emails (deliveries which raise exceptions) will be logged
95
+ to the database and can be viewed via a mountable web interface.
96
+ email:
97
+ - github@phlippers.net
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - app/views/layouts/dead_letter_office/application.html.erb
103
+ - app/views/dead_letter_office/dead_letters/_action_links.html.erb
104
+ - app/views/dead_letter_office/dead_letters/_dead_letter.html.erb
105
+ - app/views/dead_letter_office/dead_letters/_notice.html.erb
106
+ - app/views/dead_letter_office/dead_letters/destroy.js.erb
107
+ - app/views/dead_letter_office/dead_letters/index.html.erb
108
+ - app/models/dead_letter_office/dead_letter.rb
109
+ - app/helpers/dead_letter_office/application_helper.rb
110
+ - app/controllers/dead_letter_office/application_controller.rb
111
+ - app/controllers/dead_letter_office/dead_letters_controller.rb
112
+ - app/assets/stylesheets/dead_letter_office/application.css
113
+ - app/assets/stylesheets/dead_letter_office/bootstrap.min.css.scss
114
+ - app/assets/stylesheets/dead_letter_office/datatables.css.scss
115
+ - app/assets/stylesheets/dead_letter_office/dead_letters.css
116
+ - app/assets/stylesheets/dead_letter_office/dead_letters.css.scss
117
+ - app/assets/javascripts/dead_letter_office/application.js
118
+ - app/assets/javascripts/dead_letter_office/bootstrap.min.js
119
+ - app/assets/javascripts/dead_letter_office/bootstrap_pagination.js
120
+ - app/assets/javascripts/dead_letter_office/datatables.js
121
+ - app/assets/javascripts/dead_letter_office/dead_letters.js
122
+ - app/assets/images/dead_letter_office/bootstrap/glyphicons-halflings-white.png
123
+ - app/assets/images/dead_letter_office/bootstrap/glyphicons-halflings.png
124
+ - app/assets/images/dead_letter_office/datatables/back_disabled.png
125
+ - app/assets/images/dead_letter_office/datatables/back_enabled.png
126
+ - app/assets/images/dead_letter_office/datatables/back_enabled_hover.png
127
+ - app/assets/images/dead_letter_office/datatables/favicon.ico
128
+ - app/assets/images/dead_letter_office/datatables/forward_disabled.png
129
+ - app/assets/images/dead_letter_office/datatables/forward_enabled.png
130
+ - app/assets/images/dead_letter_office/datatables/forward_enabled_hover.png
131
+ - app/assets/images/dead_letter_office/datatables/sort_asc.png
132
+ - app/assets/images/dead_letter_office/datatables/sort_asc_disabled.png
133
+ - app/assets/images/dead_letter_office/datatables/sort_both.png
134
+ - app/assets/images/dead_letter_office/datatables/sort_desc.png
135
+ - app/assets/images/dead_letter_office/datatables/sort_desc_disabled.png
136
+ - app/assets/images/dead_letter_office/datatables/Sorting icons.psd
137
+ - config/routes.rb
138
+ - config/initializers/exception_handler.rb
139
+ - db/migrate/20120712054220_create_dead_letter_office_dead_letters.rb
140
+ - lib/dead_letter_office.rb
141
+ - lib/dead_letter_office/engine.rb
142
+ - lib/dead_letter_office/version.rb
143
+ - lib/tasks/dead_letter_office_tasks.rake
144
+ - MIT-LICENSE
145
+ - Rakefile
146
+ - README.md
147
+ homepage: http://phlippers.net/dead_letter_office
148
+ licenses: []
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ segments:
159
+ - 0
160
+ hash: 2002549777813010636
161
+ none: false
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ segments:
168
+ - 0
169
+ hash: 2002549777813010636
170
+ none: false
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 1.8.24
174
+ signing_key:
175
+ specification_version: 3
176
+ summary: This project implements a Dead letter office for your Rails 3 application.
177
+ test_files: []