mail_grabber 1.0.0.rc1 → 1.2.0

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.
@@ -0,0 +1,86 @@
1
+ var MailGrabberDOM = {
2
+ /**
3
+ * Change which content (message part) should show. When the page is loading,
4
+ * the HTML content will be active and the others will be hidden. When we
5
+ * click on tab e.g. Plain Text then this content will be active and other
6
+ * hidden.
7
+ *
8
+ * @param {Object} event - which part we clicked
9
+ */
10
+ changeMessageContent: function(event) {
11
+ var messageTabs =
12
+ document
13
+ .querySelectorAll('[data-message-tab]');
14
+
15
+ var messageContents =
16
+ document
17
+ .querySelectorAll('[data-message-content]');
18
+
19
+ var clickedTabType = event.target.dataset.messageTab;
20
+
21
+ messageTabs.forEach(function(messageTab, index) {
22
+ messageTab.classList.remove('active');
23
+ messageContents[index].classList.remove('hide');
24
+
25
+ if(messageTab.dataset.messageTab === clickedTabType) {
26
+ messageTab.classList.add('active');
27
+ }
28
+
29
+ if(messageContents[index].dataset.messageContent !== clickedTabType) {
30
+ messageContents[index].classList.add('hide');
31
+ }
32
+ });
33
+ },
34
+
35
+ /**
36
+ * Create a clone from an element, e.g. template tag.
37
+ *
38
+ * @param {String} selector - which describe how to find the element
39
+ *
40
+ * @return {Object} the clone of the found element
41
+ */
42
+ cloneContent: function(selector) {
43
+ return document.querySelector(selector).content.cloneNode(true);
44
+ },
45
+
46
+ /**
47
+ * Show default background image instead of any content.
48
+ */
49
+ defaultBackground: function() {
50
+ var messageContent =
51
+ document
52
+ .querySelector('div[data-content-type=message-content]');
53
+
54
+ messageContent.innerHTML = '';
55
+
56
+ messageContent.style.background =
57
+ "url('" + messageContent.dataset.backgroundImage +
58
+ "') center center no-repeat";
59
+ messageContent.style.backgroundSize = '50%';
60
+ messageContent.style.opacity = '10%';
61
+ },
62
+
63
+ /**
64
+ * Delete all content (message list and message content as well),
65
+ * set default background and the infinite scroll params when we click on
66
+ * the Reload or Delete tabs.
67
+ */
68
+ deleteContent: function() {
69
+ MailGrabberVariables.lastMessageId = -1;
70
+ MailGrabberVariables.page = 1;
71
+ MailGrabberDOM.defaultBackground();
72
+
73
+ document
74
+ .querySelector('ul[data-content-type=message-list]')
75
+ .innerHTML = '';
76
+ },
77
+
78
+ /**
79
+ * Root path, which returns with the server's root path. It can be an empty
80
+ * string or a string. It depends on how the server is running (standalone
81
+ * or in Ruby on Rails).
82
+ */
83
+ rootPath: function() {
84
+ return document.querySelector('body').dataset.rootPath;
85
+ }
86
+ };
@@ -0,0 +1,36 @@
1
+ var MailGrabberMessageAttachment = {
2
+ /**
3
+ * Render message attachment. Show the list of attachments at the top of the
4
+ * message content.
5
+ *
6
+ * @param {Object} messageAttachments - the message attachments container
7
+ * @param {Object} messagePart - a message part which we loaded
8
+ */
9
+ render: function(messageAttachments, messagePart) {
10
+ var messageAttachment = document.createElement('a');
11
+ var fileSize = document.createElement('span');
12
+ var messageAttachmentTemplate =
13
+ MailGrabberDOM
14
+ .cloneContent(
15
+ 'template[data-content-type=message-attachment-template]'
16
+ );
17
+
18
+ messageAttachment.href =
19
+ 'data:' + messagePart.mime_type + ';base64,' + messagePart.body;
20
+ messageAttachment.download = messagePart.filename;
21
+ messageAttachment.innerHTML = messagePart.filename;
22
+ messageAttachment.classList.add('color-black', 'no-text-decoration');
23
+
24
+ fileSize.innerHTML = MailGrabberUtilities.formatSize(messagePart.size);
25
+ fileSize.classList.add('color-gray', 'font-size-0_9', 'padding-left-10');
26
+
27
+ [messageAttachment, fileSize].forEach(function(node) {
28
+ messageAttachmentTemplate
29
+ .querySelector('li[data-content-type=message-attachment]')
30
+ .appendChild(node);
31
+ });
32
+
33
+ messageAttachments.classList.remove('hide');
34
+ messageAttachments.appendChild(messageAttachmentTemplate);
35
+ }
36
+ };
@@ -0,0 +1,114 @@
1
+ var MailGrabberMessageContent = {
2
+ /**
3
+ * Fill up the message content template with content.
4
+ *
5
+ * @param {Object} response - from the server with data
6
+ *
7
+ * @return {Object} the filled up template
8
+ */
9
+ fillUpTemplateWith: function(response) {
10
+ var message = response.message;
11
+ var messageParts = response.message_parts;
12
+ var messageContentTemplate =
13
+ MailGrabberDOM
14
+ .cloneContent('template[data-content-type=message-content-template]');
15
+
16
+ messageContentTemplate
17
+ .querySelector('div[data-content-type=message-subject]')
18
+ .innerHTML = message.subject;
19
+
20
+ MailGrabberMessageMetadata.render(
21
+ messageContentTemplate
22
+ .querySelector('dl[data-content-type=metadata]'),
23
+ message
24
+ );
25
+
26
+ messageContentTemplate
27
+ .querySelector('time[data-content-type=message-sent-at]')
28
+ .innerHTML = MailGrabberUtilities.formatDateTime(message.created_at);
29
+
30
+ messageContentTemplate
31
+ .querySelectorAll('[data-message-tab]')
32
+ .forEach(function(tab) {
33
+ tab.addEventListener('click', MailGrabberDOM.changeMessageContent);
34
+ });
35
+
36
+ messageContentTemplate
37
+ .querySelector('li[data-content-type=message-delete-tab]')
38
+ .addEventListener('click', function() {
39
+ MailGrabberApplication.deleteMessage(message.id);
40
+ });
41
+
42
+ messageContentTemplate
43
+ .querySelector('li[data-content-type=message-close-tab]')
44
+ .addEventListener('click', MailGrabberDOM.defaultBackground);
45
+
46
+ messageParts.forEach(function(messagePart) {
47
+ if(messagePart.is_attachment === 0 && messagePart.is_inline === 0) {
48
+ switch(messagePart.mime_type) {
49
+ case 'text/html':
50
+ MailGrabberVariables.messageHasHtmlPart = true;
51
+ MailGrabberMessageHtmlPart.render(
52
+ messageContentTemplate
53
+ .querySelector('iframe[data-content-type=message-html-body]'),
54
+ messageParts,
55
+ messagePart.body
56
+ );
57
+
58
+ break;
59
+ case 'text/plain':
60
+ messageContentTemplate
61
+ .querySelector('pre[data-content-type=message-text-body]')
62
+ .innerText = messagePart.body;
63
+
64
+ break;
65
+ }
66
+ } else if(messagePart.is_attachment === 1 &&
67
+ messagePart.is_inline === 0) {
68
+ MailGrabberMessageAttachment.render(
69
+ messageContentTemplate
70
+ .querySelector('ul[data-content-type=message-attachments]'),
71
+ messagePart
72
+ );
73
+ }
74
+ });
75
+
76
+ messageContentTemplate
77
+ .querySelector('pre[data-content-type=message-raw-body]')
78
+ .innerText = message.raw;
79
+
80
+ return messageContentTemplate;
81
+ },
82
+
83
+ /**
84
+ * Render the content of the message (all parts, inline attachments and
85
+ * attachments). Also, it sets up event listeners of the HTML, PlainText,
86
+ * Raw, Delete and Close tabs.
87
+ *
88
+ * @param {Object} response - the response of the get message request
89
+ */
90
+ render: function(response) {
91
+ var messageContent =
92
+ document
93
+ .querySelector('div[data-content-type=message-content]');
94
+
95
+ messageContent.removeAttribute('style');
96
+ messageContent.innerHTML = '';
97
+
98
+ MailGrabberVariables.messageHasHtmlPart = false;
99
+
100
+ messageContent.appendChild(
101
+ MailGrabberMessageContent.fillUpTemplateWith(response)
102
+ );
103
+
104
+ if(!MailGrabberVariables.messageHasHtmlPart) {
105
+ messageContent
106
+ .querySelector('li[data-message-tab=text]')
107
+ .click();
108
+
109
+ messageContent
110
+ .querySelector('li[data-message-tab=html]')
111
+ .classList.add('hide');
112
+ }
113
+ }
114
+ };
@@ -0,0 +1,26 @@
1
+ var MailGrabberMessageHtmlPart = {
2
+ /**
3
+ * Render the HTML part of the message. If the message has inline images,
4
+ * then it will render those images as well. An iframe will contain this
5
+ * content.
6
+ *
7
+ * @param {Object} iFrame - the iframe HTML tag
8
+ * @param {Object} messageParts - the parts of the message
9
+ * @param {Object} messageHtmlPart - the HTML part of the message
10
+ */
11
+ render: function(iFrame, messageParts, messageHtmlPart) {
12
+ var messageInlineAttachmentRegExp = new RegExp('cid:');
13
+
14
+ if(messageInlineAttachmentRegExp.test(messageHtmlPart)) {
15
+ messageHtmlPart =
16
+ MailGrabberMessageInlineAttachments.render(
17
+ messageParts, messageHtmlPart
18
+ );
19
+ }
20
+
21
+ iFrame.srcdoc = messageHtmlPart;
22
+ iFrame.onload = function() {
23
+ iFrame.height = iFrame.contentDocument.body.scrollHeight + 65;
24
+ }
25
+ }
26
+ };
@@ -0,0 +1,21 @@
1
+ var MailGrabberMessageInlineAttachments = {
2
+ /**
3
+ * Render inline images of the message. Change the cid:something12345 with
4
+ * the encoded image content.
5
+ *
6
+ * @param {Object} messageParts - the parts of the message
7
+ * @param {Object} messageHtmlPart - the HTML part of the message
8
+ *
9
+ * @return {Object} messageHtmlPart - the modified HTML part of the message
10
+ */
11
+ render: function(messageParts, messageHtmlPart) {
12
+ messageParts.forEach(function(messagePart) {
13
+ if(messagePart.is_attachment === 1 && messagePart.is_inline === 1) {
14
+ messageHtmlPart = messageHtmlPart.replace('cid:' + messagePart.cid,
15
+ 'data:' + messagePart.mime_type + ';base64,' + messagePart.body);
16
+ }
17
+ });
18
+
19
+ return messageHtmlPart;
20
+ }
21
+ };
@@ -0,0 +1,54 @@
1
+ var MailGrabberMessageList = {
2
+ /**
3
+ * Fill up the message list template with content.
4
+ *
5
+ * @param {Object} message
6
+ *
7
+ * @return {Object} the filled up template
8
+ */
9
+ fillUpTemplateWith: function(message) {
10
+ var messageListTemplate =
11
+ MailGrabberDOM
12
+ .cloneContent('template[data-content-type=message-list-template]');
13
+
14
+ messageListTemplate
15
+ .querySelector('li')
16
+ .addEventListener('click', function() {
17
+ MailGrabberApplication.getMessage(message.id);
18
+ });
19
+
20
+ messageListTemplate
21
+ .querySelector('div[data-content-type=message-senders]')
22
+ .innerHTML = message.senders;
23
+
24
+ messageListTemplate
25
+ .querySelector('time[data-content-type=message-sent-at]')
26
+ .innerHTML =
27
+ MailGrabberUtilities
28
+ .formatDateTime(message.created_at, 'messageListDateOrTime');
29
+
30
+ messageListTemplate
31
+ .querySelector('div[data-content-type=message-subject]')
32
+ .innerHTML = message.subject;
33
+
34
+ return messageListTemplate;
35
+ },
36
+
37
+ /**
38
+ * Render the list of the messages. Also add event listener when click on a
39
+ * message then it will load that content.
40
+ *
41
+ * @param {Object} messages - the list of the given message.
42
+ */
43
+ render: function(messages) {
44
+ var messageList =
45
+ document
46
+ .querySelector('ul[data-content-type=message-list]');
47
+
48
+ messages.forEach(function(message) {
49
+ messageList.appendChild(
50
+ MailGrabberMessageList.fillUpTemplateWith(message)
51
+ );
52
+ });
53
+ }
54
+ };
@@ -0,0 +1,23 @@
1
+ var MailGrabberMessageMetadata = {
2
+ /**
3
+ * Render senders and recipients data of the message.
4
+ *
5
+ * @param {Object} messageMetadata - the metadata container
6
+ * @param {Object} message - the requested message
7
+ */
8
+ render: function(messageMetadata, message) {
9
+ var metadata =
10
+ '<dt>From:</dt><dd>' + message.senders + '</dd>' +
11
+ '<dt>To:</dt><dd>' + message.recipients + '</dd>';
12
+
13
+ if(message.carbon_copy) {
14
+ metadata += '<dt>Cc:</dt><dd>' + message.carbon_copy + '</dd>';
15
+ }
16
+
17
+ if(message.blind_carbon_copy) {
18
+ metadata += '<dt>Bcc:</dt><dd>' + message.blind_carbon_copy + '</dd>';
19
+ }
20
+
21
+ messageMetadata.innerHTML = metadata;
22
+ }
23
+ };
@@ -0,0 +1,65 @@
1
+ var MailGrabberUtilities = {
2
+ /**
3
+ * Format the given date or time.
4
+ *
5
+ * @param {DateTime} dateTime - the message created at attribute
6
+ * @param {String} ouputType - what type we would like to see
7
+ *
8
+ * @return {String} the new format of the date or time
9
+ */
10
+ formatDateTime: function(dateTime, outputType) {
11
+ dateTime = new Date(dateTime);
12
+ var dateTimeNow = new Date();
13
+ // Sun Feb 21 2021 21:00:00 GMT+0100 (Central European Standard Time)
14
+ // 0 1 2 3 4 5 6 7 8 9
15
+ var dateTimeComponents = dateTime.toString().split(' ');
16
+ var output;
17
+
18
+ switch(outputType) {
19
+ case 'messageListDateOrTime':
20
+ if(dateTime.getDate() === dateTimeNow.getDate()) {
21
+ output = MailGrabberUtilities.formatTime(dateTimeComponents[4]);
22
+ } else if(dateTime.getFullYear() === dateTimeNow.getFullYear()) {
23
+ output = dateTimeComponents[1] + ' ' + dateTimeComponents[2];
24
+ } else {
25
+ output = dateTimeComponents[3] + ' ' + dateTimeComponents[1] + ' ' +
26
+ dateTimeComponents[2];
27
+ }
28
+
29
+ break;
30
+ default:
31
+ output = dateTimeComponents[3] + ' ' + dateTimeComponents[1] + ' ' +
32
+ dateTimeComponents[2] + ' - ' +
33
+ MailGrabberUtilities.formatTime(dateTimeComponents[4]);
34
+ }
35
+
36
+ return output;
37
+ },
38
+
39
+ /**
40
+ * Format the given number (attachment size).
41
+ *
42
+ * @param {Number} size - the size of the attachment in bytes
43
+ *
44
+ * @return {String} the formatted number with unit
45
+ */
46
+ formatSize: function(size) {
47
+ var exponent = (Math.log(size) / Math.log(1024)) | 0;
48
+ var number = +(size / Math.pow(1024, exponent)).toFixed(1);
49
+
50
+ return number + ' ' + ('KMGTPEZY'[exponent - 1] || '') + 'B';
51
+ },
52
+
53
+ /**
54
+ * Format the given time.
55
+ *
56
+ * @param {String} time
57
+ *
58
+ * @return {String} the new format of the time
59
+ */
60
+ formatTime: function(time) {
61
+ var timeComponents = time.split(':');
62
+
63
+ return timeComponents[0] + ':' + timeComponents[1];
64
+ }
65
+ };
@@ -0,0 +1,24 @@
1
+ var MailGrabberVariables = {
2
+ /**
3
+ * The last message id what loaded. If it is -1 then we have no any
4
+ * messages.
5
+ */
6
+ lastMessageId: -1,
7
+
8
+ /**
9
+ * The message has HTML part or not.
10
+ */
11
+ messageHasHtmlPart: false,
12
+
13
+ /**
14
+ * The message is list reloading or not (click on the Reload tab).
15
+ */
16
+ messageListReloading: false,
17
+
18
+ /**
19
+ * Params that we can follow how many messages we have on the list. We are
20
+ * loading 15 messages in every request.
21
+ */
22
+ page: 1,
23
+ perPage: 15
24
+ };
@@ -0,0 +1,6 @@
1
+ (function() {
2
+ /**
3
+ * When DOM loaded, then call MailGrabber's init function.
4
+ */
5
+ document.addEventListener('DOMContentLoaded', MailGrabberApplication.init);
6
+ })();
@@ -11,6 +11,16 @@
11
11
  <link rel="stylesheet" href="<%= root_path %>/stylesheets/application.css" type="text/css" charset="utf-8">
