mailpeek 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7463689f2eb145d0c020fc9a714935f581c49ada
4
+ data.tar.gz: 9001858ec444f4f4dd4f6596dfeddc2dcbd2f292
5
+ SHA512:
6
+ metadata.gz: 8f5f5fdd8c565fbf51e64b506676f15667193c390e1a92dc8e65ee5b16e8bc76297a693f6e4ba5f160aa789bb578416742222c3e900911bcd11fd206aecf1b44
7
+ data.tar.gz: 6aa5e39ef84c359fcb7b45dc167aee11c5397473e29d4e92577ba983b30b564194af7b14b1d5497157c6bcaa9bc3fe46e18dab52de195c99e68fe0ab78cf52ea
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Rogue Pod, LLC.
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,19 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Mailpeek'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ load 'rails/tasks/statistics.rake'
18
+
19
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,5 @@
1
+ #= require lodash
2
+ #= require moment
3
+ #= require react
4
+ #= require react_ujs
5
+ #= require_tree ./components
@@ -0,0 +1,96 @@
1
+ class @App extends React.Component
2
+ constructor: (props) ->
3
+ super props
4
+ emails = JSON.parse(@props.data).emails
5
+ @state =
6
+ emails: emails
7
+ selected: _.first(emails)
8
+ open: false
9
+ fetching: false
10
+ error: null
11
+
12
+ _retrieveEmails: ->
13
+ @setState
14
+ fetching: true
15
+ error: null
16
+ request = new XMLHttpRequest()
17
+ request.open('GET', '/mailpeek/mail.json', true)
18
+
19
+ request.onload = =>
20
+ try
21
+ response = JSON.parse(request.responseText)
22
+ catch e
23
+ response =
24
+ error: 'Sorry, An error occurred when retrieving the emails'
25
+
26
+ if request.status >= 200 && request.status < 400
27
+ if @state.selected
28
+ selected = @state.selected
29
+ else
30
+ selected = _.first(response.emails)
31
+ @setState
32
+ emails: response.emails
33
+ fetching: false
34
+ selected: selected
35
+ else
36
+ console.log 'nope'
37
+ @setState
38
+ fetching: false
39
+ error: response.error
40
+
41
+ request.onerror = =>
42
+ console.log 'error';
43
+ @setState
44
+ fetching: false
45
+ error: 'Sorry, An error occurred when retrieving the emails'
46
+
47
+ request.send()
48
+ true
49
+
50
+ componentDidMount: ->
51
+ true
52
+
53
+ _onEmailClick: (email) ->
54
+ @setState
55
+ selected: email
56
+ open: false
57
+ true
58
+
59
+ _onMenuIconClick: ->
60
+ @setState
61
+ open: !@state.open
62
+ true
63
+
64
+ _onRefreshIconClick: ->
65
+ this._retrieveEmails()
66
+ true
67
+
68
+ render: ->
69
+ classNames = ['error']
70
+ classNames.push 'error_show' if @state.error
71
+ error = `<div className={classNames.join(' ')}>{this.state.error}</div>`
72
+
73
+ loading = null
74
+ if @state.fetching
75
+ loading =
76
+ `<div className="loading">
77
+ <i className="fa fa-refresh fa-spin loading__icon" />
78
+ </div>`
79
+ `<div>
80
+ {loading}
81
+ <header className="header">
82
+ <i
83
+ className="fa fa-bars header__menu-icon visible-xs" onClick={this._onMenuIconClick.bind(this)} />
84
+ <i
85
+ className="fa fa-refresh header__refresh-icon" onClick={this._onRefreshIconClick.bind(this)} />
86
+ <span className="header__title">Mailpeek</span>
87
+ </header>
88
+ {error}
89
+ <Sidebar
90
+ emails={this.state.emails}
91
+ open={this.state.open}
92
+ selected={this.state.selected}
93
+ handleEmailClick={this._onEmailClick.bind(this)} />
94
+ <Email
95
+ email={this.state.selected} />
96
+ </div>`
@@ -0,0 +1,50 @@
1
+ class @Body extends React.Component
2
+ constructor: (props) ->
3
+ super props
4
+ @state =
5
+ tab: props.email.body[0].type
6
+
7
+ componentWillReceiveProps: (nextProps) ->
8
+ if nextProps.email.message_id != @props.email.message_id
9
+ @setState
10
+ tab: nextProps.email.body[0].type
11
+ true
12
+
13
+ _onTabChange: (tab) ->
14
+ @setState
15
+ tab: tab
16
+ true
17
+
18
+ _body: ->
19
+ for body in @props.email.body
20
+ continue unless body.type == @state.tab
21
+ if body.type == 'text'
22
+ return body.content.split('\n').map (p, index) ->
23
+ `<span key={index}>{p}<br /></span>`
24
+ else
25
+ return `<div dangerouslySetInnerHTML={{__html: body.content}} />`
26
+ null
27
+
28
+ render: ->
29
+ email = @props.email
30
+
31
+ tabs = email.body.map (body, index) =>
32
+ classNames = ['body__tab']
33
+ classNames.push 'body__tab_selected' if body.type == @state.tab
34
+ onClick = @_onTabChange.bind(@, body.type)
35
+ `<div
36
+ key={index}
37
+ className={classNames.join(' ')}
38
+ onClick={onClick}>
39
+ {body.type.toUpperCase()}
40
+ </div>`
41
+
42
+
43
+ body = @_body()
44
+ # <div className="body__content" dangerouslySetInnerHTML={this._body()} />
45
+ `<div className="body">
46
+ <div className="body__tabs">
47
+ {tabs}
48
+ </div>
49
+ <div className="body__content">{body}</div>
50
+ </div>`
@@ -0,0 +1,23 @@
1
+ class @Email extends React.Component
2
+ render: ->
3
+ email = @props.email
4
+
5
+ unless email
6
+ return `<div className="email email_empty">No Emails Found</div>`
7
+
8
+ createdAt = moment(email.date).format('MMM Do YYYY, h:mm:ss a')
9
+ `<div className="email">
10
+ <div className="email__details">
11
+ <dl className="email__list dl-horizontal">
12
+ <dt>Sent</dt>
13
+ <dd>{createdAt}</dd>
14
+ <dt>Subject</dt>
15
+ <dd>{email.subject}</dd>
16
+ <dt>To</dt>
17
+ <dd>{email.to}</dd>
18
+ <dt>From</dt>
19
+ <dd>{email.from}</dd>
20
+ </dl>
21
+ </div>
22
+ <Body email={email} />
23
+ </div>`
@@ -0,0 +1,25 @@
1
+ class @Sidebar extends React.Component
2
+ render: ->
3
+ emails = @props.emails.map (email, index) =>
4
+ click = this.props.handleEmailClick.bind(this, email)
5
+
6
+ classNames = 'email-item'
7
+ if email.message_id == @props.selected.message_id
8
+ classNames = 'email-item email-item_selected'
9
+
10
+ `<li
11
+ className={classNames}
12
+ key={index}
13
+ onClick={click}>
14
+ <strong className="email-item__subject">{email.subject}</strong>
15
+ <em className="email-item__date text-muted">{email.created_at} ago</em>
16
+ </li>`
17
+
18
+
19
+ classNames = 'sidebar'
20
+ classNames = 'sidebar sidebar_open' if this.props.open
21
+ `<div className={classNames}>
22
+ <ul className="list-unstyled">
23
+ {emails}
24
+ </ul>
25
+ </div>`
@@ -0,0 +1,197 @@
1
+ /*
2
+ *= require_tree .
3
+ *= require_self
4
+ */
5
+
6
+ $body-bg: #F5F5F5;
7
+ $brand-primary: #2196F3;
8
+ $white: #fff;
9
+
10
+ @import "bootstrap-sprockets";
11
+ @import "bootstrap";
12
+
13
+ @import "font-awesome-sprockets";
14
+ @import "font-awesome";
15
+
16
+ @mixin card($z) {
17
+ @if $z == 3 {
18
+ @include box-shadow(0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12));
19
+ }
20
+ @else if $z == 2 {
21
+ @include box-shadow(0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12));
22
+ } @else {
23
+ @include box-shadow(0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12));
24
+ }
25
+ @include border-bottom-radius(2px);
26
+ @include border-top-radius(2px);
27
+ }
28
+
29
+ body {
30
+ padding-bottom: 15px;
31
+ }
32
+
33
+ $header-height: 64px;
34
+ $sidebar-width: 320px;
35
+
36
+ .header {
37
+ background: $brand-primary;
38
+ color: $white;
39
+ height: $header-height;
40
+ position: relative;
41
+ z-index: 4;
42
+ padding: 0 15px;
43
+ @include box-shadow(0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12));
44
+ &__menu-icon {
45
+ line-height: $header-height;
46
+ float:left;
47
+ margin-right: 15px;
48
+ font-size: 24px;
49
+ }
50
+ &__refresh-icon {
51
+ line-height: $header-height;
52
+ float:right;
53
+ margin-right: 15px;
54
+ font-size: 24px;
55
+ }
56
+
57
+ &__title {
58
+ line-height: $header-height;
59
+ font-size: 24px;
60
+ }
61
+ }
62
+
63
+ .sidebar {
64
+ position: fixed;
65
+ top: $header-height;
66
+ bottom: 0px;
67
+ left: 0px;
68
+ max-width: $sidebar-width;
69
+ width: 100%;
70
+ background: $white;
71
+ overflow-y: auto;
72
+ overflow-x: hidden;
73
+ z-index: 3;
74
+ @include card(2);
75
+ @include border-bottom-radius(0);
76
+ @include border-top-radius(0);
77
+ @include transition(transform 0.25s ease);
78
+ }
79
+
80
+ .loading {
81
+ @include opacity(0.5);
82
+ background: #757575;
83
+ position: fixed;
84
+ top: 0;
85
+ left: 0;
86
+ right: 0;
87
+ bottom: 0;
88
+ z-index: 5;
89
+ text-align: center;
90
+ &__icon {
91
+ position: absolute;
92
+ top: 50%;
93
+ color: $white;
94
+ font-size: 64px;
95
+ @include translate(0, -50%);
96
+ }
97
+ }
98
+
99
+ .error {
100
+ position: fixed;
101
+ bottom: 15px;
102
+ z-index: 2;
103
+ left: 0;
104
+ right: 0;
105
+ padding: 20px;
106
+ width: 300px;
107
+ margin: 0 auto;
108
+ @include card(3);
109
+ background: #F44336;
110
+ color: $white;
111
+ text-align: center;
112
+ @include transition(transform 0.25s ease);
113
+ @include translate(0, 200%);
114
+
115
+ &_show {
116
+ @include translate(0, 0);
117
+ }
118
+ }
119
+
120
+ .email-item {
121
+ padding: 15px;
122
+ background: $white;
123
+ border-bottom: 1px solid #E0E0E0;
124
+
125
+ &_selected {
126
+ background: #BBDEFB;
127
+ }
128
+
129
+ &__subject {
130
+ display:block;
131
+ }
132
+
133
+ &__date {
134
+ display:block;
135
+ font-size: 12px;
136
+ }
137
+ }
138
+
139
+ .email {
140
+ margin: 15px 15px 0 345px;
141
+
142
+ &_empty {
143
+ @include card(2);
144
+ text-align: center;
145
+ font-size: 24px;
146
+ padding: 15px;
147
+ background: $white;
148
+ }
149
+
150
+ &__details {
151
+ @include card(2);
152
+ margin-bottom: 15px;
153
+ padding: 15px;
154
+ background: $white;
155
+ }
156
+
157
+ &__list {
158
+ margin-bottom: 0;
159
+ }
160
+ }
161
+
162
+ @media (max-width: $screen-sm-min) {
163
+ .sidebar {
164
+ @include translate(-$sidebar-width, 0);
165
+ &_open {
166
+ @include translate(0, 0);
167
+ }
168
+ }
169
+
170
+ .email {
171
+ margin-left: 15px;
172
+ }
173
+ }
174
+
175
+ .body {
176
+ @include card(2);
177
+ background: $white;
178
+
179
+ &__tabs {
180
+ background: $brand-primary;
181
+ }
182
+
183
+ &__tab {
184
+ color: $white;
185
+ border-bottom: 3px solid $brand-primary;
186
+ display: inline-block;
187
+ padding: 15px;
188
+
189
+ &_selected {
190
+ border-bottom: 3px solid #FFEB3B;
191
+ }
192
+ }
193
+
194
+ &__content {
195
+ padding: 15px;
196
+ }
197
+ }
@@ -0,0 +1,4 @@
1
+ module Mailpeek
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,23 @@
1
+ require_dependency 'mailpeek/application_controller'
2
+
3
+ module Mailpeek
4
+ # Public: MailController
5
+ class MailController < ApplicationController
6
+ def index
7
+ # raise 'nope'
8
+ dir = Rails.root.join('tmp', 'mailpeek')
9
+ @emails = []
10
+
11
+ return unless File.directory?(dir)
12
+
13
+ Dir.foreach(dir) do |item|
14
+ next if item == '.' || item == '..'
15
+ mail = Mail.read("#{dir}/#{item}")
16
+ # puts mail.inspect
17
+ @emails.push mail
18
+ end
19
+
20
+ @emails = @emails.sort { |a, b| b.date <=> a.date }.first(50)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ module Mailpeek
2
+ # Public: ApplicationHelper
3
+ module ApplicationHelper
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Mailpeek
2
+ # Public: MailHelper
3
+ module MailHelper
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Mailpeek</title>
5
+ <%= stylesheet_link_tag 'mailpeek/application', media: 'all' %>
6
+ <%= javascript_include_tag 'mailpeek/application' %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,2 @@
1
+ <%= react_component('App',
2
+ data: render(template: 'mailpeek/mail/index.json.jbuilder')) %>
@@ -0,0 +1,24 @@
1
+ json.emails(@emails) do |email|
2
+ json.extract!(email, :message_id, :date, :subject)
3
+ json.created_at time_ago_in_words(email.date)
4
+ json.to email[:to].decoded
5
+ json.from email[:from].decoded
6
+
7
+ parts = []
8
+ if email.body.parts.empty?
9
+ parts.push(
10
+ type: email.content_type =~ /plain/ ? 'text' : 'html',
11
+ content: email.body.decoded)
12
+ else
13
+ email.body.parts.each do |part|
14
+ parts.push(
15
+ type: part.content_type =~ /plain/ ? 'text' : 'html',
16
+ content: part.body.decoded)
17
+ end
18
+ end
19
+
20
+ json.body(parts) do |part|
21
+ json.type part[:type]
22
+ json.content part[:content]
23
+ end
24
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Mailpeek::Engine.routes.draw do
2
+ resources :mail, only: [:index, :destroy]
3
+
4
+ root to: 'mail#index'
5
+ end
data/lib/mailpeek.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'mailpeek/engine'
2
+ require 'mailpeek/delivery'
3
+
4
+ # Public: Mailpeek
5
+ module Mailpeek
6
+ end
@@ -0,0 +1,33 @@
1
+ require 'mail/check_delivery_params'
2
+
3
+ module Mailpeek
4
+ # Public: Delivery
5
+ class Delivery
6
+ include Mail::CheckDeliveryParams if defined?(Mail::CheckDeliveryParams)
7
+
8
+ class InvalidOption < StandardError; end
9
+
10
+ attr_accessor :settings
11
+
12
+ def initialize(options = {})
13
+ if options[:location].nil?
14
+ raise(
15
+ InvalidOption,
16
+ 'A location option is required when using Mailpeek')
17
+ end
18
+ self.settings = options
19
+ end
20
+
21
+ def deliver!(mail)
22
+ check_delivery_params(mail) if respond_to?(:check_delivery_params)
23
+
24
+ FileUtils.mkdir_p(settings[:location])
25
+
26
+ filepath = File.join(settings[:location], Time.now.to_i.to_s)
27
+
28
+ File.open(filepath, 'w') do |f|
29
+ f.write mail.to_s
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ module Mailpeek
2
+ # Public: Engine
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Mailpeek
5
+
6
+ initializer 'mailpeek.add_delivery_method' do
7
+ ActiveSupport.on_load :action_mailer do
8
+ ActionMailer::Base.add_delivery_method(
9
+ :mailpeek,
10
+ Mailpeek::Delivery,
11
+ location: Rails.root.join('tmp', 'mailpeek'))
12
+ end
13
+ end
14
+
15
+ initializer('mailpeek.react-rails') do
16
+ Mailpeek::Engine.config.react.variant = :development
17
+ end
18
+
19
+ require 'react-rails'
20
+ require 'bootstrap-sass'
21
+ require 'font-awesome-sass'
22
+ require 'lodash-rails'
23
+ require 'momentjs-rails'
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Mailpeek
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :mailpeek do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,247 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailpeek
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rogue Pod, LLC.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mail
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jbuilder
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: react-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: uglifier
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coffee-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sass-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: bootstrap-sass
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: font-awesome-sass
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: lodash-rails
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: momentjs-rails
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: guard-rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rspec-rails
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description: Provides a web interface to view emails sent out when developing in rails
196
+ email:
197
+ - jeffharper@roguepod.com
198
+ executables: []
199
+ extensions: []
200
+ extra_rdoc_files: []
201
+ files:
202
+ - MIT-LICENSE
203
+ - Rakefile
204
+ - app/assets/javascripts/mailpeek/application.coffee
205
+ - app/assets/javascripts/mailpeek/components/App.js.jsx.coffee
206
+ - app/assets/javascripts/mailpeek/components/Body.js.jsx.coffee
207
+ - app/assets/javascripts/mailpeek/components/Email.js.jsx.coffee
208
+ - app/assets/javascripts/mailpeek/components/Sidebar.js.jsx.coffee
209
+ - app/assets/stylesheets/mailpeek/application.scss
210
+ - app/controllers/mailpeek/application_controller.rb
211
+ - app/controllers/mailpeek/mail_controller.rb
212
+ - app/helpers/mailpeek/application_helper.rb
213
+ - app/helpers/mailpeek/mail_helper.rb
214
+ - app/views/layouts/mailpeek/application.html.erb
215
+ - app/views/mailpeek/mail/index.html.erb
216
+ - app/views/mailpeek/mail/index.json.jbuilder
217
+ - config/routes.rb
218
+ - lib/mailpeek.rb
219
+ - lib/mailpeek/delivery.rb
220
+ - lib/mailpeek/engine.rb
221
+ - lib/mailpeek/version.rb
222
+ - lib/tasks/mailpeek_tasks.rake
223
+ homepage: https://github.com/RoguePod/mailpeek
224
+ licenses:
225
+ - MIT
226
+ metadata: {}
227
+ post_install_message:
228
+ rdoc_options: []
229
+ require_paths:
230
+ - lib
231
+ required_ruby_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ required_rubygems_version: !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - ">="
239
+ - !ruby/object:Gem::Version
240
+ version: '0'
241
+ requirements: []
242
+ rubyforge_project:
243
+ rubygems_version: 2.5.1
244
+ signing_key:
245
+ specification_version: 4
246
+ summary: Preview Rails Emails
247
+ test_files: []