dmarcurator 0.1.1
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 +7 -0
- data/.gitignore +4 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +21 -0
- data/Rakefile +1 -0
- data/bin/dmarcurator +4 -0
- data/dmarcurator.gemspec +22 -0
- data/lib/dmarcurator/cli/app.rb +65 -0
- data/lib/dmarcurator/import_reports.rb +25 -0
- data/lib/dmarcurator/parser/base.rb +23 -0
- data/lib/dmarcurator/parser/record.rb +55 -0
- data/lib/dmarcurator/parser/report.rb +65 -0
- data/lib/dmarcurator/parser.rb +7 -0
- data/lib/dmarcurator/store/record.rb +42 -0
- data/lib/dmarcurator/store/report.rb +52 -0
- data/lib/dmarcurator/store.rb +7 -0
- data/lib/dmarcurator/version.rb +5 -0
- data/lib/dmarcurator.rb +14 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4db33b8efc1496dabb33d6612b082a56c47a1b28
|
4
|
+
data.tar.gz: 0a60be2fbc7fcc09ae27c6d4fcee25cbd1eb0fd9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 25fd8f9c7898fc133c58b27645921e01ab085a8a86dc319618ddd110cee1f555ceee3067b01fd5c9436c4d53fae0d726a07acabd1e6d44c06519be99848cae2e
|
7
|
+
data.tar.gz: 908dc64c6d499f5e37e5068c1cc5270154ea7114e83b1ca2c10d226809232cfe3ca4cabfa21bce1590c56731af7411bf7548751b78489352d056643c9333f395
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Ayumi Yu
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
## dmarcurator
|
2
|
+
|
3
|
+
Imports DMARC report XML into SQLite DB.
|
4
|
+
|
5
|
+
- [More info on email authentication](https://jl.ly/Email/authcheat.html)
|
6
|
+
|
7
|
+
## install
|
8
|
+
|
9
|
+
Install sqlite3 bc it's cool and you need it
|
10
|
+
`brew install sqlite3`
|
11
|
+
|
12
|
+
`gem install dmarcurator`
|
13
|
+
|
14
|
+
## usage
|
15
|
+
|
16
|
+
- Get some DMARC reports in XML and put them in a directory.
|
17
|
+
- `dmarcurator --db=./dmarc/reports.sqlite --reports-path=./dmarc/reports`
|
18
|
+
|
19
|
+
## how to browse db
|
20
|
+
|
21
|
+
[SQLite-web](https://github.com/coleifer/sqlite-web) is a deec interface.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/dmarcurator
ADDED
data/dmarcurator.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require File.expand_path("../lib/dmarcurator/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.add_dependency "ox", "~> 2.4"
|
6
|
+
s.add_dependency "sequel", "~> 4.38"
|
7
|
+
s.add_dependency "sqlite3", "~> 1.3"
|
8
|
+
s.add_development_dependency "bundler", "~> 1.13"
|
9
|
+
s.add_development_dependency "pry", "~> 0"
|
10
|
+
s.add_development_dependency "rake", "~> 0"
|
11
|
+
s.authors = ["Ayumi Yu"]
|
12
|
+
s.description = "Simple tool for viewing DMARC reports"
|
13
|
+
s.email = ["ayumi@ayumiyu.com"]
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
s.homepage = "https://github.com/ayumi/dmarcurator"
|
17
|
+
s.license = "MIT"
|
18
|
+
s.name = "dmarcurator"
|
19
|
+
s.summary = "Tool for viewing DMARC reports"
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.version = Dmarcurator::VERSION
|
22
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Dmarcurator
|
3
|
+
module Cli
|
4
|
+
class App
|
5
|
+
require "pry"
|
6
|
+
|
7
|
+
attr_reader :db_uri, :reports_path
|
8
|
+
|
9
|
+
def self.main
|
10
|
+
params = parse_options(ARGV)
|
11
|
+
new(params).run
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse_options(options)
|
15
|
+
params = {}
|
16
|
+
|
17
|
+
opt_parser = OptionParser.new do |parser|
|
18
|
+
parser.banner = "dmarcurator parses DMARC reports and stores them into an SQLite3 DB.\nIt can also serve a basic web UI for viewing reports (-ui=true).\nUsage: dmarcurator [options]"
|
19
|
+
|
20
|
+
parser.on("-db", "--db-sqlite=SQLITE_DB", "[Required] Path to sqlite3 DB. (e.g. ./tmp/reports.sqlite)") do |value|
|
21
|
+
params[:db_path] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.on("-rp", "--reports-path=REPORTS_PATH", "Path to directory containing DMARC reports. (e.g. ./tmp/reports/)") do |value|
|
25
|
+
params[:reports_path] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
parser.on("-h", "--help", "Halp pls") do
|
29
|
+
puts parser
|
30
|
+
exit 0
|
31
|
+
end
|
32
|
+
|
33
|
+
parser.on("-v", "--version", "Print version") do
|
34
|
+
puts ::Dmarcurator::VERSION
|
35
|
+
exit 0
|
36
|
+
end
|
37
|
+
|
38
|
+
if options.empty?
|
39
|
+
puts parser
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
opt_parser.parse!(options)
|
45
|
+
if !params[:reports_path]
|
46
|
+
puts "Dmarcurator can import DMARC reports into an sqlite3 database -> Set --db and --reports-path)"
|
47
|
+
exit 0
|
48
|
+
end
|
49
|
+
|
50
|
+
params
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(db_path:, reports_path: nil)
|
54
|
+
@db_uri = "sqlite://#{File.expand_path(db_path)}"
|
55
|
+
@reports_path = reports_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
if reports_path
|
60
|
+
::Dmarcurator::ImportReports.new(db_uri: db_uri, reports_path: reports_path).run
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "sequel"
|
3
|
+
|
4
|
+
module Dmarcurator
|
5
|
+
# Import DMARC XML reports into DB
|
6
|
+
class ImportReports
|
7
|
+
attr_reader :db, :reports_path
|
8
|
+
|
9
|
+
def initialize(db_uri:, reports_path:)
|
10
|
+
@db = Sequel.connect(db_uri)
|
11
|
+
@reports_path = reports_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
puts "Importing #{reports_path}"
|
16
|
+
Dir.foreach(reports_path) do |path|
|
17
|
+
next if path == '.' || path == '..' || File.extname(path) != ".xml"
|
18
|
+
puts " #{path}"
|
19
|
+
parsed_report = ::Dmarcurator::Parser::Report.new(xml: "#{reports_path}/#{path}")
|
20
|
+
::Dmarcurator::Store::Report.import_parsed(db: db, parsed: parsed_report)
|
21
|
+
end
|
22
|
+
puts "Done importing :)"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "open3"
|
3
|
+
require "ox"
|
4
|
+
|
5
|
+
module Dmarcurator
|
6
|
+
module Parser
|
7
|
+
# Base XML parser
|
8
|
+
class Base
|
9
|
+
attr_reader :doc
|
10
|
+
|
11
|
+
def initialize(xml: nil, parsed_xml: nil)
|
12
|
+
if xml
|
13
|
+
content = File.read(xml)
|
14
|
+
@doc = Ox.parse(content)
|
15
|
+
elsif parsed_xml
|
16
|
+
@doc = parsed_xml
|
17
|
+
else
|
18
|
+
raise "Either :xml or :parsed_xml are required"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Dmarcurator
|
3
|
+
module Parser
|
4
|
+
# Parsed XML of a record
|
5
|
+
class Record < Base
|
6
|
+
def source_ip
|
7
|
+
doc.locate("row/source_ip")[0].text
|
8
|
+
end
|
9
|
+
|
10
|
+
def count
|
11
|
+
doc.locate("row/count")[0].text.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def disposition
|
15
|
+
doc.locate("row/policy_evaluated/disposition")[0].text
|
16
|
+
end
|
17
|
+
|
18
|
+
def policy_result_dkim
|
19
|
+
doc.locate("row/policy_evaluated/dkim")[0].text
|
20
|
+
end
|
21
|
+
|
22
|
+
def policy_result_spf
|
23
|
+
doc.locate("row/policy_evaluated/spf")[0].text
|
24
|
+
end
|
25
|
+
|
26
|
+
def envelope_to
|
27
|
+
doc.locate("identifiers/envelope_to")[0]&.text
|
28
|
+
end
|
29
|
+
|
30
|
+
def header_from
|
31
|
+
doc.locate("identifiers/header_from")[0].text
|
32
|
+
end
|
33
|
+
|
34
|
+
def auth_dkim_domain
|
35
|
+
doc.locate("auth_results/dkim/domain")[0]&.text
|
36
|
+
end
|
37
|
+
|
38
|
+
def auth_dkim_result
|
39
|
+
doc.locate("auth_results/dkim/result")[0]&.text
|
40
|
+
end
|
41
|
+
|
42
|
+
def auth_dkim_selector
|
43
|
+
doc.locate("auth_results/dkim/selector")[0]&.text
|
44
|
+
end
|
45
|
+
|
46
|
+
def auth_spf_domain
|
47
|
+
doc.locate("auth_results/spf/domain")[0].text
|
48
|
+
end
|
49
|
+
|
50
|
+
def auth_spf_result
|
51
|
+
doc.locate("auth_results/spf/result")[0].text
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Dmarcurator
|
3
|
+
module Parser
|
4
|
+
# Parsed XML of a report
|
5
|
+
class Report < Base
|
6
|
+
def org_name
|
7
|
+
doc.locate("feedback/report_metadata/org_name")[0].text
|
8
|
+
end
|
9
|
+
|
10
|
+
def email
|
11
|
+
doc.locate("feedback/report_metadata/email")[0].text
|
12
|
+
end
|
13
|
+
|
14
|
+
def extra_contact_info
|
15
|
+
doc.locate("feedback/report_metadata/extra_contact_info")[0]&.text
|
16
|
+
end
|
17
|
+
|
18
|
+
def dmarc_report_id
|
19
|
+
doc.locate("feedback/report_metadata/report_id")[0].text
|
20
|
+
end
|
21
|
+
|
22
|
+
def error
|
23
|
+
doc.locate("feedback/report_metadata/error")[0]&.text
|
24
|
+
end
|
25
|
+
|
26
|
+
def begin_at
|
27
|
+
Time.at(doc.locate("feedback/report_metadata/date_range/begin")[0].text.to_i)
|
28
|
+
end
|
29
|
+
|
30
|
+
def end_at
|
31
|
+
Time.at(doc.locate("feedback/report_metadata/date_range/end")[0].text.to_i)
|
32
|
+
end
|
33
|
+
|
34
|
+
def policy_domain
|
35
|
+
doc.locate("feedback/policy_published/domain")[0].text
|
36
|
+
end
|
37
|
+
|
38
|
+
def policy_adkim
|
39
|
+
doc.locate("feedback/policy_published/adkim")[0]&.text
|
40
|
+
end
|
41
|
+
|
42
|
+
def policy_aspf
|
43
|
+
doc.locate("feedback/policy_published/aspf")[0]&.text
|
44
|
+
end
|
45
|
+
|
46
|
+
def policy_p
|
47
|
+
doc.locate("feedback/policy_published/p")[0].text
|
48
|
+
end
|
49
|
+
|
50
|
+
def policy_sp
|
51
|
+
doc.locate("feedback/policy_published/sp")[0]&.text
|
52
|
+
end
|
53
|
+
|
54
|
+
def policy_pct
|
55
|
+
doc.locate("feedback/policy_published/pct")[0].text.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
def records
|
59
|
+
doc.locate("feedback/record").map do |record|
|
60
|
+
Record.new(parsed_xml: record)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "sequel"
|
3
|
+
|
4
|
+
module Dmarcurator
|
5
|
+
class Store
|
6
|
+
# DMARC report. Contains many records.
|
7
|
+
class Record
|
8
|
+
attr_reader :db
|
9
|
+
|
10
|
+
def self.create_table(db:)
|
11
|
+
db.create_table :records do
|
12
|
+
primary_key :id
|
13
|
+
foreign_key(:report_id, :reports, key: :id)
|
14
|
+
String :source_ip
|
15
|
+
Integer :count
|
16
|
+
String :disposition
|
17
|
+
String :policy_result_dkim
|
18
|
+
String :policy_result_spf
|
19
|
+
String :envelope_to
|
20
|
+
String :header_from
|
21
|
+
String :auth_dkim_domain
|
22
|
+
String :auth_dkim_result
|
23
|
+
String :auth_dkim_selector
|
24
|
+
String :auth_spf_domain
|
25
|
+
String :auth_spf_result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.import_parsed(db:, parsed:, report_id:)
|
30
|
+
create_table(db: db) if !db.table_exists?(:records)
|
31
|
+
|
32
|
+
attributes = { report_id: report_id }
|
33
|
+
db[:records].columns.each do |attribute|
|
34
|
+
next if !parsed.respond_to?(attribute)
|
35
|
+
attributes[attribute] = parsed.public_send(attribute)
|
36
|
+
end
|
37
|
+
result = db[:records].insert(attributes)
|
38
|
+
STDOUT << "."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# DMARC report. Contains many records.
|
3
|
+
module Dmarcurator
|
4
|
+
class Store
|
5
|
+
class Report
|
6
|
+
attr_reader :db
|
7
|
+
|
8
|
+
def self.create_table(db:)
|
9
|
+
puts "Creating table: reports"
|
10
|
+
db.create_table :reports do
|
11
|
+
primary_key :id
|
12
|
+
String :org_name
|
13
|
+
String :email
|
14
|
+
String :extra_contact_info
|
15
|
+
String :dmarc_report_id
|
16
|
+
String :error
|
17
|
+
DateTime :begin_at
|
18
|
+
DateTime :end_at
|
19
|
+
String :policy_domain
|
20
|
+
String :policy_adkim
|
21
|
+
String :policy_aspf
|
22
|
+
String :policy_p
|
23
|
+
String :policy_sp
|
24
|
+
Integer :policy_pct
|
25
|
+
|
26
|
+
index :dmarc_report_id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.import_parsed(db:, parsed:)
|
31
|
+
create_table(db: db) if !db.table_exists?(:reports)
|
32
|
+
if db[:reports].where(dmarc_report_id: parsed.dmarc_report_id).count > 0
|
33
|
+
puts "Report exists; skipping"
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
attributes = {}
|
38
|
+
db[:reports].columns.each do |attribute|
|
39
|
+
next if !parsed.respond_to?(attribute)
|
40
|
+
attributes[attribute] = parsed.public_send(attribute)
|
41
|
+
end
|
42
|
+
result = db[:reports].insert(attributes)
|
43
|
+
imported_report_id = db[:reports].select(:id).order('id ASC').limit(1).first[:id]
|
44
|
+
|
45
|
+
parsed.records.each do |parsed_record|
|
46
|
+
Record.import_parsed(db: db, parsed: parsed_record, report_id: imported_report_id)
|
47
|
+
end
|
48
|
+
puts "Report++"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/dmarcurator.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "dmarcurator/version"
|
3
|
+
|
4
|
+
module Dmarcurator
|
5
|
+
require "dmarcurator/cli/app"
|
6
|
+
require "dmarcurator/import_reports"
|
7
|
+
require "dmarcurator/parser"
|
8
|
+
require "dmarcurator/parser/base"
|
9
|
+
require "dmarcurator/parser/record"
|
10
|
+
require "dmarcurator/parser/report"
|
11
|
+
require "dmarcurator/store"
|
12
|
+
require "dmarcurator/store/record"
|
13
|
+
require "dmarcurator/store/report"
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dmarcurator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ayumi Yu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ox
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sequel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.38'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.38'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.13'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.13'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Simple tool for viewing DMARC reports
|
98
|
+
email:
|
99
|
+
- ayumi@ayumiyu.com
|
100
|
+
executables:
|
101
|
+
- dmarcurator
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".ruby-version"
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- bin/dmarcurator
|
112
|
+
- dmarcurator.gemspec
|
113
|
+
- lib/dmarcurator.rb
|
114
|
+
- lib/dmarcurator/cli/app.rb
|
115
|
+
- lib/dmarcurator/import_reports.rb
|
116
|
+
- lib/dmarcurator/parser.rb
|
117
|
+
- lib/dmarcurator/parser/base.rb
|
118
|
+
- lib/dmarcurator/parser/record.rb
|
119
|
+
- lib/dmarcurator/parser/report.rb
|
120
|
+
- lib/dmarcurator/store.rb
|
121
|
+
- lib/dmarcurator/store/record.rb
|
122
|
+
- lib/dmarcurator/store/report.rb
|
123
|
+
- lib/dmarcurator/version.rb
|
124
|
+
homepage: https://github.com/ayumi/dmarcurator
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.5.1
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Tool for viewing DMARC reports
|
148
|
+
test_files: []
|