osa 0.2.1 → 0.2.2

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
  SHA256:
3
- metadata.gz: 1008becc098b639309f218c9f763e57d4d01f201b28fd105c478cd46534de913
4
- data.tar.gz: 2c285065f454aeaa7fcc1f9dd6f72e92d3423dbe292d06ef36afba6a8db6f9eb
3
+ metadata.gz: b3bc9c2b204260bd0cecd1650fdbfca0676c53e6e44c59aef8926caf9a5f0246
4
+ data.tar.gz: f32d6566bc6195847fc12fe680f8c22e6cbfe91f587bc7a35937efb1582eaccc
5
5
  SHA512:
6
- metadata.gz: 4b53ba423fc0b0da3bc8f49188d34370cf49d12e968a13a436ffaa6c849dceddedcf10c7e2b833d7316dbc0045fe487c44891b6eb50b98fb63477f63b8542a0e
7
- data.tar.gz: ba063539fe384116422310df5a0d3a14c324a0560674932dd39998951d433236fb929a86aae981895adff04a29d71d0780c8fc4a2a9d11fa817359ad56c10ff0
6
+ metadata.gz: 76462c72b811ecb6b2224725ec954aa3ff3c6d2fc99a4cc91ae66698d72de709c740683ce6c4690095853199c7ef67c836ddc0bf6c0d3c4eb33751ee0fec3058
7
+ data.tar.gz: f4e79f61caa68f2c1ecd646ffa3d127070addf334f827bb33066bfdefc1e44f8b2986b6983c120c94867fa907e65184fd679ef73ad0eaa6b1b34f49956d5393d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osa (0.2.1)
4
+ osa (0.2.2)
5
5
  activerecord (~> 6.0)
6
6
  faraday (~> 1.1)
7
7
  mail (~> 2.7.1)
@@ -37,7 +37,7 @@ GEM
37
37
  mail (2.7.1)
38
38
  mini_mime (>= 0.1.1)
39
39
  mini_mime (1.0.2)
40
- minitest (5.14.3)
40
+ minitest (5.14.4)
41
41
  multi_json (1.15.0)
42
42
  multipart-post (2.1.1)
43
43
  mustermann (1.1.1)
@@ -6,6 +6,7 @@ require 'osa/util/db'
6
6
  class DashboardServer < Sinatra::Base
7
7
  set :views, File.absolute_path(File.dirname(__FILE__) + '/../views')
8
8
  set :port, ENV['SERVER_PORT'] || 8080
9
+ after { ActiveRecord::Base.connection.close }
9
10
 
10
11
  get '/' do
11
12
  erb :index
@@ -54,7 +55,11 @@ class DashboardServer < Sinatra::Base
54
55
  end
55
56
 
56
57
  get '/api/stats/spammers' do
57
- spammers = OSA::Report.select('sender_domain as domain', 'COUNT(*) as count').limit(50).order(count: :desc).group(:sender_domain)
58
+ spammers = OSA::Report.select('sender_domain as domain', 'COUNT(*) as count')
59
+ unless params[:interval].blank?
60
+ spammers = spammers.where('received_at > ?', Time.now - params[:interval].to_i.days)
61
+ end
62
+ spammers = spammers.limit(50).order(count: :desc).group(:sender_domain)
58
63
  json spammers
59
64
  end
60
65
 
@@ -63,6 +68,9 @@ class DashboardServer < Sinatra::Base
63
68
  unless params[:spammer].blank?
64
69
  historical_data = historical_data.where(sender: params[:spammer]).or(OSA::Report.where(sender_domain: params[:spammer]))
65
70
  end
71
+ unless params[:interval].blank?
72
+ historical_data = historical_data.where('received_at > ?', Time.now - params[:interval].to_i.days)
73
+ end
66
74
  json historical_data.group(:date)
67
75
  end
68
76
  end
@@ -21,13 +21,26 @@ def resolve_blacklist(mail_id, email_address, domain, context, dns_blacklists)
21
21
  dns_blacklists.find { |bl| bl.blacklisted?(ip) }&.server
22
22
  end
23
23
 
