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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 08d2302a67b12fe5f7526c85990fdd00dc36f09d
4
- data.tar.gz: a8b507672ac95619a351250630b58e17ebf06a13
3
+ metadata.gz: 0b12132d30e684f47cc6409c240b0684615fb436
4
+ data.tar.gz: 11958f289b65ecf2f04958d1a9a05eaa3813392c
5
5
  SHA512:
6
- metadata.gz: 45dad7c9b750c0f9f65c4f64666c9ef11a17c2a6449e1ed4ca2a24dc93ca2e089b8387d477b2ece2b6b269ae8454999c36d8ee5ef2d2a4d0ce46ce0579bcda82
7
- data.tar.gz: 2bb109596422c4eb875ef6846602c1f09d4b20976743ee98a1e6f9b9707c80086b18ff63a562f0e2b5861a889fe84d09d02ada267f3a2bbb5e2feb44affde68b
6
+ metadata.gz: 6027fc8fdb637e18dcc60a37973dd16bf9a7942c17f25e453e669cda48881ba92e9fa7f13366e1dfe7a4501a15c8d422bb0cc4571abe643cc79df00d867d5502
7
+ data.tar.gz: 7cf61262e58f58ed09b76bb4ed9a493bb34c827280c83fb457201c9e2e98735917b86c9c646991448fe48fcb58de0ee2130bd5773af88723aa4fe1935319910a
@@ -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: 20 }
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
@@ -1,3 +1,3 @@
1
1
  module MailCatcher
2
- VERSION = "1.1.3"
2
+ VERSION = "1.1.4"
3
3
  end
@@ -11,6 +11,8 @@ class Sinatra::Request
11
11
  end
12
12
 
13
13
  class MailCatcher::Web < Sinatra::Base
14
+ use ActiveRecord::ConnectionAdapters::ConnectionManagement
15
+
14
16
  set :root, File.expand_path("#{__FILE__}/../../..")
15
17
  set :haml, :format => :html5
16
18
 