12
12
 
13
13
  <script src="<%= root_path %>/javascripts/application.js"></script>
14
+ <script src="<%= root_path %>/javascripts/dom.js"></script>
15
+ <script src="<%= root_path %>/javascripts/message_attachment.js"></script>
16
+ <script src="<%= root_path %>/javascripts/message_content.js"></script>
17
+ <script src="<%= root_path %>/javascripts/message_html_part.js"></script>
18
+ <script src="<%= root_path %>/javascripts/message_inline_attachments.js"></script>
19
+ <script src="<%= root_path %>/javascripts/message_list.js"></script>
20
+ <script src="<%= root_path %>/javascripts/message_metadata.js"></script>
21
+ <script src="<%= root_path %>/javascripts/utilities.js"></script>
22
+ <script src="<%= root_path %>/javascripts/variables.js"></script>
23
+ <script src="<%= root_path %>/javascripts/web.js"></script>
14
24
  </head>
15
25
 
16
26
  <body data-root-path="<%= root_path %>">
@@ -14,7 +14,8 @@ module MailGrabber
14
14
  module Web
15
15
  module_function
16
16
 
17
- # Method which build a Rack application and run the Web::Application
17
+ # Method which build a Rack application and run the
18
+ # MailGrabber::Web::Application.
18
19
  def app
