dead_letter_office 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.
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: []