@@ -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
- var _this = this;
18
- $('#messages tr').live('click', function(e) {
19
- e.preventDefault();
20
- return _this.loadMessage($(e.currentTarget).attr('data-message-id'));
21
- });
22
- $('input[name=search]').keyup(function(e) {
23
- var query;
24
- query = $.trim($(e.currentTarget).val());
25
- if (query) {
26
- return _this.searchMessages(query);
27
- } else {
28
- return _this.clearSearch();
29
- }
30
- });
31
- $('#message .views .format.tab a').live('click', function(e) {
32
- e.preventDefault();
33
- return _this.loadMessageBody(_this.selectedMessage(), $($(e.currentTarget).parent('li')).data('message-format'));
34
- });
35
- $('#message .views .analysis.tab a').live('click', function(e) {
36
- e.preventDefault();
37
- return _this.loadMessageAnalysis(_this.selectedMessage());
38
- });
39
- $('#message iframe').load(function() {
40
- return _this.decorateMessageBody();
41
- });
42
- $('#resizer').live({
43
- mousedown: function(e) {
44
- var events;
45
- e.preventDefault();
46
- return $(window).bind(events = {
47
- mouseup: function(e) {
48
- e.preventDefault();
49
- return $(window).unbind(events);
50
- },
51
- mousemove: function(e) {
52
- e.preventDefault();
53
- return _this.resizeTo(e.clientY);
54
- }
55
- });
56
- }
57
- });
58
- this.resizeToSaved();
59
- $('nav.app .clear a').live('click', function(e) {
60
- e.preventDefault();
61
- if (confirm("You will lose all your received messages.\n\nAre you sure you want to clear all messages?")) {
62
- return $.ajax({
63
- url: '/messages',
64
- type: 'DELETE',
65
- success: function() {
66
- return _this.unselectMessage();
67
- },
68
- error: function() {
69
- return alert('Error while clearing all messages.');
70
- }
71
- });
72
- }
73
- });
74
- $('nav.app .quit a').live('click', function(e) {
75
- e.preventDefault();
76
- if (confirm("You will lose all your received messages.\n\nAre you sure you want to quit?")) {
77
- return $.ajax({
78
- type: 'DELETE',
79
- success: function() {
80
- return location.replace($('body > header h1 a').attr('href'));
81
- },
82
- error: function() {
83
- return alert('Error while quitting.');
84
- }
85
- });
86
- }
87
- });
88
- key('up', function() {
89
- if (_this.selectedMessage()) {
90
- _this.loadMessage($('#messages tr.selected').prev().data('message-id'));
91
- } else {
92
- _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
93
- }
94
- return false;
95
- });
96
- key('down', function() {
97
- if (_this.selectedMessage()) {
98
- _this.loadMessage($('#messages tr.selected').next().data('message-id'));
99
- } else {
100
- _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
101
- }
102
- return false;
103
- });
104
- key('Γîÿ+up, ctrl+up', function() {
105
- _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
106
- return false;
107
- });
108
- key('Γîÿ+down, ctrl+down', function() {
109
- _this.loadMessage($('#messages tbody tr[data-message-id]:last').data('message-id'));
110
- return false;
111
- });
112
- key('left', function() {
113
- _this.openTab(_this.previousTab());
114
- return false;
115
- });
116
- key('right', function() {
117
- _this.openTab(_this.nextTab());
118
- return false;
119
- });
120
- key('backspace, delete', function() {
121
- var id;
122
- id = _this.selectedMessage();
123
- if (id != null) {
124
- $.ajax({
125
- url: '/messages/' + id,
126
- type: 'DELETE',
127
- success: function() {
128
- var messageRow, switchTo;
129
- messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
130
- switchTo = messageRow.next().data('message-id') || messageRow.prev().data('message-id');
131
- messageRow.remove();
132
- if (switchTo) {
133
- return _this.loadMessage(switchTo);
134
- } else {
135
- return _this.unselectMessage();
136
- }
137
- },
138
- error: function() {
139
- return alert('Error while removing message.');
140
- }
141
- });
142
- }
143
- return false;
144
- });
145
- this.refresh();
146
- this.subscribe();
147
- }
148
-
149
- MailCatcher.prototype.parseDateRegexp = /^(\d{4})[-\/\\](\d{2})[-\/\\](\d{2})(?:\s+|T)(\d{2})[:-](\d{2})[:-](\d{2})(?:([ +-]\d{2}:\d{2}|\s*\S+|Z?))?$/;
150
-
151
- MailCatcher.prototype.parseDate = function(date) {
152
- var match;
153
- if (match = this.parseDateRegexp.exec(date)) {
154
- return new Date(match[1], match[2] - 1, match[3], match[4], match[5], match[6], 0);
155
- }
156
- };
157
-
158
- MailCatcher.prototype.offsetTimeZone = function(date) {
159
- var offset;
160
- offset = Date.now().getTimezoneOffset() * 60000;
161
- date.setTime(date.getTime() - offset);
162
- return date;
163
- };
164
-
165
- MailCatcher.prototype.formatDate = function(date) {
166
- if (typeof date === "string") {
167
- date && (date = this.parseDate(date));
168
- }
169
- date && (date = this.offsetTimeZone(date));
170
- return date && (date = date.toString("dddd, d MMM yyyy h:mm:ss tt"));
171
- };
172
-
173
- MailCatcher.prototype.messagesCount = function() {
174
- return $('#messages tr').length - 1;
175
- };
176
-
177
- MailCatcher.prototype.tabs = function() {
178
- return $('#message ul').children('.tab');
179
- };
180
-
181
- MailCatcher.prototype.getTab = function(i) {
182
- return $(this.tabs()[i]);
183
- };
184
-
185
- MailCatcher.prototype.selectedTab = function() {
186
- return this.tabs().index($('#message li.tab.selected'));
187
- };
188
-
189
- MailCatcher.prototype.openTab = function(i) {
190
- return this.getTab(i).children('a').click();
191
- };
192
-
193
- MailCatcher.prototype.previousTab = function(tab) {
194
- var i;
195
- i = tab || tab === 0 ? tab : this.selectedTab() - 1;
196
- if (i < 0) {
197
- i = this.tabs().length - 1;
198
- }
199
- if (this.getTab(i).is(":visible")) {
200
- return i;
201
- } else {
202
- return this.previousTab(i - 1);
203
- }
204
- };
205
-
206
- MailCatcher.prototype.nextTab = function(tab) {
207
- var i;
208
- i = tab ? tab : this.selectedTab() + 1;
209
- if (i > this.tabs().length - 1) {
210
- i = 0;
211
- }
212
- if (this.getTab(i).is(":visible")) {
213
- return i;
214
- } else {
215
- return this.nextTab(i + 1);
216
- }
217
- };
218
-
219
- MailCatcher.prototype.haveMessage = function(message) {
220
- if (message.id != null) {
221
- message = message.id;
222
- }
223
- return $("#messages tbody tr[data-message-id=\"" + message + "\"]").length > 0;
224
- };
225
-
226
- MailCatcher.prototype.selectedMessage = function() {
227
- return $('#messages tr.selected').data('message-id');
228
- };
229
-
230
- MailCatcher.prototype.searchMessages = function(query) {
231
- var $rows, selector, token;
232
- selector = ((function() {
233
- var _i, _len, _ref, _results;
234
- _ref = query.split(/\s+/);
235
- _results = [];
236
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
237
- token = _ref[_i];
238
- _results.push(":icontains('" + token + "')");
239
- }
240
- return _results;
241
- })()).join("");
242
- $rows = $("#messages tbody tr");
243
- $rows.not(selector).hide();
244
- return $rows.filter(selector).show();
245
- };
246
-
247
- MailCatcher.prototype.clearSearch = function() {
248
- return $('#messages tbody tr').show();
249
- };
250
-
251
- MailCatcher.prototype.addMessage = function(message) {
252
- 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))));
253
- };
254
-
255
- MailCatcher.prototype.scrollToRow = function(row) {
256
- var overflow, relativePosition;
257
- relativePosition = row.offset().top - $('#messages').offset().top;
258
- if (relativePosition < 0) {
259
- return $('#messages').scrollTop($('#messages').scrollTop() + relativePosition - 20);
260
- } else {
261
- overflow = relativePosition + row.height() - $('#messages').height();
262
- if (overflow > 0) {
263
- return $('#messages').scrollTop($('#messages').scrollTop() + overflow + 20);
264
- }
265
- }
266
- };
267
-
268
- MailCatcher.prototype.unselectMessage = function() {
269
- $('#messages tbody, #message .metadata dd').empty();
270
- $('#message .metadata .attachments').hide();
271
- $('#message iframe').attr('src', 'about:blank');
272
- return null;
273
- };
274
-
275
- MailCatcher.prototype.loadMessage = function(id) {
276
- var messageRow,
277
- _this = this;
278
- if ((id != null ? id.id : void 0) != null) {
279
- id = id.id;
280
- }
281
- id || (id = $('#messages tr.selected').attr('data-message-id'));
282
- if (id != null) {
283
- $("#messages tbody tr:not([data-message-id='" + id + "'])").removeClass('selected');
284
- messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
285
- messageRow.addClass('selected');
286
- this.scrollToRow(messageRow);
287
- return $.getJSON("/messages/" + id + ".json", function(message) {
288
- var $ul;
289
- if (message.recipients != null) {
290
- message.recipients = JSON.parse(message.recipients);
291
- }
292
- $('#message .metadata dd.created_at').text(_this.formatDate(message.created_at));
293
- $('#message .metadata dd.from').text(message.sender);
294
- $('#message .metadata dd.to').text((message.recipients || []).join(', '));
295
- $('#message .metadata dd.subject').text(message.subject);
296
- $('#message .views .tab.format').each(function(i, el) {
297
- var $el, format;
298
- $el = $(el);
299
- format = $el.attr('data-message-format');
300
- if ($.inArray(format, message.formats) >= 0) {
301
- $el.find('a').attr('href', "/messages/" + id + "." + format);
302
- return $el.show();
303
- } else {
304
- return $el.hide();
305
- }
306
- });
307
- if ($("#message .views .tab.selected:not(:visible)").length) {
308
- $("#message .views .tab.selected").removeClass("selected");
309
- $("#message .views .tab:visible:first").addClass("selected");
310
- }
311
- if (message.attachments.length) {
312
- $ul = $('<ul/>').appendTo($('#message .metadata dd.attachments').empty());
313
- $.each(message.attachments, function(i, attachment) {
314
- return $ul.append($('<li>').append($('<a>').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
315
- });
316
- $('#message .metadata .attachments').show();
317
- } else {
318
- $('#message .metadata .attachments').hide();
319
- }
320
- $('#message .views .download a').attr('href', "/messages/" + id + ".eml");
321
- if ($('#message .views .tab.analysis.selected').length) {
322
- return _this.loadMessageAnalysis();
323
- } else {
324
- return _this.loadMessageBody();
325
- }
326
- });
327
- }
328
- };
329
-
330
- MailCatcher.prototype.loadMessageBody = function(id, format) {
331
- var app;
332
- id || (id = this.selectedMessage());
333
- format || (format = $('#message .views .tab.format.selected').attr('data-message-format'));
334
- format || (format = 'html');
335
- $("#message .views .tab[data-message-format=\"" + format + "\"]:not(.selected)").addClass('selected');
336
- $("#message .views .tab:not([data-message-format=\"" + format + "\"]).selected").removeClass('selected');
337
- if (id != null) {
338
- $('#message iframe').attr("src", "/messages/" + id + "." + format);
339
- return app = this;
340
- }
341
- };
342
-
343
- MailCatcher.prototype.decorateMessageBody = function() {
344
- var body, format, message_iframe, text;
345
- format = $('#message .views .tab.format.selected').attr('data-message-format');
346
- switch (format) {
347
- case 'html':
348
- body = $('#message iframe').contents().find('body');
349
- return $("a", body).attr("target", "_blank");
350
- case 'plain':
351
- message_iframe = $('#message iframe').contents();
352
- text = message_iframe.text();
353
- text = text.replace(/((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#])?)/g, '<a href="$1" target="_blank">$1</a>');
354
- text = text.replace(/\n/g, '<br/>');
355
- return message_iframe.find('html').html('<html><body>' + text + '</html></body>');
356
- }
357
- };
358
-
359
- MailCatcher.prototype.loadMessageAnalysis = function(id) {
360
- var $form, $iframe;
361
- id || (id = this.selectedMessage());
362
- $("#message .views .analysis.tab:not(.selected)").addClass('selected');
363
- $("#message .views :not(.analysis).tab.selected").removeClass('selected');
364
- if (id != null) {
365
- $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&hellip;</span>\n</form>\n</body>\n</html>");
366
- return $form = $iframe.find('form').submit(function(e) {
367
- e.preventDefault();
368
- $(this).find('input[type="submit"]').attr('disabled', 'disabled').end().find('.loading').show();
369
- return $('#message iframe').contents().find('body').xslt("/messages/" + id + "/analysis.xml", "/stylesheets/analysis.xsl");
370
- });
371
- }
372
- };
373
-
374
- MailCatcher.prototype.refresh = function() {
375
- var _this = this;
376
- return $.getJSON('/messages', function(messages) {
377
- return $.each(messages, function(i, message) {
378
- if (!_this.haveMessage(message)) {
379
- if (message.recipients != null) {
380
- message.recipients = JSON.parse(message.recipients);
381
- }
382
- return _this.addMessage(message);
383
- }
384
- });
385
- });
386
- };
387
-
388
- MailCatcher.prototype.subscribe = function() {
389
- if (typeof WebSocket !== "undefined" && WebSocket !== null) {
390
- return this.subscribeWebSocket();
391
- } else {
392
- return this.subscribePoll();
393
- }
394
- };
395
-
396
- MailCatcher.prototype.subscribeWebSocket = function() {
397
- var secure,
398
- _this = this;
399
- secure = window.location.scheme === 'https';
400
- this.websocket = new WebSocket("" + (secure ? 'wss' : 'ws') + "://" + window.location.host + "/messages");
401
- return this.websocket.onmessage = function(event) {
402
- return _this.addMessage($.parseJSON(event.data));
403
- };
404
- };
405
-
406
- MailCatcher.prototype.subscribePoll = function() {
407
- var _this = this;
408
- if (this.refreshInterval == null) {
409
- return this.refreshInterval = setInterval((function() {
410
- return _this.refresh();
411
- }), 1000);
412
- }
413
- };
414
-
415
- MailCatcher.prototype.resizeToSavedKey = 'mailcatcherSeparatorHeight';
416
-
417
- MailCatcher.prototype.resizeTo = function(height) {
418
- var _ref;
419
- $('#messages').css({
420
- height: height - $('#messages').offset().top
421
- });
422
- return (_ref = window.localStorage) != null ? _ref.setItem(this.resizeToSavedKey, height) : void 0;
423
- };
424
-
425
- MailCatcher.prototype.resizeToSaved = function() {
426
- var height, _ref;
427
- height = parseInt((_ref = window.localStorage) != null ? _ref.getItem(this.resizeToSavedKey) : void 0);
428
- if (!isNaN(height)) {
429
- return this.resizeTo(height);
430
- }
431
- };
432
-
433
- return MailCatcher;
434
-
435
- })();
436
-
437
- $(function() {
438
- return window.MailCatcher = new MailCatcher;
439
- });
440
-
441
- }).call(this);
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\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#])?)/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&hellip;</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);