19
20
  @app ||= Rack::Builder.new do
20
21
  use Rack::Static,
data/lib/mail_grabber.rb CHANGED
@@ -3,6 +3,6 @@
3
3
  require 'mail_grabber/error'
4
4
  require 'mail_grabber/database_helper'
5
5
  require 'mail_grabber/delivery_method'
6
- # If we are using this gem outside of Rails then do not load this code.
6
+ # If we are using this gem outside of Rails, then do not load this code.
7
7
  require 'mail_grabber/railtie' if defined?(Rails)
8
8
  require 'mail_grabber/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail_grabber
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Norbert Szivós
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-20 00:00:00.000000000 Z
11
+ date: 2022-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mail
@@ -78,6 +78,16 @@ files:
78
78
  - lib/mail_grabber/web/application_router.rb
79
79
  - lib/mail_grabber/web/assets/images/mail_grabber515x500.png
80
80
  - lib/mail_grabber/web/assets/javascripts/application.js
81
+ - lib/mail_grabber/web/assets/javascripts/dom.js
82
+ - lib/mail_grabber/web/assets/javascripts/message_attachment.js
83
+ - lib/mail_grabber/web/assets/javascripts/message_content.js
84
+ - lib/mail_grabber/web/assets/javascripts/message_html_part.js
85
+ - lib/mail_grabber/web/assets/javascripts/message_inline_attachments.js
86
+ - lib/mail_grabber/web/assets/javascripts/message_list.js
87
+ - lib/mail_grabber/web/assets/javascripts/message_metadata.js
88
+ - lib/mail_grabber/web/assets/javascripts/utilities.js
89
+ - lib/mail_grabber/web/assets/javascripts/variables.js
90
+ - lib/mail_grabber/web/assets/javascripts/web.js
81
91
  - lib/mail_grabber/web/assets/stylesheets/application.css
