postmortem 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/layout/default.html.erb +2 -1
- data/layout/layout.css +1 -1
- data/layout/layout.js +33 -13
- data/layout/postmortem_identity.html.erb +20 -0
- data/layout/{index.html.erb → postmortem_index.html.erb} +3 -6
- data/lib/postmortem.rb +2 -0
- data/lib/postmortem/adapters/mail.rb +1 -1
- data/lib/postmortem/delivery.rb +7 -9
- data/lib/postmortem/identity.rb +20 -0
- data/lib/postmortem/index.rb +12 -5
- data/lib/postmortem/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0231d0fd15050a1535451df10e0a700f2218345be118d911c495285c35548c3
|
4
|
+
data.tar.gz: 5427f04480ae4b3d59fc169949429ab17e8451cff4a7b008b84c5457766fde6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7568bba76a5439455684d7691216eb01e3e18165693ef649d85e981ed4cb88ab9fcfbb34abcc0d801e2080dcbd6ec4b6e10534221998c227a821e01c33d0593
|
7
|
+
data.tar.gz: 7f7467751d3d4975d908e322f58c2cf1c0948c213ef6a01e28c5071db52f682fcec41c515fe21067cae95cd4d4924e1dac5682e069a5d4f734d0abb9db0707d9
|
data/README.md
CHANGED
data/layout/default.html.erb
CHANGED
@@ -62,7 +62,8 @@
|
|
62
62
|
</div>
|
63
63
|
</div>
|
64
64
|
</div>
|
65
|
-
<iframe id="index-iframe" src="
|
65
|
+
<iframe id="index-iframe" src="postmortem_index.html"></iframe>
|
66
|
+
<iframe id="identity-iframe" src="postmortem_identity.html"></iframe>
|
66
67
|
<script type="text/javascript">
|
67
68
|
<%= javascript_dependencies %>
|
68
69
|
</script>
|
data/layout/layout.css
CHANGED
data/layout/layout.js
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
(function () {
|
2
2
|
let previousInbox;
|
3
3
|
let currentView;
|
4
|
+
let reloadIdentityIframeTimeout;
|
5
|
+
let identityUuid;
|
4
6
|
let indexUuid;
|
5
7
|
let inboxInitialized = false;
|
6
8
|
|
7
9
|
var htmlIframeDocument = document.querySelector("#html-iframe").contentDocument;
|
8
10
|
var indexIframe = document.querySelector("#index-iframe");
|
11
|
+
var identityIframe = document.querySelector("#identity-iframe");
|
9
12
|
var textIframeDocument = document.querySelector("#text-iframe").contentDocument;
|
10
13
|
var sourceIframeDocument = document.querySelector("#source-iframe").contentDocument;
|
11
14
|
var sourceHighlightBundle = [
|
@@ -22,16 +25,21 @@
|
|
22
25
|
const initialize = () => {
|
23
26
|
loadMail(initialData);
|
24
27
|
|
25
|
-
|
28
|
+
reloadIdentityIframeTimeout = setTimeout(() => identityIframe.src += '', 3000);
|
26
29
|
|
27
30
|
window.addEventListener('message', function (ev) {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
switch (ev.data.type) {
|
32
|
+
case 'index':
|
33
|
+
renderInbox(ev.data.uuid, ev.data.mails);
|
34
|
+
break;
|
35
|
+
case 'identity':
|
36
|
+
compareIdentity(ev.data.uuid);
|
37
|
+
break;
|
38
|
+
};
|
32
39
|
});
|
33
40
|
|
34
41
|
setInterval(function () { indexIframe.contentWindow.postMessage('HELO', '*'); }, 1000);
|
42
|
+
setInterval(function () { identityIframe.contentWindow.postMessage('HELO', '*'); }, 1000);
|
35
43
|
|
36
44
|
toolbar.html.onclick = function (ev) { setView('html', ev); };
|
37
45
|
toolbar.text.onclick = function (ev) { setView('text', ev); };
|
@@ -215,25 +223,36 @@
|
|
215
223
|
$("#download-link").attr('href', uri);
|
216
224
|
};
|
217
225
|
|
218
|
-
const
|
219
|
-
|
220
|
-
|
226
|
+
const compareIdentity = (uuid) => {
|
227
|
+
clearTimeout(reloadIdentityIframeTimeout);
|
228
|
+
reloadIdentityIframeTimeout = setTimeout(() => identityIframe.src += '', 3000);
|
229
|
+
if (identityUuid !== uuid) indexIframe.src += '';
|
230
|
+
identityUuid = uuid;
|
231
|
+
};
|
232
|
+
|
233
|
+
const renderInbox = (uuid, mails) => {
|
234
|
+
if (uuid === indexUuid) {
|
235
|
+
return;
|
236
|
+
}
|
237
|
+
const mailsById = {};
|
238
|
+
const html = mails.map((mail, index) => {
|
221
239
|
const parsedTimestamp = new Date(mail.timestamp);
|
222
240
|
const timestampSpan = `<span class="timestamp">${parsedTimestamp.toLocaleString()}</span>`;
|
223
241
|
const classes = ['list-group-item', 'inbox-item'];
|
224
|
-
if (window.location.hash === '#' +
|
225
|
-
|
242
|
+
if (window.location.hash === '#' + mail.id) classes.push('active');
|
243
|
+
mailsById[mail.id] = mail;
|
244
|
+
return `<li data-email-id="${mail.id}" class="${classes.join(' ')}"><a title="${mail.subject}" href="javascript:void(0)">${mail.subject}</a>${timestampSpan}</li>`
|
226
245
|
});
|
227
246
|
if (arrayIdentical(html, previousInbox)) return;
|
228
247
|
previousInbox = html;
|
229
248
|
$('#inbox').html('<ul class="list-group">' + html.join('\n') + '</ul>');
|
230
249
|
$('.inbox-item').click((ev) => {
|
231
250
|
const $target = $(ev.currentTarget);
|
232
|
-
const
|
251
|
+
const id = $target.data('email-id');
|
233
252
|
$('.inbox-item').removeClass('active');
|
234
253
|
$target.addClass('active');
|
235
|
-
window.location.hash =
|
236
|
-
setTimeout(() => loadMail(
|
254
|
+
window.location.hash = id;
|
255
|
+
setTimeout(() => loadMail(mailsById[id].content), 0);
|
237
256
|
});
|
238
257
|
|
239
258
|
if (!inboxInitialized) {
|
@@ -242,6 +261,7 @@
|
|
242
261
|
setVisible(inbox, true);
|
243
262
|
}
|
244
263
|
inboxInitialized = true;
|
264
|
+
indexUuid = uuid;
|
245
265
|
};
|
246
266
|
|
247
267
|
initialize();
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<body>
|
4
|
+
<div data-uuid="<%= uuid %>" id="identity">
|
5
|
+
</div>
|
6
|
+
<script>
|
7
|
+
window.addEventListener('message', function (ev) {
|
8
|
+
const identity = document.querySelector('#identity');
|
9
|
+
const uuid = identity.dataset.uuid;
|
10
|
+
const type = 'identity';
|
11
|
+
ev.source.postMessage({ uuid, type }, '*');
|
12
|
+
});
|
13
|
+
|
14
|
+
setInterval(function () {
|
15
|
+
window.location.reload();
|
16
|
+
}, 3000);
|
17
|
+
|
18
|
+
</script>
|
19
|
+
</body>
|
20
|
+
</html>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<body>
|
4
|
-
<div data-uuid="<%=
|
4
|
+
<div data-uuid="<%= uuid %>" id="index">
|
5
5
|
### INDEX START
|
6
6
|
<% encoded_index.each do |encoded| -%>
|
7
7
|
<%= encoded %>
|
@@ -13,16 +13,13 @@
|
|
13
13
|
const filter = (line) => line !== '' && !line.startsWith('### INDEX');
|
14
14
|
const index = document.querySelector('#index');
|
15
15
|
const uuid = index.dataset.uuid;
|
16
|
+
const type = 'index';
|
16
17
|
const mails = index.innerText
|
17
18
|
.split('\n')
|
18
19
|
.filter(filter)
|
19
20
|
.map(line => JSON.parse(atob(line)));
|
20
|
-
ev.source.postMessage({ uuid, mails }, '*');
|
21
|
+
ev.source.postMessage({ uuid, type, mails }, '*');
|
21
22
|
});
|
22
|
-
|
23
|
-
setInterval(function () {
|
24
|
-
window.location.reload();
|
25
|
-
}, 3000);
|
26
23
|
</script>
|
27
24
|
</body>
|
28
25
|
</html>
|
data/lib/postmortem.rb
CHANGED
@@ -8,12 +8,14 @@ require 'mail'
|
|
8
8
|
require 'erb'
|
9
9
|
require 'json'
|
10
10
|
require 'cgi'
|
11
|
+
require 'digest'
|
11
12
|
|
12
13
|
require 'postmortem/version'
|
13
14
|
require 'postmortem/adapters'
|
14
15
|
require 'postmortem/delivery'
|
15
16
|
require 'postmortem/layout'
|
16
17
|
require 'postmortem/configuration'
|
18
|
+
require 'postmortem/identity'
|
17
19
|
require 'postmortem/index'
|
18
20
|
|
19
21
|
# HTML email inspection tool.
|
@@ -10,7 +10,7 @@ module Postmortem
|
|
10
10
|
%i[from reply_to to cc bcc subject]
|
11
11
|
.map { |field| [field, @data.public_send(field)] }
|
12
12
|
.to_h
|
13
|
-
.merge({ text_body: @data.text_part, html_body: @data.html_part })
|
13
|
+
.merge({ text_body: @data.text_part&.decoded, html_body: @data.html_part&.decoded })
|
14
14
|
end
|
15
15
|
|
16
16
|
def mail
|
data/lib/postmortem/delivery.rb
CHANGED
@@ -7,8 +7,9 @@ module Postmortem
|
|
7
7
|
|
8
8
|
def initialize(mail)
|
9
9
|
@mail = mail
|
10
|
-
@path = Postmortem.config.preview_directory.join('
|
11
|
-
@index_path = Postmortem.config.preview_directory.join('
|
10
|
+
@path = Postmortem.config.preview_directory.join('index.html')
|
11
|
+
@index_path = Postmortem.config.preview_directory.join('postmortem_index.html')
|
12
|
+
@identity_path = Postmortem.config.preview_directory.join('postmortem_identity.html')
|
12
13
|
end
|
13
14
|
|
14
15
|
def record
|
@@ -16,20 +17,17 @@ module Postmortem
|
|
16
17
|
content = Layout.new(@mail).content
|
17
18
|
path.write(content)
|
18
19
|
index_path.write(index.content)
|
20
|
+
@identity_path.write(identity.content)
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
22
24
|
|
23
25
|
def index
|
24
|
-
@index ||= Index.new(index_path, path,
|
26
|
+
@index ||= Index.new(index_path, path, @mail)
|
25
27
|
end
|
26
28
|
|
27
|
-
def
|
28
|
-
@
|
29
|
-
end
|
30
|
-
|
31
|
-
def token
|
32
|
-
SecureRandom.hex(4)
|
29
|
+
def identity
|
30
|
+
@identity ||= Identity.new
|
33
31
|
end
|
34
32
|
|
35
33
|
def subject
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Postmortem
|
4
|
+
# Provides an HTML document that announces a unique ID to a parent page via JS message events.
|
5
|
+
class Identity
|
6
|
+
def content
|
7
|
+
ERB.new(File.read(path), nil, '-').result(binding)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def uuid
|
13
|
+
@uuid ||= SecureRandom.uuid
|
14
|
+
end
|
15
|
+
|
16
|
+
def path
|
17
|
+
File.expand_path(File.join(__dir__, '..', '..', 'layout', 'postmortem_identity.html.erb'))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/postmortem/index.rb
CHANGED
@@ -3,10 +3,9 @@
|
|
3
3
|
module Postmortem
|
4
4
|
# Generates and parses an index of previously-sent emails.
|
5
5
|
class Index
|
6
|
-
def initialize(index_path, mail_path,
|
6
|
+
def initialize(index_path, mail_path, mail)
|
7
7
|
@index_path = index_path
|
8
8
|
@mail_path = mail_path
|
9
|
-
@timestamp = timestamp.iso8601
|
10
9
|
@mail = mail
|
11
10
|
end
|
12
11
|
|
@@ -21,6 +20,14 @@ module Postmortem
|
|
21
20
|
|
22
21
|
private
|
23
22
|
|
23
|
+
def uuid
|
24
|
+
@uuid ||= SecureRandom.uuid
|
25
|
+
end
|
26
|
+
|
27
|
+
def timestamp
|
28
|
+
Time.now.iso8601
|
29
|
+
end
|
30
|
+
|
24
31
|
def encoded_index
|
25
32
|
return [encoded_mail] unless @index_path.file?
|
26
33
|
|
@@ -28,13 +35,13 @@ module Postmortem
|
|
28
35
|
end
|
29
36
|
|
30
37
|
def encoded_mail
|
31
|
-
Base64.encode64(mail_data.to_json).split("\n").join
|
38
|
+
Base64.encode64(mail_data.merge(id: Digest::MD5.hexdigest(mail_data.to_json)).to_json).split("\n").join
|
32
39
|
end
|
33
40
|
|
34
41
|
def mail_data
|
35
42
|
{
|
36
43
|
subject: @mail.subject || '(no subject)',
|
37
|
-
timestamp:
|
44
|
+
timestamp: timestamp,
|
38
45
|
path: @mail_path,
|
39
46
|
content: @mail.serializable
|
40
47
|
}
|
@@ -54,7 +61,7 @@ module Postmortem
|
|
54
61
|
end
|
55
62
|
|
56
63
|
def template_path
|
57
|
-
File.expand_path(File.join(__dir__, '..', '..', 'layout', '
|
64
|
+
File.expand_path(File.join(__dir__, '..', '..', 'layout', 'postmortem_index.html.erb'))
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
data/lib/postmortem/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postmortem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mail
|
@@ -145,9 +145,10 @@ files:
|
|
145
145
|
- layout/dependencies.css
|
146
146
|
- layout/dependencies.js
|
147
147
|
- layout/headers_template.html
|
148
|
-
- layout/index.html.erb
|
149
148
|
- layout/layout.css
|
150
149
|
- layout/layout.js
|
150
|
+
- layout/postmortem_identity.html.erb
|
151
|
+
- layout/postmortem_index.html.erb
|
151
152
|
- lib/postmortem.rb
|
152
153
|
- lib/postmortem/adapters.rb
|
153
154
|
- lib/postmortem/adapters/action_mailer.rb
|
@@ -156,6 +157,7 @@ files:
|
|
156
157
|
- lib/postmortem/adapters/pony.rb
|
157
158
|
- lib/postmortem/configuration.rb
|
158
159
|
- lib/postmortem/delivery.rb
|
160
|
+
- lib/postmortem/identity.rb
|
159
161
|
- lib/postmortem/index.rb
|
160
162
|
- lib/postmortem/layout.rb
|
161
163
|
- lib/postmortem/plugins/action_mailer.rb
|