postmortem 0.2.1 → 0.2.3
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/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
|