mailcatcher 0.5.6 → 0.5.7
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.
- data/README.md +1 -0
- data/VERSION +1 -1
- data/lib/mail_catcher.rb +35 -10
- data/lib/mail_catcher/smtp.rb +11 -0
- data/public/javascripts/application.js +118 -66
- data/public/javascripts/keymaster.min.js +4 -0
- data/views/index.haml +1 -0
- metadata +95 -30
data/README.md
CHANGED
@@ -20,6 +20,7 @@ MailCatcher runs a super simple SMTP server which catches any message sent to it
|
|
20
20
|
* Runs as a daemon run in the background.
|
21
21
|
* Sendmail-analogue command, `catchmail`, makes [using mailcatcher from PHP][withphp] a lot easier.
|
22
22
|
* Written super-simply in EventMachine, easy to dig in and change.
|
23
|
+
* Keyboard navigation between messages
|
23
24
|
|
24
25
|
## How
|
25
26
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.7
|
data/lib/mail_catcher.rb
CHANGED
@@ -15,6 +15,10 @@ module MailCatcher
|
|
15
15
|
|
16
16
|
module_function
|
17
17
|
|
18
|
+
def which command
|
19
|
+
IO.popen(["which", command], "r", :err => :close).read.chomp.presence
|
20
|
+
end
|
21
|
+
|
18
22
|
def mac?
|
19
23
|
RbConfig::CONFIG['host_os'] =~ /darwin/
|
20
24
|
end
|
@@ -28,17 +32,23 @@ module_function
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def growlnotify?
|
31
|
-
|
35
|
+
which "growlnotify"
|
32
36
|
end
|
33
37
|
|
34
|
-
def
|
35
|
-
|
36
|
-
# TODO: Look for growl framework accessible
|
37
|
-
false
|
38
|
+
def growl?
|
39
|
+
growlnotify?
|
38
40
|
end
|
39
41
|
|
40
|
-
def
|
41
|
-
|
42
|
+
def browse?
|
43
|
+
windows? or which "open"
|
44
|
+
end
|
45
|
+
|
46
|
+
def browse url
|
47
|
+
if windows?
|
48
|
+
system "start", "/b", url
|
49
|
+
elsif which "open"
|
50
|
+
system "open", url
|
51
|
+
end
|
42
52
|
end
|
43
53
|
|
44
54
|
@@defaults = {
|
@@ -49,6 +59,7 @@ module_function
|
|
49
59
|
:verbose => false,
|
50
60
|
:daemon => !windows?,
|
51
61
|
:growl => growlnotify?,
|
62
|
+
:browse => false,
|
52
63
|
}
|
53
64
|
|
54
65
|
def parse! arguments=ARGV, defaults=@@defaults
|
@@ -96,6 +107,12 @@ module_function
|
|
96
107
|
end
|
97
108
|
end
|
98
109
|
|
110
|
+
if browse?
|
111
|
+
parser.on('-b', '--browse', 'Open web browser') do
|
112
|
+
options[:browse] = true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
99
116
|
parser.on('-v', '--verbose', 'Be more verbose') do
|
100
117
|
options[:verbose] = true
|
101
118
|
end
|
@@ -123,19 +140,27 @@ module_function
|
|
123
140
|
# Get our lion on if asked
|
124
141
|
MailCatcher::Growl.start if options[:growl]
|
125
142
|
|
126
|
-
|
143
|
+
smtp_url = "smtp://#{options[:smtp_ip]}:#{options[:smtp_port]}"
|
144
|
+
http_url = "http://#{options[:http_ip]}:#{options[:http_port]}"
|
127
145
|
|
128
146
|
# Set up an SMTP server to run within EventMachine
|
129
147
|
rescue_port options[:smtp_port] do
|
130
148
|
EventMachine.start_server options[:smtp_ip], options[:smtp_port], Smtp
|
131
|
-
puts "==>
|
149
|
+
puts "==> #{smtp_url}"
|
132
150
|
end
|
133
151
|
|
134
152
|
# Let Thin set itself up inside our EventMachine loop
|
135
153
|
# (Skinny/WebSockets just works on the inside)
|
136
154
|
rescue_port options[:http_port] do
|
137
155
|
Thin::Server.start options[:http_ip], options[:http_port], Web
|
138
|
-
puts "==>
|
156
|
+
puts "==> #{http_url}"
|
157
|
+
end
|
158
|
+
|
159
|
+
# Open the web browser before detatching console
|
160
|
+
if options[:browse]
|
161
|
+
EventMachine.next_tick do
|
162
|
+
browse http_url
|
163
|
+
end
|
139
164
|
end
|
140
165
|
|
141
166
|
# Daemonize, if we should, but only after the servers have started.
|
data/lib/mail_catcher/smtp.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
|
3
3
|
class MailCatcher::Smtp < EventMachine::Protocols::SmtpServer
|
4
|
+
# We override EM's mail from processing to allow multiple mail-from commands
|
5
|
+
# per [RFC 2821](http://tools.ietf.org/html/rfc2821#section-4.1.1.2)
|
6
|
+
def process_mail_from sender
|
7
|
+
if @state.include? :mail_from
|
8
|
+
@state -= [:mail_from, :rcpt, :data]
|
9
|
+
receive_reset
|
10
|
+
end
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
4
15
|
def current_message
|
5
16
|
@current_message ||= {}
|
6
17
|
end
|
@@ -1,36 +1,37 @@
|
|
1
1
|
(function() {
|
2
2
|
var MailCatcher;
|
3
|
-
|
3
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
4
4
|
jQuery.expr[':'].icontains = function(a, i, m) {
|
5
5
|
var _ref, _ref2;
|
6
6
|
return ((_ref = (_ref2 = a.textContent) != null ? _ref2 : a.innerText) != null ? _ref : "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
|
7
7
|
};
|
8
|
-
|
9
8
|
MailCatcher = (function() {
|
10
|
-
|
11
9
|
function MailCatcher() {
|
12
|
-
|
13
|
-
|
10
|
+
this.nextTab = __bind(this.nextTab, this);;
|
11
|
+
this.previousTab = __bind(this.previousTab, this);;
|
12
|
+
this.openTab = __bind(this.openTab, this);;
|
13
|
+
this.selectedTab = __bind(this.selectedTab, this);;
|
14
|
+
this.getTab = __bind(this.getTab, this);; $('#messages tr').live('click', __bind(function(e) {
|
14
15
|
e.preventDefault();
|
15
|
-
return
|
16
|
-
});
|
17
|
-
$('input[name=search]').keyup(function(e) {
|
16
|
+
return this.loadMessage($(e.currentTarget).attr('data-message-id'));
|
17
|
+
}, this));
|
18
|
+
$('input[name=search]').keyup(__bind(function(e) {
|
18
19
|
var query;
|
19
20
|
query = $.trim($(e.currentTarget).val());
|
20
21
|
if (query) {
|
21
|
-
return
|
22
|
+
return this.searchMessages(query);
|
22
23
|
} else {
|
23
|
-
return
|
24
|
+
return this.clearSearch();
|
24
25
|
}
|
25
|
-
});
|
26
|
-
$('#message .views .format.tab a').live('click', function(e) {
|
26
|
+
}, this));
|
27
|
+
$('#message .views .format.tab a').live('click', __bind(function(e) {
|
27
28
|
e.preventDefault();
|
28
|
-
return
|
29
|
-
});
|
30
|
-
$('#message .views .analysis.tab a').live('click', function(e) {
|
29
|
+
return this.loadMessageBody(this.selectedMessage(), $($(e.currentTarget).parent('li')).data('message-format'));
|
30
|
+
}, this));
|
31
|
+
$('#message .views .analysis.tab a').live('click', __bind(function(e) {
|
31
32
|
e.preventDefault();
|
32
|
-
return
|
33
|
-
});
|
33
|
+
return this.loadMessageAnalysis(this.selectedMessage());
|
34
|
+
}, this));
|
34
35
|
$('#resizer').live({
|
35
36
|
mousedown: function(e) {
|
36
37
|
var events;
|
@@ -49,7 +50,7 @@
|
|
49
50
|
});
|
50
51
|
}
|
51
52
|
});
|
52
|
-
$('nav.app .clear a').live('click', function(e) {
|
53
|
+
$('nav.app .clear a').live('click', __bind(function(e) {
|
53
54
|
e.preventDefault();
|
54
55
|
if (confirm("You will lose all your received messages.\n\nAre you sure you want to clear all messages?")) {
|
55
56
|
return $.ajax({
|
@@ -65,8 +66,8 @@
|
|
65
66
|
}
|
66
67
|
});
|
67
68
|
}
|
68
|
-
});
|
69
|
-
$('nav.app .quit a').live('click', function(e) {
|
69
|
+
}, this));
|
70
|
+
$('nav.app .quit a').live('click', __bind(function(e) {
|
70
71
|
e.preventDefault();
|
71
72
|
if (confirm("You will lose all your received messages.\n\nAre you sure you want to quit?")) {
|
72
73
|
return $.ajax({
|
@@ -79,42 +80,106 @@
|
|
79
80
|
}
|
80
81
|
});
|
81
82
|
}
|
82
|
-
});
|
83
|
+
}, this));
|
84
|
+
key('up', __bind(function() {
|
85
|
+
var id;
|
86
|
+
id = this.selectedMessage() || 1;
|
87
|
+
if (id > 1) {
|
88
|
+
id -= 1;
|
89
|
+
}
|
90
|
+
return this.loadMessage(id);
|
91
|
+
}, this));
|
92
|
+
key('down', __bind(function() {
|
93
|
+
var id;
|
94
|
+
id = this.selectedMessage() || this.messagesCount();
|
95
|
+
if (id < this.messagesCount()) {
|
96
|
+
id += 1;
|
97
|
+
}
|
98
|
+
return this.loadMessage(id);
|
99
|
+
}, this));
|
100
|
+
key('⌘+up, ctrl+up', __bind(function() {
|
101
|
+
return this.loadMessage(1);
|
102
|
+
}, this));
|
103
|
+
key('⌘+down, ctrl+down', __bind(function() {
|
104
|
+
return this.loadMessage(this.messagesCount());
|
105
|
+
}, this));
|
106
|
+
key('left', __bind(function() {
|
107
|
+
return this.openTab(this.previousTab());
|
108
|
+
}, this));
|
109
|
+
key('right', __bind(function() {
|
110
|
+
return this.openTab(this.nextTab());
|
111
|
+
}, this));
|
83
112
|
this.refresh();
|
84
113
|
this.subscribe();
|
85
114
|
}
|
86
|
-
|
87
115
|
MailCatcher.prototype.parseDateRegexp = /^(\d{4})[-\/\\](\d{2})[-\/\\](\d{2})(?:\s+|T)(\d{2})[:-](\d{2})[:-](\d{2})(?:([ +-]\d{2}:\d{2}|\s*\S+|Z?))?$/;
|
88
|
-
|
89
116
|
MailCatcher.prototype.parseDate = function(date) {
|
90
117
|
var match;
|
91
118
|
if (match = this.parseDateRegexp.exec(date)) {
|
92
119
|
return new Date(match[1], match[2] - 1, match[3], match[4], match[5], match[6], 0);
|
93
120
|
}
|
94
121
|
};
|
95
|
-
|
96
122
|
MailCatcher.prototype.offsetTimeZone = function(date) {
|
97
123
|
var offset;
|
98
124
|
offset = Date.now().getTimezoneOffset() * 60000;
|
99
125
|
date.setTime(date.getTime() - offset);
|
100
126
|
return date;
|
101
127
|
};
|
102
|
-
|
103
128
|
MailCatcher.prototype.formatDate = function(date) {
|
104
|
-
if (typeof date === "string")
|
129
|
+
if (typeof date === "string") {
|
130
|
+
date && (date = this.parseDate(date));
|
131
|
+
}
|
105
132
|
date && (date = this.offsetTimeZone(date));
|
106
133
|
return date && (date = date.toString("dddd, d MMM yyyy h:mm:ss tt"));
|
107
134
|
};
|
108
|
-
|
135
|
+
MailCatcher.prototype.messagesCount = function() {
|
136
|
+
return $('#messages tr').length - 1;
|
137
|
+
};
|
138
|
+
MailCatcher.prototype.tabs = function() {
|
139
|
+
return $('#message ul').children('.tab');
|
140
|
+
};
|
141
|
+
MailCatcher.prototype.getTab = function(i) {
|
142
|
+
return $(this.tabs()[i]);
|
143
|
+
};
|
144
|
+
MailCatcher.prototype.selectedTab = function() {
|
145
|
+
return this.tabs().index($('#message li.tab.selected'));
|
146
|
+
};
|
147
|
+
MailCatcher.prototype.openTab = function(i) {
|
148
|
+
return this.getTab(i).children('a').click();
|
149
|
+
};
|
150
|
+
MailCatcher.prototype.previousTab = function(tab) {
|
151
|
+
var i;
|
152
|
+
i = tab || tab === 0 ? tab : this.selectedTab() - 1;
|
153
|
+
if (i < 0) {
|
154
|
+
i = this.tabs().length - 1;
|
155
|
+
}
|
156
|
+
if (this.getTab(i).is(":visible")) {
|
157
|
+
return i;
|
158
|
+
} else {
|
159
|
+
return this.previousTab(i - 1);
|
160
|
+
}
|
161
|
+
};
|
162
|
+
MailCatcher.prototype.nextTab = function(tab) {
|
163
|
+
var i;
|
164
|
+
i = tab ? tab : this.selectedTab() + 1;
|
165
|
+
if (i > this.tabs().length - 1) {
|
166
|
+
i = 0;
|
167
|
+
}
|
168
|
+
if (this.getTab(i).is(":visible")) {
|
169
|
+
return i;
|
170
|
+
} else {
|
171
|
+
return this.nextTab(i + 1);
|
172
|
+
}
|
173
|
+
};
|
109
174
|
MailCatcher.prototype.haveMessage = function(message) {
|
110
|
-
if (message.id != null)
|
175
|
+
if (message.id != null) {
|
176
|
+
message = message.id;
|
177
|
+
}
|
111
178
|
return $("#messages tbody tr[data-message-id=\"" + message + "\"]").length > 0;
|
112
179
|
};
|
113
|
-
|
114
180
|
MailCatcher.prototype.selectedMessage = function() {
|
115
181
|
return $('#messages tr.selected').data('message-id');
|
116
182
|
};
|
117
|
-
|
118
183
|
MailCatcher.prototype.searchMessages = function(query) {
|
119
184
|
var $rows, selector, token;
|
120
185
|
selector = ((function() {
|
@@ -131,25 +196,23 @@
|
|
131
196
|
$rows.not(selector).hide();
|
132
197
|
return $rows.filter(selector).show();
|
133
198
|
};
|
134
|
-
|
135
199
|
MailCatcher.prototype.clearSearch = function() {
|
136
200
|
return $('#messages tbody tr').show();
|
137
201
|
};
|
138
|
-
|
139
202
|
MailCatcher.prototype.addMessage = function(message) {
|
140
203
|
return $('#messages tbody').append($('<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 receipients").toggleClass("blank", !message.recipients.length)).append($('<td/>').text(message.subject || "No subject").toggleClass("blank", !message.subject)).append($('<td/>').text(this.formatDate(message.created_at))));
|
141
204
|
};
|
142
|
-
|
143
205
|
MailCatcher.prototype.loadMessage = function(id) {
|
144
|
-
|
145
|
-
|
206
|
+
if ((id != null ? id.id : void 0) != null) {
|
207
|
+
id = id.id;
|
208
|
+
}
|
146
209
|
id || (id = $('#messages tr.selected').attr('data-message-id'));
|
147
210
|
if (id != null) {
|
148
211
|
$('#messages tbody tr:not([data-message-id="' + id + '"])').removeClass('selected');
|
149
212
|
$('#messages tbody tr[data-message-id="' + id + '"]').addClass('selected');
|
150
|
-
return $.getJSON('/messages/' + id + '.json', function(message) {
|
213
|
+
return $.getJSON('/messages/' + id + '.json', __bind(function(message) {
|
151
214
|
var $ul;
|
152
|
-
$('#message .metadata dd.created_at').text(
|
215
|
+
$('#message .metadata dd.created_at').text(this.formatDate(message.created_at));
|
153
216
|
$('#message .metadata dd.from').text(message.sender);
|
154
217
|
$('#message .metadata dd.to').text((message.recipients || []).join(', '));
|
155
218
|
$('#message .metadata dd.subject').text(message.subject);
|
@@ -179,14 +242,13 @@
|
|
179
242
|
}
|
180
243
|
$('#message .views .download a').attr('href', "/messages/" + id + ".eml");
|
181
244
|
if ($('#message .views .tab.analysis.selected').length) {
|
182
|
-
return
|
245
|
+
return this.loadMessageAnalysis();
|
183
246
|
} else {
|
184
|
-
return
|
247
|
+
return this.loadMessageBody();
|
185
248
|
}
|
186
|
-
});
|
249
|
+
}, this));
|
187
250
|
}
|
188
251
|
};
|
189
|
-
|
190
252
|
MailCatcher.prototype.loadMessageBody = function(id, format) {
|
191
253
|
id || (id = this.selectedMessage());
|
192
254
|
format || (format = $('#message .views .tab.format.selected').attr('data-message-format'));
|
@@ -197,7 +259,6 @@
|
|
197
259
|
return $('#message iframe').attr("src", "/messages/" + id + "." + format);
|
198
260
|
}
|
199
261
|
};
|
200
|
-
|
201
262
|
MailCatcher.prototype.loadMessageAnalysis = function(id) {
|
202
263
|
var $form, $iframe;
|
203
264
|
id || (id = this.selectedMessage());
|
@@ -212,49 +273,40 @@
|
|
212
273
|
});
|
213
274
|
}
|
214
275
|
};
|
215
|
-
|
216
276
|
MailCatcher.prototype.refresh = function() {
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
277
|
+
return $.getJSON('/messages', __bind(function(messages) {
|
278
|
+
return $.each(messages, __bind(function(i, message) {
|
279
|
+
if (!this.haveMessage(message)) {
|
280
|
+
return this.addMessage(message);
|
281
|
+
}
|
282
|
+
}, this));
|
283
|
+
}, this));
|
223
284
|
};
|
224
|
-
|
225
285
|
MailCatcher.prototype.subscribe = function() {
|
226
|
-
if (typeof WebSocket
|
286
|
+
if (typeof WebSocket != "undefined" && WebSocket !== null) {
|
227
287
|
return this.subscribeWebSocket();
|
228
288
|
} else {
|
229
289
|
return this.subscribePoll();
|
230
290
|
}
|
231
291
|
};
|
232
|
-
|
233
292
|
MailCatcher.prototype.subscribeWebSocket = function() {
|
234
|
-
var secure
|
235
|
-
_this = this;
|
293
|
+
var secure;
|
236
294
|
secure = window.location.scheme === 'https';
|
237
295
|
this.websocket = new WebSocket("" + (secure ? 'wss' : 'ws') + "://" + window.location.host + "/messages");
|
238
|
-
return this.websocket.onmessage = function(event) {
|
239
|
-
return
|
240
|
-
};
|
296
|
+
return this.websocket.onmessage = __bind(function(event) {
|
297
|
+
return this.addMessage($.parseJSON(event.data));
|
298
|
+
}, this);
|
241
299
|
};
|
242
|
-
|
243
300
|
MailCatcher.prototype.subscribePoll = function() {
|
244
|
-
var _this = this;
|
245
301
|
if (this.refreshInterval == null) {
|
246
|
-
return this.refreshInterval = setInterval((function() {
|
247
|
-
return
|
248
|
-
}), 1000);
|
302
|
+
return this.refreshInterval = setInterval((__bind(function() {
|
303
|
+
return this.refresh();
|
304
|
+
}, this)), 1000);
|
249
305
|
}
|
250
306
|
};
|
251
|
-
|
252
307
|
return MailCatcher;
|
253
|
-
|
254
308
|
})();
|
255
|
-
|
256
309
|
$(function() {
|
257
310
|
return window.MailCatcher = new MailCatcher;
|
258
311
|
});
|
259
|
-
|
260
312
|
}).call(this);
|
@@ -0,0 +1,4 @@
|
|
1
|
+
// keymaster.js
|
2
|
+
// (c) 2011 Thomas Fuchs
|
3
|
+
// keymaster.js may be freely distributed under the MIT license.
|
4
|
+
(function(a){function h(a,b){var c=a.length;while(c--)if(a[c]===b)return c;return-1}function i(a){var b,g,i,j,k;b=a.keyCode;if(b==93||b==224)b=91;if(b in d){d[b]=!0;for(i in f)f[i]==b&&(l[i]=!0);return}if(!l.filter.call(this,a))return;if(!(b in c))return;for(j=0;j<c[b].length;j++){g=c[b][j];if(g.scope==e||g.scope=="all"){k=g.mods.length>0;for(i in d)if(!d[i]&&h(g.mods,+i)>-1||d[i]&&h(g.mods,+i)==-1)k=!1;(g.mods.length==0&&!d[16]&&!d[18]&&!d[17]&&!d[91]||k)&&g.method(a,g)===!1&&(a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation&&a.stopPropagation(),a.cancelBubble&&(a.cancelBubble=!0))}}}function j(a){var b=a.keyCode,c;if(b==93||b==224)b=91;if(b in d){d[b]=!1;for(c in f)f[c]==b&&(l[c]=!1)}}function k(){for(b in d)d[b]=!1;for(b in f)l[b]=!1}function l(a,b,d){var e,h,i,j;d===undefined&&(d=b,b="all"),a=a.replace(/\s/g,""),e=a.split(","),e[e.length-1]==""&&(e[e.length-2]+=",");for(i=0;i<e.length;i++){h=[],a=e[i].split("+");if(a.length>1){h=a.slice(0,a.length-1);for(j=0;j<h.length;j++)h[j]=f[h[j]];a=[a[a.length-1]]}a=a[0],a=g[a]||a.toUpperCase().charCodeAt(0),a in c||(c[a]=[]),c[a].push({shortcut:e[i],scope:b,method:d,key:e[i],mods:h})}}function m(a){var b=(a.target||a.srcElement).tagName;return b!="INPUT"&&b!="SELECT"&&b!="TEXTAREA"}function n(a){e=a||"all"}function o(){return e||"all"}function p(a){var b,d,e;for(b in c){d=c[b];for(e=0;e<d.length;)d[e].scope===a?d.splice(e,1):e++}}function q(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,function(){c(window.event)})}var b,c={},d={16:!1,18:!1,17:!1,91:!1},e="all",f={"⇧":16,shift:16,"⌥":18,alt:18,option:18,"⌃":17,ctrl:17,control:17,"⌘":91,command:91},g={backspace:8,tab:9,clear:12,enter:13,"return":13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,"delete":46,home:36,end:35,pageup:33,pagedown:34,",":188,".":190,"/":191,"`":192,"-":189,"=":187,";":186,"'":222,"[":219,"]":221,"\\":220};for(b=1;b<20;b++)f["f"+b]=111+b;for(b in f)l[b]=!1;q(document,"keydown",i),q(document,"keyup",j),q(window,"focus",k),a.key=l,a.key.setScope=n,a.key.getScope=o,a.key.deleteScope=p,a.key.filter=m,typeof module!="undefined"&&(module.exports=key)})(this);
|
data/views/index.haml
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mailcatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: eventmachine
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0.12'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.12'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: haml
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '3.1'
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: mail
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: '2.3'
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.3'
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: sinatra
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ~>
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '1.2'
|
66
86
|
type: :runtime
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.2'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: skinny
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ~>
|
@@ -76,10 +101,15 @@ dependencies:
|
|
76
101
|
version: '0.2'
|
77
102
|
type: :runtime
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.2'
|
80
110
|
- !ruby/object:Gem::Dependency
|
81
111
|
name: sqlite3
|
82
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
83
113
|
none: false
|
84
114
|
requirements:
|
85
115
|
- - ~>
|
@@ -87,10 +117,15 @@ dependencies:
|
|
87
117
|
version: '1.3'
|
88
118
|
type: :runtime
|
89
119
|
prerelease: false
|
90
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.3'
|
91
126
|
- !ruby/object:Gem::Dependency
|
92
127
|
name: thin
|
93
|
-
requirement:
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
94
129
|
none: false
|
95
130
|
requirements:
|
96
131
|
- - ~>
|
@@ -98,10 +133,15 @@ dependencies:
|
|
98
133
|
version: '1.2'
|
99
134
|
type: :runtime
|
100
135
|
prerelease: false
|
101
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '1.2'
|
102
142
|
- !ruby/object:Gem::Dependency
|
103
143
|
name: coffee-script
|
104
|
-
requirement:
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
105
145
|
none: false
|
106
146
|
requirements:
|
107
147
|
- - ~>
|
@@ -109,10 +149,15 @@ dependencies:
|
|
109
149
|
version: '2.2'
|
110
150
|
type: :development
|
111
151
|
prerelease: false
|
112
|
-
version_requirements:
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '2.2'
|
113
158
|
- !ruby/object:Gem::Dependency
|
114
159
|
name: compass
|
115
|
-
requirement:
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
116
161
|
none: false
|
117
162
|
requirements:
|
118
163
|
- - ~>
|
@@ -120,10 +165,15 @@ dependencies:
|
|
120
165
|
version: 0.11.1
|
121
166
|
type: :development
|
122
167
|
prerelease: false
|
123
|
-
version_requirements:
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.11.1
|
124
174
|
- !ruby/object:Gem::Dependency
|
125
175
|
name: rake
|
126
|
-
requirement:
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
127
177
|
none: false
|
128
178
|
requirements:
|
129
179
|
- - ! '>='
|
@@ -131,10 +181,15 @@ dependencies:
|
|
131
181
|
version: '0'
|
132
182
|
type: :development
|
133
183
|
prerelease: false
|
134
|
-
version_requirements:
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
135
190
|
- !ruby/object:Gem::Dependency
|
136
191
|
name: rdoc
|
137
|
-
requirement:
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
138
193
|
none: false
|
139
194
|
requirements:
|
140
195
|
- - ! '>='
|
@@ -142,10 +197,15 @@ dependencies:
|
|
142
197
|
version: '0'
|
143
198
|
type: :development
|
144
199
|
prerelease: false
|
145
|
-
version_requirements:
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
146
206
|
- !ruby/object:Gem::Dependency
|
147
207
|
name: sass
|
148
|
-
requirement:
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
149
209
|
none: false
|
150
210
|
requirements:
|
151
211
|
- - ~>
|
@@ -153,7 +213,12 @@ dependencies:
|
|
153
213
|
version: '3.1'
|
154
214
|
type: :development
|
155
215
|
prerelease: false
|
156
|
-
version_requirements:
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ~>
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '3.1'
|
157
222
|
description: ! " MailCatcher runs a super simple SMTP server which catches any\n
|
158
223
|
\ message sent to it to display in a web interface. Run\n mailcatcher, set
|
159
224
|
your favourite app to deliver to\n smtp://127.0.0.1:1025 instead of your default
|
@@ -184,6 +249,7 @@ files:
|
|
184
249
|
- public/javascripts/date.js
|
185
250
|
- public/javascripts/flexie.min.js
|
186
251
|
- public/javascripts/jquery.js
|
252
|
+
- public/javascripts/keymaster.min.js
|
187
253
|
- public/javascripts/modernizr.js
|
188
254
|
- public/javascripts/xslt-3.2.js
|
189
255
|
- public/stylesheets/application.css
|
@@ -209,9 +275,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
275
|
version: '0'
|
210
276
|
requirements: []
|
211
277
|
rubyforge_project:
|
212
|
-
rubygems_version: 1.8.
|
278
|
+
rubygems_version: 1.8.23
|
213
279
|
signing_key:
|
214
280
|
specification_version: 3
|
215
281
|
summary: Runs an SMTP server, catches and displays email in a web interface.
|
216
282
|
test_files: []
|
217
|
-
has_rdoc:
|