82
92
  - lib/mail_grabber/web/views/_message_attachment_template.html.erb
83
93
  - lib/mail_grabber/web/views/_message_content_template.html.erb
@@ -91,7 +101,8 @@ metadata:
91
101
  source_code_uri: https://github.com/MailToolbox/mail_grabber
92
102
  changelog_uri: https://github.com/MailToolbox/mail_grabber/blob/main/CHANGELOG.md
93
103
  bug_tracker_uri: https://github.com/MailToolbox/mail_grabber/issues
94
- documentation_uri: https://rubydoc.info/gems/mail_grabber
104
+ documentation_uri: https://rubydoc.info/github/MailToolbox/mail_grabber/main
105
+ rubygems_mfa_required: 'true'
95
106
  post_install_message:
96
107
  rdoc_options: []
97
108
  require_paths:
@@ -100,14 +111,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
111
  requirements:
101
112
  - - ">="
102
113
  - !ruby/object:Gem::Version
103
- version: 2.5.0
114
+ version: 2.7.0
104
115
  required_rubygems_version: !ruby/object:Gem::Requirement
105
116
  requirements:
106
- - - ">"
117
+ - - ">="
107
118
  - !ruby/object:Gem::Version
108
- version: 1.3.1
119
+ version: '0'
109
120
  requirements: []
110
- rubygems_version: 3.1.4
121
+ rubygems_version: 3.3.3
111
122
  signing_key:
112
123
  specification_version: 4
113
124
  summary: Grab mails to inspect with MailGrabber.