mailcatcher-jruby 1.1.3 → 1.1.4
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.
- checksums.yaml +4 -4
- data/lib/mail_catcher/mail.rb +4 -61
- data/lib/mail_catcher/version.rb +1 -1
- data/lib/mail_catcher/web.rb +2 -0
- data/public/javascripts/application.js +474 -441
- data/public/stylesheets/application.css +365 -365
- metadata +92 -93
- data/config.ru +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b12132d30e684f47cc6409c240b0684615fb436
|
4
|
+
data.tar.gz: 11958f289b65ecf2f04958d1a9a05eaa3813392c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6027fc8fdb637e18dcc60a37973dd16bf9a7942c17f25e453e669cda48881ba92e9fa7f13366e1dfe7a4501a15c8d422bb0cc4571abe643cc79df00d867d5502
|
7
|
+
data.tar.gz: 7cf61262e58f58ed09b76bb4ed9a493bb34c827280c83fb457201c9e2e98735917b86c9c646991448fe48fcb58de0ee2130bd5773af88723aa4fe1935319910a
|
data/lib/mail_catcher/mail.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
require 'active_support/json'
|
2
2
|
require 'active_record'
|
3
3
|
require 'mail'
|
4
|
-
#require 'sqlite3'
|
5
4
|
require 'eventmachine'
|
6
5
|
require 'tmpdir'
|
7
6
|
|
8
7
|
db_path = File.join(Dir::tmpdir, 'mailcatcherdb')
|
9
8
|
|
10
|
-
ActiveRecord::Base.configurations["db"] = { adapter: 'jdbcsqlite3', database: db_path, pool:
|
9
|
+
#ActiveRecord::Base.configurations["db"] = { adapter: 'jdbcsqlite3', database: db_path, pool: 5 }
|
10
|
+
ActiveRecord::Base.establish_connection({ adapter: 'jdbcsqlite3', database: db_path, pool: 5 })
|
11
11
|
|
12
12
|
class Message < ActiveRecord::Base
|
13
|
-
establish_connection :db
|
13
|
+
#establish_connection :db
|
14
14
|
has_many :message_parts, dependent: :destroy
|
15
15
|
self.inheritance_column = nil
|
16
16
|
|
@@ -19,7 +19,7 @@ class Message < ActiveRecord::Base
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
class MessagePart < ActiveRecord::Base
|
22
|
-
establish_connection :db
|
22
|
+
#establish_connection :db
|
23
23
|
belongs_to :message
|
24
24
|
self.inheritance_column = nil
|
25
25
|
end
|
@@ -50,10 +50,8 @@ end unless MessagePart.table_exists?
|
|
50
50
|
module MailCatcher::Mail extend self
|
51
51
|
|
52
52
|
def add_message(message)
|
53
|
-
#@add_message_query ||= db.prepare("INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'))")
|
54
53
|
|
55
54
|
mail = Mail.new(message[:source])
|
56
|
-
#@add_message_query.execute(message[:sender], message[:recipients].to_json, mail.subject, message[:source], mail.mime_type || 'text/plain', message[:source].length)
|
57
55
|
|
58
56
|
m = Message.create(
|
59
57
|
sender: message[:sender],
|
@@ -72,7 +70,6 @@ module MailCatcher::Mail extend self
|
|
72
70
|
body = part.body.to_s
|
73
71
|
# Only parts have CIDs, not mail
|
74
72
|
cid = part.cid if part.respond_to? :cid
|
75
|
-
#add_message_part(message_id, cid, part.mime_type || 'text/plain', part.attachment? ? 1 : 0, part.filename, part.charset, body, body.length)
|
76
73
|
MessagePart.create(
|
77
74
|
message_id: message_id,
|
78
75
|
cid: cid,
|
@@ -91,77 +88,38 @@ module MailCatcher::Mail extend self
|
|
91
88
|
end
|
92
89
|
end
|
93
90
|
|
94
|
-
#def add_message_part(*args)
|
95
|
-
#@add_message_part_query ||= db.prepare "INSERT INTO message_part (message_id, cid, type, is_attachment, filename, charset, body, size, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))"
|
96
|
-
#@add_message_part_query.execute(*args)
|
97
|
-
#end
|
98
|
-
|
99
|
-
#def latest_created_at
|
100
|
-
#@latest_created_at_query ||= db.prepare "SELECT created_at FROM message ORDER BY created_at DESC LIMIT 1"
|
101
|
-
#@latest_created_at_query.execute.next
|
102
|
-
#end
|
103
|
-
|
104
91
|
def messages
|
105
92
|
Message.all.map(&:attributes)
|
106
|
-
#@messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at ASC"
|
107
|
-
#@messages_query.execute.map do |row|
|
108
|
-
#Hash[row.fields.zip(row)].tap do |message|
|
109
|
-
#message["recipients"] &&= ActiveSupport::JSON.decode message["recipients"]
|
110
|
-
#end
|
111
|
-
#end
|
112
93
|
end
|
113
94
|
|
114
95
|
def message(id)
|
115
96
|
Message.find(id).attributes
|
116
|
-
#@message_query ||= db.prepare "SELECT * FROM message WHERE id = ? LIMIT 1"
|
117
|
-
#row = @message_query.execute(id).next
|
118
|
-
#row && Hash[row.fields.zip(row)].tap do |message|
|
119
|
-
#message["recipients"] &&= ActiveSupport::JSON.decode message["recipients"]
|
120
|
-
#end
|
121
97
|
end
|
122
98
|
|
123
99
|
def message_has_html?(id)
|
124
100
|
part = MessagePart.where(message_id: id, is_attachment: 0).where("type IN ('application/xhtml+xml', 'text/html')").first
|
125
101
|
part.present? || ['text/html', 'application/xhtml+xml'].include?(Message.find(id).type)
|
126
|
-
#@message_has_html_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type IN ('application/xhtml+xml', 'text/html') LIMIT 1"
|
127
|
-
#(!!@message_has_html_query.execute(id).next) || ['text/html', 'application/xhtml+xml'].include?(message(id)["type"])
|
128
102
|
end
|
129
103
|
|
130
104
|
def message_has_plain?(id)
|
131
105
|
part = MessagePart.where(message_id: id, is_attachment: 0, type: 'text/plain').first
|
132
106
|
part.present? || Message.find(id).type == 'text/plain'
|
133
|
-
#@message_has_plain_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type = 'text/plain' LIMIT 1"
|
134
|
-
#(!!@message_has_plain_query.execute(id).next) || message(id)["type"] == "text/plain"
|
135
107
|
end
|
136
108
|
|
137
109
|
def message_parts(id)
|
138
110
|
MessagePart.where(:message_id => id).order('filename ASC').map(&:attributes)
|
139
|
-
#@message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? ORDER BY filename ASC"
|
140
|
-
#@message_parts_query.execute(id).map do |row|
|
141
|
-
#Hash[row.fields.zip(row)]
|
142
|
-
#end
|
143
111
|
end
|
144
112
|
|
145
113
|
def message_attachments(id)
|
146
114
|
MessagePart.where(message_id: id, is_attachment: 1).order('filename ASC').map(&:attributes)
|
147
|
-
#@message_parts_query ||= db.prepare "SELECT cid, type, filename, size FROM message_part WHERE message_id = ? AND is_attachment = 1 ORDER BY filename ASC"
|
148
|
-
#@message_parts_query.execute(id).map do |row|
|
149
|
-
#Hash[row.fields.zip(row)]
|
150
|
-
#end
|
151
115
|
end
|
152
116
|
|
153
117
|
def message_part(message_id, part_id)
|
154
118
|
MessagePart.where(message_id: message_id, id: part_id).first.try(:attributes)
|
155
|
-
#@message_part_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND id = ? LIMIT 1"
|
156
|
-
#row = @message_part_query.execute(message_id, part_id).next
|
157
|
-
#row && Hash[row.fields.zip(row)]
|
158
119
|
end
|
159
120
|
|
160
121
|
def message_part_type(message_id, part_type)
|
161
122
|
MessagePart.where(message_id: message_id, type: part_type, is_attachment: 0).first.try(:attributes)
|
162
|
-
#@message_part_type_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ? AND type = ? AND is_attachment = 0 LIMIT 1"
|
163
|
-
#row = @message_part_type_query.execute(message_id, part_type).next
|
164
|
-
#row && Hash[row.fields.zip(row)]
|
165
123
|
end
|
166
124
|
|
167
125
|
def message_part_html(message_id)
|
@@ -179,28 +137,13 @@ module MailCatcher::Mail extend self
|
|
179
137
|
|
180
138
|
def message_part_cid(message_id, cid)
|
181
139
|
MessagePart.where(message_id: message_id, cid: cid).first.try(:attributes)
|
182
|
-
#@message_part_cid_query ||= db.prepare 'SELECT * FROM message_part WHERE message_id = ?'
|
183
|
-
#@message_part_cid_query.execute(message_id).map do |row|
|
184
|
-
#Hash[row.fields.zip(row)]
|
185
|
-
#end.find do |part|
|
186
|
-
#part["cid"] == cid
|
187
|
-
#end
|
188
140
|
end
|
189
141
|
|
190
142
|
def delete!
|
191
143
|
Message.destroy_all
|
192
|
-
#@delete_messages_query ||= db.prepare 'DELETE FROM message'
|
193
|
-
#@delete_message_parts_query ||= db.prepare 'DELETE FROM message_part'
|
194
|
-
|
195
|
-
#@delete_messages_query.execute and
|
196
|
-
#@delete_message_parts_query.execute
|
197
144
|
end
|
198
145
|
|
199
146
|
def delete_message!(message_id)
|
200
147
|
Message.where(id: message_id).destroy_all
|
201
|
-
#@delete_messages_query ||= db.prepare 'DELETE FROM message WHERE id = ?'
|
202
|
-
#@delete_message_parts_query ||= db.prepare 'DELETE FROM message_part WHERE message_id = ?'
|
203
|
-
#@delete_messages_query.execute(message_id) and
|
204
|
-
#@delete_message_parts_query.execute(message_id)
|
205
148
|
end
|
206
149
|
end
|
data/lib/mail_catcher/version.rb
CHANGED
data/lib/mail_catcher/web.rb
CHANGED
@@ -1,441 +1,474 @@
|
|
1
|
-
(function() {
|
2
|
-
var MailCatcher,
|
3
|
-
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
4
|
-
|
5
|
-
jQuery.expr[':'].icontains = function(a, i, m) {
|
6
|
-
var _ref, _ref1;
|
7
|
-
return ((_ref = (_ref1 = a.textContent) != null ? _ref1 : a.innerText) != null ? _ref : "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
|
8
|
-
};
|
9
|
-
|
10
|
-
MailCatcher = (function() {
|
11
|
-
function MailCatcher() {
|
12
|
-
this.nextTab = __bind(this.nextTab, this);
|
13
|
-
this.previousTab = __bind(this.previousTab, this);
|
14
|
-
this.openTab = __bind(this.openTab, this);
|
15
|
-
this.selectedTab = __bind(this.selectedTab, this);
|
16
|
-
this.getTab = __bind(this.getTab, this);
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
}
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
return
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
this
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
};
|
205
|
-
|
206
|
-
MailCatcher.prototype.
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
return $(
|
253
|
-
};
|
254
|
-
|
255
|
-
MailCatcher.prototype.
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
$(
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
$('#
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
$(
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
1
|
+
(function() {
|
2
|
+
var MailCatcher,
|
3
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
4
|
+
|
5
|
+
jQuery.expr[':'].icontains = function(a, i, m) {
|
6
|
+
var _ref, _ref1;
|
7
|
+
return ((_ref = (_ref1 = a.textContent) != null ? _ref1 : a.innerText) != null ? _ref : "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
|
8
|
+
};
|
9
|
+
|
10
|
+
MailCatcher = (function() {
|
11
|
+
function MailCatcher() {
|
12
|
+
this.nextTab = __bind(this.nextTab, this);
|
13
|
+
this.previousTab = __bind(this.previousTab, this);
|
14
|
+
this.openTab = __bind(this.openTab, this);
|
15
|
+
this.selectedTab = __bind(this.selectedTab, this);
|
16
|
+
this.getTab = __bind(this.getTab, this);
|
17
|
+
$('#messages tr').live('click', (function(_this) {
|
18
|
+
return function(e) {
|
19
|
+
e.preventDefault();
|
20
|
+
return _this.loadMessage($(e.currentTarget).attr('data-message-id'));
|
21
|
+
};
|
22
|
+
})(this));
|
23
|
+
$('input[name=search]').keyup((function(_this) {
|
24
|
+
return function(e) {
|
25
|
+
var query;
|
26
|
+
query = $.trim($(e.currentTarget).val());
|
27
|
+
if (query) {
|
28
|
+
return _this.searchMessages(query);
|
29
|
+
} else {
|
30
|
+
return _this.clearSearch();
|
31
|
+
}
|
32
|
+
};
|
33
|
+
})(this));
|
34
|
+
$('#message .views .format.tab a').live('click', (function(_this) {
|
35
|
+
return function(e) {
|
36
|
+
e.preventDefault();
|
37
|
+
return _this.loadMessageBody(_this.selectedMessage(), $($(e.currentTarget).parent('li')).data('message-format'));
|
38
|
+
};
|
39
|
+
})(this));
|
40
|
+
$('#message .views .analysis.tab a').live('click', (function(_this) {
|
41
|
+
return function(e) {
|
42
|
+
e.preventDefault();
|
43
|
+
return _this.loadMessageAnalysis(_this.selectedMessage());
|
44
|
+
};
|
45
|
+
})(this));
|
46
|
+
$('#message iframe').load((function(_this) {
|
47
|
+
return function() {
|
48
|
+
return _this.decorateMessageBody();
|
49
|
+
};
|
50
|
+
})(this));
|
51
|
+
$('#resizer').live({
|
52
|
+
mousedown: (function(_this) {
|
53
|
+
return function(e) {
|
54
|
+
var events;
|
55
|
+
e.preventDefault();
|
56
|
+
return $(window).bind(events = {
|
57
|
+
mouseup: function(e) {
|
58
|
+
e.preventDefault();
|
59
|
+
return $(window).unbind(events);
|
60
|
+
},
|
61
|
+
mousemove: function(e) {
|
62
|
+
e.preventDefault();
|
63
|
+
return _this.resizeTo(e.clientY);
|
64
|
+
}
|
65
|
+
});
|
66
|
+
};
|
67
|
+
})(this)
|
68
|
+
});
|
69
|
+
this.resizeToSaved();
|
70
|
+
$('nav.app .clear a').live('click', (function(_this) {
|
71
|
+
return function(e) {
|
72
|
+
e.preventDefault();
|
73
|
+
if (confirm("You will lose all your received messages.\n\nAre you sure you want to clear all messages?")) {
|
74
|
+
return $.ajax({
|
75
|
+
url: '/messages',
|
76
|
+
type: 'DELETE',
|
77
|
+
success: function() {
|
78
|
+
return _this.unselectMessage();
|
79
|
+
},
|
80
|
+
error: function() {
|
81
|
+
return alert('Error while clearing all messages.');
|
82
|
+
}
|
83
|
+
});
|
84
|
+
}
|
85
|
+
};
|
86
|
+
})(this));
|
87
|
+
$('nav.app .quit a').live('click', (function(_this) {
|
88
|
+
return function(e) {
|
89
|
+
e.preventDefault();
|
90
|
+
if (confirm("You will lose all your received messages.\n\nAre you sure you want to quit?")) {
|
91
|
+
return $.ajax({
|
92
|
+
type: 'DELETE',
|
93
|
+
success: function() {
|
94
|
+
return location.replace($('body > header h1 a').attr('href'));
|
95
|
+
},
|
96
|
+
error: function() {
|
97
|
+
return alert('Error while quitting.');
|
98
|
+
}
|
99
|
+
});
|
100
|
+
}
|
101
|
+
};
|
102
|
+
})(this));
|
103
|
+
key('up', (function(_this) {
|
104
|
+
return function() {
|
105
|
+
if (_this.selectedMessage()) {
|
106
|
+
_this.loadMessage($('#messages tr.selected').prev().data('message-id'));
|
107
|
+
} else {
|
108
|
+
_this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
|
109
|
+
}
|
110
|
+
return false;
|
111
|
+
};
|
112
|
+
})(this));
|
113
|
+
key('down', (function(_this) {
|
114
|
+
return function() {
|
115
|
+
if (_this.selectedMessage()) {
|
116
|
+
_this.loadMessage($('#messages tr.selected').next().data('message-id'));
|
117
|
+
} else {
|
118
|
+
_this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
|
119
|
+
}
|
120
|
+
return false;
|
121
|
+
};
|
122
|
+
})(this));
|
123
|
+
key('⌘+up, ctrl+up', (function(_this) {
|
124
|
+
return function() {
|
125
|
+
_this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
|
126
|
+
return false;
|
127
|
+
};
|
128
|
+
})(this));
|
129
|
+
key('⌘+down, ctrl+down', (function(_this) {
|
130
|
+
return function() {
|
131
|
+
_this.loadMessage($('#messages tbody tr[data-message-id]:last').data('message-id'));
|
132
|
+
return false;
|
133
|
+
};
|
134
|
+
})(this));
|
135
|
+
key('left', (function(_this) {
|
136
|
+
return function() {
|
137
|
+
_this.openTab(_this.previousTab());
|
138
|
+
return false;
|
139
|
+
};
|
140
|
+
})(this));
|
141
|
+
key('right', (function(_this) {
|
142
|
+
return function() {
|
143
|
+
_this.openTab(_this.nextTab());
|
144
|
+
return false;
|
145
|
+
};
|
146
|
+
})(this));
|
147
|
+
key('backspace, delete', (function(_this) {
|
148
|
+
return function() {
|
149
|
+
var id;
|
150
|
+
id = _this.selectedMessage();
|
151
|
+
if (id != null) {
|
152
|
+
$.ajax({
|
153
|
+
url: '/messages/' + id,
|
154
|
+
type: 'DELETE',
|
155
|
+
success: function() {
|
156
|
+
var messageRow, switchTo;
|
157
|
+
messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
|
158
|
+
switchTo = messageRow.next().data('message-id') || messageRow.prev().data('message-id');
|
159
|
+
messageRow.remove();
|
160
|
+
if (switchTo) {
|
161
|
+
return _this.loadMessage(switchTo);
|
162
|
+
} else {
|
163
|
+
return _this.unselectMessage();
|
164
|
+
}
|
165
|
+
},
|
166
|
+
error: function() {
|
167
|
+
return alert('Error while removing message.');
|
168
|
+
}
|
169
|
+
});
|
170
|
+
}
|
171
|
+
return false;
|
172
|
+
};
|
173
|
+
})(this));
|
174
|
+
this.refresh();
|
175
|
+
this.subscribe();
|
176
|
+
}
|
177
|
+
|
178
|
+
MailCatcher.prototype.parseDateRegexp = /^(\d{4})[-\/\\](\d{2})[-\/\\](\d{2})(?:\s+|T)(\d{2})[:-](\d{2})[:-](\d{2})(?:([ +-]\d{2}:\d{2}|\s*\S+|Z?))?$/;
|
179
|
+
|
180
|
+
MailCatcher.prototype.parseDate = function(date) {
|
181
|
+
var match;
|
182
|
+
if (match = this.parseDateRegexp.exec(date)) {
|
183
|
+
return new Date(match[1], match[2] - 1, match[3], match[4], match[5], match[6], 0);
|
184
|
+
}
|
185
|
+
};
|
186
|
+
|
187
|
+
MailCatcher.prototype.offsetTimeZone = function(date) {
|
188
|
+
var offset;
|
189
|
+
offset = Date.now().getTimezoneOffset() * 60000;
|
190
|
+
date.setTime(date.getTime() - offset);
|
191
|
+
return date;
|
192
|
+
};
|
193
|
+
|
194
|
+
MailCatcher.prototype.formatDate = function(date) {
|
195
|
+
if (typeof date === "string") {
|
196
|
+
date && (date = this.parseDate(date));
|
197
|
+
}
|
198
|
+
date && (date = this.offsetTimeZone(date));
|
199
|
+
return date && (date = date.toString("dddd, d MMM yyyy h:mm:ss tt"));
|
200
|
+
};
|
201
|
+
|
202
|
+
MailCatcher.prototype.messagesCount = function() {
|
203
|
+
return $('#messages tr').length - 1;
|
204
|
+
};
|
205
|
+
|
206
|
+
MailCatcher.prototype.tabs = function() {
|
207
|
+
return $('#message ul').children('.tab');
|
208
|
+
};
|
209
|
+
|
210
|
+
MailCatcher.prototype.getTab = function(i) {
|
211
|
+
return $(this.tabs()[i]);
|
212
|
+
};
|
213
|
+
|
214
|
+
MailCatcher.prototype.selectedTab = function() {
|
215
|
+
return this.tabs().index($('#message li.tab.selected'));
|
216
|
+
};
|
217
|
+
|
218
|
+
MailCatcher.prototype.openTab = function(i) {
|
219
|
+
return this.getTab(i).children('a').click();
|
220
|
+
};
|
221
|
+
|
222
|
+
MailCatcher.prototype.previousTab = function(tab) {
|
223
|
+
var i;
|
224
|
+
i = tab || tab === 0 ? tab : this.selectedTab() - 1;
|
225
|
+
if (i < 0) {
|
226
|
+
i = this.tabs().length - 1;
|
227
|
+
}
|
228
|
+
if (this.getTab(i).is(":visible")) {
|
229
|
+
return i;
|
230
|
+
} else {
|
231
|
+
return this.previousTab(i - 1);
|
232
|
+
}
|
233
|
+
};
|
234
|
+
|
235
|
+
MailCatcher.prototype.nextTab = function(tab) {
|
236
|
+
var i;
|
237
|
+
i = tab ? tab : this.selectedTab() + 1;
|
238
|
+
if (i > this.tabs().length - 1) {
|
239
|
+
i = 0;
|
240
|
+
}
|
241
|
+
if (this.getTab(i).is(":visible")) {
|
242
|
+
return i;
|
243
|
+
} else {
|
244
|
+
return this.nextTab(i + 1);
|
245
|
+
}
|
246
|
+
};
|
247
|
+
|
248
|
+
MailCatcher.prototype.haveMessage = function(message) {
|
249
|
+
if (message.id != null) {
|
250
|
+
message = message.id;
|
251
|
+
}
|
252
|
+
return $("#messages tbody tr[data-message-id=\"" + message + "\"]").length > 0;
|
253
|
+
};
|
254
|
+
|
255
|
+
MailCatcher.prototype.selectedMessage = function() {
|
256
|
+
return $('#messages tr.selected').data('message-id');
|
257
|
+
};
|
258
|
+
|
259
|
+
MailCatcher.prototype.searchMessages = function(query) {
|
260
|
+
var $rows, selector, token;
|
261
|
+
selector = ((function() {
|
262
|
+
var _i, _len, _ref, _results;
|
263
|
+
_ref = query.split(/\s+/);
|
264
|
+
_results = [];
|
265
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
266
|
+
token = _ref[_i];
|
267
|
+
_results.push(":icontains('" + token + "')");
|
268
|
+
}
|
269
|
+
return _results;
|
270
|
+
})()).join("");
|
271
|
+
$rows = $("#messages tbody tr");
|
272
|
+
$rows.not(selector).hide();
|
273
|
+
return $rows.filter(selector).show();
|
274
|
+
};
|
275
|
+
|
276
|
+
MailCatcher.prototype.clearSearch = function() {
|
277
|
+
return $('#messages tbody tr').show();
|
278
|
+
};
|
279
|
+
|
280
|
+
MailCatcher.prototype.addMessage = function(message) {
|
281
|
+
return $('#messages tbody').prepend($('<tr />').attr('data-message-id', message.id.toString())).append($('<td/>').text(message.sender || "No sender").toggleClass("blank", !message.sender)).append($('<td/>').text((message.recipients || []).join(', ') || "No recipients").toggleClass("blank", !message.recipients.length)).append($('<td/>').text(message.subject || "No subject").toggleClass("blank", !message.subject)).append($('<td/>').text(this.formatDate(message.created_at)));
|
282
|
+
};
|
283
|
+
|
284
|
+
MailCatcher.prototype.scrollToRow = function(row) {
|
285
|
+
var overflow, relativePosition;
|
286
|
+
relativePosition = row.offset().top - $('#messages').offset().top;
|
287
|
+
if (relativePosition < 0) {
|
288
|
+
return $('#messages').scrollTop($('#messages').scrollTop() + relativePosition - 20);
|
289
|
+
} else {
|
290
|
+
overflow = relativePosition + row.height() - $('#messages').height();
|
291
|
+
if (overflow > 0) {
|
292
|
+
return $('#messages').scrollTop($('#messages').scrollTop() + overflow + 20);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
};
|
296
|
+
|
297
|
+
MailCatcher.prototype.unselectMessage = function() {
|
298
|
+
$('#messages tbody, #message .metadata dd').empty();
|
299
|
+
$('#message .metadata .attachments').hide();
|
300
|
+
$('#message iframe').attr('src', 'about:blank');
|
301
|
+
return null;
|
302
|
+
};
|
303
|
+
|
304
|
+
MailCatcher.prototype.loadMessage = function(id) {
|
305
|
+
var messageRow;
|
306
|
+
if ((id != null ? id.id : void 0) != null) {
|
307
|
+
id = id.id;
|
308
|
+
}
|
309
|
+
id || (id = $('#messages tr.selected').attr('data-message-id'));
|
310
|
+
if (id != null) {
|
311
|
+
$("#messages tbody tr:not([data-message-id='" + id + "'])").removeClass('selected');
|
312
|
+
messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
|
313
|
+
messageRow.addClass('selected');
|
314
|
+
this.scrollToRow(messageRow);
|
315
|
+
return $.getJSON("/messages/" + id + ".json", (function(_this) {
|
316
|
+
return function(message) {
|
317
|
+
var $ul;
|
318
|
+
if (message.recipients != null) {
|
319
|
+
message.recipients = JSON.parse(message.recipients);
|
320
|
+
}
|
321
|
+
$('#message .metadata dd.created_at').text(_this.formatDate(message.created_at));
|
322
|
+
$('#message .metadata dd.from').text(message.sender);
|
323
|
+
$('#message .metadata dd.to').text((message.recipients || []).join(', '));
|
324
|
+
$('#message .metadata dd.subject').text(message.subject);
|
325
|
+
$('#message .views .tab.format').each(function(i, el) {
|
326
|
+
var $el, format;
|
327
|
+
$el = $(el);
|
328
|
+
format = $el.attr('data-message-format');
|
329
|
+
if ($.inArray(format, message.formats) >= 0) {
|
330
|
+
$el.find('a').attr('href', "/messages/" + id + "." + format);
|
331
|
+
return $el.show();
|
332
|
+
} else {
|
333
|
+
return $el.hide();
|
334
|
+
}
|
335
|
+
});
|
336
|
+
if ($("#message .views .tab.selected:not(:visible)").length) {
|
337
|
+
$("#message .views .tab.selected").removeClass("selected");
|
338
|
+
$("#message .views .tab:visible:first").addClass("selected");
|
339
|
+
}
|
340
|
+
if (message.attachments.length) {
|
341
|
+
$ul = $('<ul/>').appendTo($('#message .metadata dd.attachments').empty());
|
342
|
+
$.each(message.attachments, function(i, attachment) {
|
343
|
+
return $ul.append($('<li>').append($('<a>').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
|
344
|
+
});
|
345
|
+
$('#message .metadata .attachments').show();
|
346
|
+
} else {
|
347
|
+
$('#message .metadata .attachments').hide();
|
348
|
+
}
|
349
|
+
$('#message .views .download a').attr('href', "/messages/" + id + ".eml");
|
350
|
+
if ($('#message .views .tab.analysis.selected').length) {
|
351
|
+
return _this.loadMessageAnalysis();
|
352
|
+
} else {
|
353
|
+
return _this.loadMessageBody();
|
354
|
+
}
|
355
|
+
};
|
356
|
+
})(this));
|
357
|
+
}
|
358
|
+
};
|
359
|
+
|
360
|
+
MailCatcher.prototype.loadMessageBody = function(id, format) {
|
361
|
+
var app;
|
362
|
+
id || (id = this.selectedMessage());
|
363
|
+
format || (format = $('#message .views .tab.format.selected').attr('data-message-format'));
|
364
|
+
format || (format = 'html');
|
365
|
+
$("#message .views .tab[data-message-format=\"" + format + "\"]:not(.selected)").addClass('selected');
|
366
|
+
$("#message .views .tab:not([data-message-format=\"" + format + "\"]).selected").removeClass('selected');
|
367
|
+
if (id != null) {
|
368
|
+
$('#message iframe').attr("src", "/messages/" + id + "." + format);
|
369
|
+
return app = this;
|
370
|
+
}
|
371
|
+
};
|
372
|
+
|
373
|
+
MailCatcher.prototype.decorateMessageBody = function() {
|
374
|
+
var body, format, message_iframe, text;
|
375
|
+
format = $('#message .views .tab.format.selected').attr('data-message-format');
|
376
|
+
switch (format) {
|
377
|
+
case 'html':
|
378
|
+
body = $('#message iframe').contents().find('body');
|
379
|
+
return $("a", body).attr("target", "_blank");
|
380
|
+
case 'plain':
|
381
|
+
message_iframe = $('#message iframe').contents();
|
382
|
+
text = message_iframe.text();
|
383
|
+
text = text.replace(/((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?)/g, '<a href="$1" target="_blank">$1</a>');
|
384
|
+
text = text.replace(/\n/g, '<br/>');
|
385
|
+
return message_iframe.find('html').html('<html><body>' + text + '</html></body>');
|
386
|
+
}
|
387
|
+
};
|
388
|
+
|
389
|
+
MailCatcher.prototype.loadMessageAnalysis = function(id) {
|
390
|
+
var $form, $iframe;
|
391
|
+
id || (id = this.selectedMessage());
|
392
|
+
$("#message .views .analysis.tab:not(.selected)").addClass('selected');
|
393
|
+
$("#message .views :not(.analysis).tab.selected").removeClass('selected');
|
394
|
+
if (id != null) {
|
395
|
+
$iframe = $('#message iframe').contents().children().html("<html>\n<head>\n<title>Analysis</title>\n" + ($('link[rel="stylesheet"]')[0].outerHTML) + "\n</head>\n<body class=\"iframe\">\n<h1>Analyse your email with Fractal</h1>\n<p><a href=\"http://getfractal.com/\" target=\"_blank\">Fractal</a> is a really neat service that applies common email design and development knowledge from <a href=\"http://www.email-standards.org/\" target=\"_blank\">Email Standards Project</a> to your HTML email and tells you what you've done wrong or what you should do instead.</p>\n<p>Please note that this <strong>sends your email to the Fractal service</strong> for analysis. Read their <a href=\"https://www.getfractal.com/page/terms\" target=\"_blank\">terms of service</a> if you're paranoid.</p>\n<form>\n<input type=\"submit\" value=\"Analyse\" /><span class=\"loading\" style=\"color: #999; display: none\">Analysing…</span>\n</form>\n</body>\n</html>");
|
396
|
+
return $form = $iframe.find('form').submit(function(e) {
|
397
|
+
e.preventDefault();
|
398
|
+
$(this).find('input[type="submit"]').attr('disabled', 'disabled').end().find('.loading').show();
|
399
|
+
return $('#message iframe').contents().find('body').xslt("/messages/" + id + "/analysis.xml", "/stylesheets/analysis.xsl");
|
400
|
+
});
|
401
|
+
}
|
402
|
+
};
|
403
|
+
|
404
|
+
MailCatcher.prototype.refresh = function() {
|
405
|
+
return $.getJSON('/messages', (function(_this) {
|
406
|
+
return function(messages) {
|
407
|
+
return $.each(messages, function(i, message) {
|
408
|
+
if (!_this.haveMessage(message)) {
|
409
|
+
if (message.recipients != null) {
|
410
|
+
message.recipients = JSON.parse(message.recipients);
|
411
|
+
}
|
412
|
+
return _this.addMessage(message);
|
413
|
+
}
|
414
|
+
});
|
415
|
+
};
|
416
|
+
})(this));
|
417
|
+
};
|
418
|
+
|
419
|
+
MailCatcher.prototype.subscribe = function() {
|
420
|
+
if (typeof WebSocket !== "undefined" && WebSocket !== null) {
|
421
|
+
|
422
|
+
} else {
|
423
|
+
return this.subscribePoll();
|
424
|
+
}
|
425
|
+
};
|
426
|
+
|
427
|
+
MailCatcher.prototype.subscribeWebSocket = function() {
|
428
|
+
var secure;
|
429
|
+
secure = window.location.scheme === 'https';
|
430
|
+
this.websocket = new WebSocket("" + (secure ? 'wss' : 'ws') + "://" + window.location.host + "/messages");
|
431
|
+
return this.websocket.onmessage = (function(_this) {
|
432
|
+
return function(event) {
|
433
|
+
return _this.addMessage($.parseJSON(event.data));
|
434
|
+
};
|
435
|
+
})(this);
|
436
|
+
};
|
437
|
+
|
438
|
+
MailCatcher.prototype.subscribePoll = function() {
|
439
|
+
if (this.refreshInterval == null) {
|
440
|
+
return this.refreshInterval = setInterval(((function(_this) {
|
441
|
+
return function() {
|
442
|
+
return _this.refresh();
|
443
|
+
};
|
444
|
+
})(this)), 1000);
|
445
|
+
}
|
446
|
+
};
|
447
|
+
|
448
|
+
MailCatcher.prototype.resizeToSavedKey = 'mailcatcherSeparatorHeight';
|
449
|
+
|
450
|
+
MailCatcher.prototype.resizeTo = function(height) {
|
451
|
+
var _ref;
|
452
|
+
$('#messages').css({
|
453
|
+
height: height - $('#messages').offset().top
|
454
|
+
});
|
455
|
+
return (_ref = window.localStorage) != null ? _ref.setItem(this.resizeToSavedKey, height) : void 0;
|
456
|
+
};
|
457
|
+
|
458
|
+
MailCatcher.prototype.resizeToSaved = function() {
|
459
|
+
var height, _ref;
|
460
|
+
height = parseInt((_ref = window.localStorage) != null ? _ref.getItem(this.resizeToSavedKey) : void 0);
|
461
|
+
if (!isNaN(height)) {
|
462
|
+
return this.resizeTo(height);
|
463
|
+
}
|
464
|
+
};
|
465
|
+
|
466
|
+
return MailCatcher;
|
467
|
+
|
468
|
+
})();
|
469
|
+
|
470
|
+
$(function() {
|
471
|
+
return window.MailCatcher = new MailCatcher;
|
472
|
+
});
|
473
|
+
|
474
|
+
}).call(this);
|