24
+ def extract_email_address(mail)
25
+ email_address = mail['sender']['emailAddress']['address']
26
+ return email_address unless email_address.nil?
27
+
28
+ # Sometimes the SMTP From header is misformatted and the email address is
29
+ # parsed as part of the name by Outlook. Try to extract the email address
30
+ # from the name.
31
+ sender_name = mail['sender']['emailAddress']['name']
32
+ return nil if sender_name.nil?
33
+
34
+ sender_name.scan(/<(.+@.+)>/).first&.first
35
+ end
36
+
24
37
  while continue
25
38
  mails = context.graph_client.mails(context.config.junk_folder_id)
26
39
  continue = false
27
40
  loop do
28
41
  break if mails.nil?
29
42
  mails['value'].each do |mail|
30
- email_address = mail['sender']['emailAddress']['address']
43
+ email_address = extract_email_address(mail)
31
44
  next if email_address.nil?
32
45
  domain = PublicSuffix.domain(email_address.split('@', 2)[1])
33
46
 
data/lib/osa/util/db.rb CHANGED
@@ -25,7 +25,7 @@ module OSA
25
25
 
26
26
  class DnsBlacklist < ActiveRecord::Base
27
27
  def blacklisted?(ip)
28
- ::Resolv.getaddress("#{ip}.#{server}") != "0.0.0.0"
28
+ ::Resolv.getaddress("#{ip}.#{server}") != '0.0.0.0'
29
29
  rescue ::Resolv::ResolvError
30
30
  return false
31
31
  end
data/lib/osa/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module OSA
3
- VERSION = '0.2.1'
3
+ VERSION = '0.2.2'
4
4
  end
@@ -77,6 +77,15 @@
77
77
  <!-- ./col -->
78
78
  </div>
79
79
 
80
+ <div class="row">
81
+ <div id="interval-btn-group" class="btn-group">
82
+ <button onclick="updateInterval(this, '')" type="button" class="btn btn-info active">All time</button>
83
+ <button onclick="updateInterval(this, '1')" type="button" class="btn btn-info">1 day</button>
84
+ <button onclick="updateInterval(this, '7')" type="button" class="btn btn-info">7 days</button>
85
+ <button onclick="updateInterval(this, '30')" type="button" class="btn btn-info">30 days</button>
86
+ </div>
87
+ </div>
88
+
80
89
  <div class="row">
81
90
  <div class="card">
82
91
  <div class="card-header">
@@ -136,6 +145,21 @@
136
145
 
137
146
  <script>
138
147
  let totalReportCount = 0;
148
+ let interval = "";
149
+
150
+ function updateInterval(element, newInterval) {
151
+ interval = newInterval;
152
+ let children = Array.from(document.getElementById("interval-btn-group").children);
153
+ console.log(children);
154
+ children.forEach((child) => {
155
+ if (child === element) {
156
+ child.classList.add("active");
157
+ } else {
158
+ child.classList.remove("active");
159
+ }
160
+ });
161
+ update();
162
+ }
139
163
 
140
164
  function sec2time(timeInSeconds) {
141
165
  const time = parseFloat(timeInSeconds).toFixed(3);
@@ -179,7 +203,7 @@
179
203
  }
180
204
 
181
205
  async function updateSpammers() {
182
- const response = await fetch('/api/stats/spammers');
206
+ const response = await fetch(`/api/stats/spammers?interval=${interval}`);
183
207
  if (response.ok) {
184
208
  const body = await response.json();
185
209
 
@@ -270,7 +294,7 @@
270
294
  const historicalChart = createHistoricalChart();
271
295
 
272
296
  async function updateHistoricalChart() {
273
- const response = await fetch("/api/stats/reports/historical");
297
+ const response = await fetch(`/api/stats/reports/historical?interval=${interval}`);
274
298
  if (response.ok) {
275
299
  const body = await response.json();
276
300
 
@@ -285,11 +309,11 @@
285
309
 
286
310
  function update() {
287
311
  updateStats()
288
- .then(updateSpammers)
289
- .then(updateHistoricalChart)
290
- .then(() => {
291
- setTimeout(update, 10 * 60 * 1000);
292
- })
312
+ .then(updateSpammers)
313
+ .then(updateHistoricalChart)
314
+ .then(() => {
315
+ setTimeout(update, 10 * 60 * 1000);
316
+ })
293
317
  }
294
318
 
295
319
  update();
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moray Baruh
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-20 00:00:00.000000000 Z
11
+ date: 2021-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord