phisher_phinder 0.1.0 → 0.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.
- checksums.yaml +4 -4
- data/.env.example +2 -1
- data/.gitignore +3 -0
- data/Gemfile +0 -11
- data/Gemfile.lock +45 -13
- data/README.md +108 -2
- data/exe/phisher_phinder +61 -0
- data/lib/phisher_phinder.rb +11 -2
- data/lib/phisher_phinder/command.rb +20 -0
- data/lib/phisher_phinder/display.rb +64 -0
- data/lib/phisher_phinder/extended_ip.rb +4 -0
- data/lib/phisher_phinder/extended_ip_factory.rb +4 -2
- data/lib/phisher_phinder/geoip_ip_data.rb +9 -2
- data/lib/phisher_phinder/mail.rb +10 -3
- data/lib/phisher_phinder/mail_parser.rb +43 -30
- data/lib/phisher_phinder/mail_parser/authentication_headers/auth_results_parser.rb +150 -0
- data/lib/phisher_phinder/mail_parser/authentication_headers/parser.rb +25 -0
- data/lib/phisher_phinder/mail_parser/authentication_headers/received_spf_parser.rb +222 -0
- data/lib/phisher_phinder/mail_parser/body/block_classifier.rb +106 -0
- data/lib/phisher_phinder/mail_parser/body/block_parser.rb +37 -0
- data/lib/phisher_phinder/mail_parser/body_parser.rb +26 -31
- data/lib/phisher_phinder/mail_parser/header_value_parser.rb +25 -10
- data/lib/phisher_phinder/mail_parser/received_headers/by_parser.rb +35 -5
- data/lib/phisher_phinder/mail_parser/received_headers/for_parser.rb +25 -5
- data/lib/phisher_phinder/mail_parser/received_headers/from_parser.rb +50 -6
- data/lib/phisher_phinder/mail_parser/received_headers/parser.rb +50 -29
- data/lib/phisher_phinder/mail_parser/received_headers/starttls_parser.rb +8 -1
- data/lib/phisher_phinder/null_lookup_client.rb +9 -0
- data/lib/phisher_phinder/null_response.rb +12 -0
- data/lib/phisher_phinder/sender_extractor.rb +74 -0
- data/lib/phisher_phinder/simple_ip.rb +4 -0
- data/lib/phisher_phinder/tracing_report.rb +47 -0
- data/lib/phisher_phinder/version.rb +1 -1
- data/phisher_phinder.gemspec +15 -1
- metadata +208 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8063750bef71fc06792e7c10440f99e979891612540b06abf4c66f2f368022d
|
4
|
+
data.tar.gz: a94cd0e2438359bc626609216a91633deb589121ac92a2567c2a90625c0e30ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cfc5618456ab2db9304232da36e6a5ae3e989edd1ba0993f5bd1f07feb27cfb4d1921052176630e002aa7847f0faee646f5f6690cdd650c34fd64ed843d0188
|
7
|
+
data.tar.gz: bb5ef0c6f6f601a8c7d42ec2a7a8c8de976ccc9a86e438c56cedf0e4853908edb9efb3dfecfae515d300e0f2671cf321c3eaebe0105dad874a52e9be2fff7050
|
data/.env.example
CHANGED
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,14 +1,3 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
|
-
|
5
|
-
gem 'dotenv', '~> 2.7.5'
|
6
|
-
gem 'maxmind-geoip2', '~> 0.4.0'
|
7
|
-
gem 'nokogiri', '~> 1.10.10'
|
8
|
-
gem 'sequel', '~> 5.33'
|
9
|
-
gem 'sqlite3', '~> 1.4.2'
|
10
|
-
|
11
|
-
gem "rake", "~> 12.0"
|
12
|
-
gem "rspec", "~> 3.0"
|
13
|
-
gem 'database_cleaner-sequel', '1.8.0'
|
14
|
-
gem 'webmock', '~> 3.8.3'
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
phisher_phinder (0.
|
4
|
+
phisher_phinder (0.2.0)
|
5
|
+
dotenv (~> 2.7.5)
|
6
|
+
maxmind-geoip2 (~> 0.4.0)
|
7
|
+
nokogiri (~> 1.11.0)
|
8
|
+
sequel (~> 5.33)
|
9
|
+
sqlite3 (~> 1.4.2)
|
10
|
+
terminal-table (~> 2.0.0)
|
11
|
+
whois (~> 5.0.1)
|
12
|
+
whois-parser (~> 1.2.0)
|
5
13
|
|
6
14
|
GEM
|
7
15
|
remote: https://rubygems.org/
|
8
16
|
specs:
|
17
|
+
activesupport (6.1.0)
|
18
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
|
+
i18n (>= 1.6, < 2)
|
20
|
+
minitest (>= 5.1)
|
21
|
+
tzinfo (~> 2.0)
|
22
|
+
zeitwerk (~> 2.3)
|
9
23
|
addressable (2.7.0)
|
10
24
|
public_suffix (>= 2.0.2, < 5.0)
|
25
|
+
bundler-audit (0.7.0.1)
|
26
|
+
bundler (>= 1.2.0, < 3)
|
27
|
+
thor (>= 0.18, < 2)
|
11
28
|
coderay (1.1.2)
|
29
|
+
concurrent-ruby (1.1.7)
|
12
30
|
connection_pool (2.2.3)
|
13
31
|
crack (0.4.3)
|
14
32
|
safe_yaml (~> 1.0.0)
|
@@ -19,8 +37,8 @@ GEM
|
|
19
37
|
diff-lcs (1.3)
|
20
38
|
domain_name (0.5.20190701)
|
21
39
|
unf (>= 0.0.5, < 1.0.0)
|
22
|
-
dotenv (2.7.
|
23
|
-
ffi (1.
|
40
|
+
dotenv (2.7.6)
|
41
|
+
ffi (1.14.2)
|
24
42
|
ffi-compiler (1.0.1)
|
25
43
|
ffi (>= 1.0.0)
|
26
44
|
rake
|
@@ -33,21 +51,26 @@ GEM
|
|
33
51
|
http-cookie (1.0.3)
|
34
52
|
domain_name (~> 0.5)
|
35
53
|
http-form_data (2.3.0)
|
36
|
-
http-parser (1.2.
|
37
|
-
ffi-compiler
|
54
|
+
http-parser (1.2.2)
|
55
|
+
ffi-compiler
|
56
|
+
i18n (1.8.7)
|
57
|
+
concurrent-ruby (~> 1.0)
|
38
58
|
maxmind-db (1.1.1)
|
39
59
|
maxmind-geoip2 (0.4.0)
|
40
60
|
connection_pool (~> 2.2)
|
41
61
|
http (~> 4.3)
|
42
62
|
maxmind-db (~> 1.1)
|
43
63
|
method_source (1.0.0)
|
44
|
-
mini_portile2 (2.
|
45
|
-
|
46
|
-
|
64
|
+
mini_portile2 (2.5.0)
|
65
|
+
minitest (5.14.2)
|
66
|
+
nokogiri (1.11.0)
|
67
|
+
mini_portile2 (~> 2.5.0)
|
68
|
+
racc (~> 1.4)
|
47
69
|
pry (0.13.1)
|
48
70
|
coderay (~> 1.1)
|
49
71
|
method_source (~> 1.0)
|
50
72
|
public_suffix (4.0.5)
|
73
|
+
racc (1.5.2)
|
51
74
|
rake (12.3.3)
|
52
75
|
rspec (3.9.0)
|
53
76
|
rspec-core (~> 3.9.0)
|
@@ -65,28 +88,37 @@ GEM
|
|
65
88
|
safe_yaml (1.0.5)
|
66
89
|
sequel (5.33.0)
|
67
90
|
sqlite3 (1.4.2)
|
91
|
+
terminal-table (2.0.0)
|
92
|
+
unicode-display_width (~> 1.1, >= 1.1.1)
|
93
|
+
thor (1.0.1)
|
94
|
+
timecop (0.9.2)
|
95
|
+
tzinfo (2.0.4)
|
96
|
+
concurrent-ruby (~> 1.0)
|
68
97
|
unf (0.1.4)
|
69
98
|
unf_ext
|
70
99
|
unf_ext (0.0.7.7)
|
100
|
+
unicode-display_width (1.7.0)
|
71
101
|
webmock (3.8.3)
|
72
102
|
addressable (>= 2.3.6)
|
73
103
|
crack (>= 0.3.2)
|
74
104
|
hashdiff (>= 0.4.0, < 2.0.0)
|
105
|
+
whois (5.0.1)
|
106
|
+
whois-parser (1.2.0)
|
107
|
+
activesupport (>= 4)
|
108
|
+
whois (>= 4.0.7)
|
109
|
+
zeitwerk (2.4.2)
|
75
110
|
|
76
111
|
PLATFORMS
|
77
112
|
ruby
|
78
113
|
|
79
114
|
DEPENDENCIES
|
115
|
+
bundler-audit (~> 0.7.0.1)
|
80
116
|
database_cleaner-sequel (= 1.8.0)
|
81
|
-
dotenv (~> 2.7.5)
|
82
|
-
maxmind-geoip2 (~> 0.4.0)
|
83
|
-
nokogiri (~> 1.10.10)
|
84
117
|
phisher_phinder!
|
85
118
|
pry
|
86
119
|
rake (~> 12.0)
|
87
120
|
rspec (~> 3.0)
|
88
|
-
|
89
|
-
sqlite3 (~> 1.4.2)
|
121
|
+
timecop (~> 0.9.2)
|
90
122
|
webmock (~> 3.8.3)
|
91
123
|
|
92
124
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -1,9 +1,22 @@
|
|
1
1
|
# PhisherPhinder
|
2
2
|
|
3
|
-
|
3
|
+
PhisherPhinder is a small utility that extracts data from an email that can be useful when trying to determine the
|
4
|
+
source of a phishing email.
|
5
|
+
|
6
|
+
As of version 0.2.0 this functionality is very limited. There is a good chance that you will encounter sharp edges - if
|
7
|
+
you do, feel free to file a GH issue and I will try to fix this.
|
8
|
+
|
9
|
+
## Caution
|
10
|
+
|
11
|
+
**When downloading an email for parsing, DO NOT CLICK on any links contained within the email. Rather download the
|
12
|
+
message source as text. As an example, here are the instructions for doing it using
|
13
|
+
[GMail](https://www.lifewire.com/how-to-view-the-source-of-a-message-in-gmail-1172105 'Gmail Download Instructions')**
|
4
14
|
|
5
15
|
## Installation
|
6
16
|
|
17
|
+
Note: Currently, Windows support is not guaranteed. If you would like to test it on Windows and tell me what does not
|
18
|
+
work, I will try my best to address these issues.
|
19
|
+
|
7
20
|
Add this line to your application's Gemfile:
|
8
21
|
|
9
22
|
```ruby
|
@@ -20,9 +33,102 @@ Or install it yourself as:
|
|
20
33
|
|
21
34
|
## Usage
|
22
35
|
|
23
|
-
|
36
|
+
At it's most simple - download the email as text to a location on th emahcine running PhihserPhinder
|
37
|
+
(`/path/to/content.eml`), then:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
phisher_phinder /path/to/content.eml
|
41
|
+
```
|
42
|
+
|
43
|
+
By default, PhisherPhinder will assume that the file uses the dos-style line endings (`\r\n`), but you can specify the
|
44
|
+
line ending type:
|
45
|
+
|
46
|
+
```bash
|
47
|
+
phisher_phinder -l unix /path/to/content.eml # unix line endings \n
|
48
|
+
phisher_phinder -l dos /path/to/content.eml # windows line endings \r\n
|
49
|
+
```
|
50
|
+
|
51
|
+
PhisherPhinder can lookup IPV4 address data from the MaxMind GeoIP service which requires a Maxmind GeoIP account.
|
52
|
+
Lookup results are cached locally in a database (SQLITE will suffice). The URL for the database needs to be provided as
|
53
|
+
an environment variable:
|
54
|
+
|
55
|
+
```bash
|
56
|
+
DATABASE_URL=sqlite://development.sqlite3 phisher_phinder -a foo -k bar -g /path/to/content.eml
|
57
|
+
```
|
58
|
+
|
59
|
+
Note: As of version 0.2.0, the GeoIP data is not used for much and the functionality may be removed in future releases.
|
60
|
+
|
61
|
+
To see help instructions for the CLI usage:
|
62
|
+
|
63
|
+
```bash
|
64
|
+
phisher_phinder -h
|
65
|
+
```
|
66
|
+
|
67
|
+
```
|
68
|
+
Usage: phisher_phinder [options] /path/to/email/contents
|
69
|
+
-a, --account_id ACCOUNT_ID GeoIP account id
|
70
|
+
-k, --license_key LICENSE_KEY GeoIP license key
|
71
|
+
-g, --geoip Enable lookup of GeoIP data for IP addresses (requires `DATABASE_URL` env variable to be defined)
|
72
|
+
-l, --line-ending TYPE Select line ending type for file
|
73
|
+
-h, --help Prints help text
|
74
|
+
|
75
|
+
```
|
76
|
+
|
77
|
+
## Output
|
78
|
+
|
79
|
+
The output of PhisherPhinder will produce something similar to the below:
|
80
|
+
|
81
|
+
```
|
82
|
+
+-------------+---------------------------------------------+
|
83
|
+
| Origin |
|
84
|
+
+-------------+---------------------------------------------+
|
85
|
+
| From | "Email Security Gateway" <test@test.zzz> |
|
86
|
+
| Message ID | <ed1770$bbsq7@test.zzz> |
|
87
|
+
| Return Path | <test@test.zzz> |
|
88
|
+
+-------------+---------------------------------------------+
|
89
|
+
|
90
|
+
|
91
|
+
+-----------+---------------+------------------+
|
92
|
+
| SPF |
|
93
|
+
+-----------+---------------+------------------+
|
94
|
+
| SPF Pass? | Sender Host | From Address |
|
95
|
+
+-----------+---------------+------------------+
|
96
|
+
| Yes | 10.0.0.1 | test@test.zzz |
|
97
|
+
+-----------+---------------+------------------+
|
98
|
+
|
99
|
+
|
100
|
+
+---------------+------------------------------+------------------------------+--------------------------+
|
101
|
+
| Trace |
|
102
|
+
+---------------+------------------------------+------------------------------+--------------------------+
|
103
|
+
| Sender IP | Sender Host | Advertised Sender | Recipient |
|
104
|
+
+---------------+------------------------------+------------------------------+--------------------------+
|
105
|
+
| 10.0.0.1 | host1.test.zzz | dodgyname.test.zzz | mx.google.com |
|
106
|
+
| 10.0.0.2 | | othersdodgyname.text.zzz | host1.test.zzz |
|
107
|
+
+---------------+------------------------------+------------------------------+--------------------------+
|
108
|
+
|
109
|
+
```
|
110
|
+
|
111
|
+
The `Origin` section contains data relating to the email origin.
|
112
|
+
|
113
|
+
With regard to the `SPF` and `Trace` sections, they are based on the assumption that the most recent SPF details
|
114
|
+
provided in the headers can be trusted as they have been provided by the host of the recipient email and can, hopefully,
|
115
|
+
be trusted.
|
116
|
+
|
117
|
+
The `Trace` secion shows a subset of the `Received` headers from the original (advertised, but not necessarily actual)
|
118
|
+
origin (the last entry in the table) to the last external server to process the email before the recipient's mail host
|
119
|
+
received the email.
|
120
|
+
|
121
|
+
## Dependencies
|
122
|
+
1. [Maxmind GeoIP2 User Account](https://dev.maxmind.com/geoip/geoip2/web-services/) - pay as you go
|
123
|
+
2. [Database Cleaner](https://github.com/DatabaseCleaner/database_cleaner#safeguards) - whitelist for database urls
|
24
124
|
|
25
125
|
## Development
|
126
|
+
.env.example contains dependent environment variables for the .env.test file. You will need to change: DATABASE_URL=sqlite://test.sqlite3.
|
127
|
+
Prior to running the specs, run the 0001 migration to create the geo_ip_cache table.
|
128
|
+
|
129
|
+
```
|
130
|
+
# bundle exec rake db:migrate
|
131
|
+
```
|
26
132
|
|
27
133
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
28
134
|
|
data/exe/phisher_phinder
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'phisher_phinder'
|
5
|
+
|
6
|
+
options = {
|
7
|
+
line_ending: "\r\n",
|
8
|
+
geoip_lookup: false,
|
9
|
+
geoip_settings: {
|
10
|
+
account_id: nil,
|
11
|
+
license_key: nil
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = 'Usage: phisher_phinder [options] /path/to/email/contents'
|
17
|
+
line_endings = {
|
18
|
+
'windows' => "\r\n",
|
19
|
+
'dos' => "\r\n",
|
20
|
+
'unix' => "\n",
|
21
|
+
}
|
22
|
+
|
23
|
+
def geoip_credentials?(opts)
|
24
|
+
opts[:geoip_settings][:account_id] && opts[:geoip_settings][:license_key]
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('-a ACCOUNT_ID', '--account_id ACCOUNT_ID', 'GeoIP account id') do |account_id|
|
28
|
+
options[:geoip_settings][:account_id] = account_id
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-k LICENSE_KEY', '--license_key LICENSE_KEY', 'GeoIP license key') do |license_key|
|
32
|
+
options[:geoip_settings][:license_key] = license_key
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on(
|
36
|
+
'-g',
|
37
|
+
'--geoip',
|
38
|
+
'Enable lookup of GeoIP data for IP addresses (requires `DATABASE_URL` env variable to be defined)'
|
39
|
+
) do |geoip|
|
40
|
+
raise 'Please provide the GeoIP account id and license key' unless geoip_credentials?(options)
|
41
|
+
raise 'Please set the DATABASE_URL ENV variable' unless ENV['DATABASE_URL']
|
42
|
+
options[:geoip_lookup] = geoip
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on('-l TYPE', '--line-ending TYPE', line_endings, 'Select line ending type for file') do |ending|
|
46
|
+
options[:line_ending] = ending
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on('-h', '--help', 'Prints help text') do
|
50
|
+
puts opts
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
end.parse!
|
54
|
+
|
55
|
+
file_contents = IO.read(ARGV.last)
|
56
|
+
|
57
|
+
command = PhisherPhinder::Command.new
|
58
|
+
|
59
|
+
PhisherPhinder::Display.new.display_report(
|
60
|
+
command.report(file_contents, **options)
|
61
|
+
)
|
data/lib/phisher_phinder.rb
CHANGED
@@ -2,11 +2,13 @@ require "phisher_phinder/version"
|
|
2
2
|
|
3
3
|
require 'maxmind/geoip2'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
require_relative './phisher_phinder/command'
|
6
|
+
require_relative './phisher_phinder/display'
|
7
7
|
|
8
8
|
require_relative './phisher_phinder/body_hyperlink'
|
9
9
|
require_relative './phisher_phinder/cached_geoip_client'
|
10
|
+
require_relative './phisher_phinder/null_lookup_client'
|
11
|
+
require_relative './phisher_phinder/null_response'
|
10
12
|
require_relative './phisher_phinder/geoip_ip_data'
|
11
13
|
require_relative './phisher_phinder/expanded_data_processor'
|
12
14
|
require_relative './phisher_phinder/extended_ip'
|
@@ -14,6 +16,11 @@ require_relative './phisher_phinder/extended_ip_factory'
|
|
14
16
|
require_relative './phisher_phinder/mail_parser'
|
15
17
|
require_relative './phisher_phinder/mail'
|
16
18
|
require_relative './phisher_phinder/simple_ip'
|
19
|
+
require_relative './phisher_phinder/mail_parser/authentication_headers/parser'
|
20
|
+
require_relative './phisher_phinder/mail_parser/authentication_headers/auth_results_parser'
|
21
|
+
require_relative './phisher_phinder/mail_parser/authentication_headers/received_spf_parser'
|
22
|
+
require_relative './phisher_phinder/mail_parser/body/block_classifier'
|
23
|
+
require_relative './phisher_phinder/mail_parser/body/block_parser'
|
17
24
|
require_relative './phisher_phinder/mail_parser/received_headers/parser'
|
18
25
|
require_relative './phisher_phinder/mail_parser/received_headers/by_parser'
|
19
26
|
require_relative './phisher_phinder/mail_parser/received_headers/classifier'
|
@@ -21,6 +28,8 @@ require_relative './phisher_phinder/mail_parser/received_headers/for_parser'
|
|
21
28
|
require_relative './phisher_phinder/mail_parser/received_headers/from_parser'
|
22
29
|
require_relative './phisher_phinder/mail_parser/received_headers/starttls_parser'
|
23
30
|
require_relative './phisher_phinder/mail_parser/received_headers/timestamp_parser'
|
31
|
+
require_relative './phisher_phinder/sender_extractor'
|
32
|
+
require_relative './phisher_phinder/tracing_report'
|
24
33
|
|
25
34
|
module PhisherPhinder
|
26
35
|
class Error < StandardError; end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhisherPhinder
|
4
|
+
class Command
|
5
|
+
def report(contents, line_ending:, geoip_lookup:, geoip_settings: {})
|
6
|
+
lookup_client = if geoip_lookup
|
7
|
+
PhisherPhinder::CachedGeoipClient.new(
|
8
|
+
MaxMind::GeoIP2::Client.new(**geoip_settings),
|
9
|
+
Time.now - 86400
|
10
|
+
)
|
11
|
+
else
|
12
|
+
PhisherPhinder::NullLookupClient.new
|
13
|
+
end
|
14
|
+
ip_factory = PhisherPhinder::ExtendedIpFactory.new(geoip_client: lookup_client)
|
15
|
+
mail_parser = PhisherPhinder::MailParser::Parser.new(ip_factory, line_ending)
|
16
|
+
tracing_report = PhisherPhinder::TracingReport.new(mail_parser.parse(contents))
|
17
|
+
tracing_report.report
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'terminal-table'
|
3
|
+
|
4
|
+
module PhisherPhinder
|
5
|
+
class Display
|
6
|
+
def display_report(input_data)
|
7
|
+
origin_table = Terminal::Table.new(
|
8
|
+
title: 'Origin',
|
9
|
+
rows: format_origin_data(input_data)
|
10
|
+
)
|
11
|
+
|
12
|
+
puts origin_table
|
13
|
+
|
14
|
+
puts "\n\n"
|
15
|
+
|
16
|
+
spf_table = Terminal::Table.new(
|
17
|
+
headings: ['SPF Pass?', 'Sender Host', 'From Address'],
|
18
|
+
title: 'SPF',
|
19
|
+
rows: [
|
20
|
+
[
|
21
|
+
input_data[:authentication][:spf][:success] ? 'Yes' : 'No',
|
22
|
+
input_data[:authentication][:spf][:ip],
|
23
|
+
input_data[:authentication][:spf][:from_address]
|
24
|
+
]
|
25
|
+
]
|
26
|
+
)
|
27
|
+
|
28
|
+
puts spf_table
|
29
|
+
|
30
|
+
puts "\n\n"
|
31
|
+
|
32
|
+
data = input_data[:tracing].map do |entry|
|
33
|
+
[
|
34
|
+
entry[:sender][:ip],
|
35
|
+
entry[:sender][:host],
|
36
|
+
entry[:advertised_sender] || entry[:helo],
|
37
|
+
entry[:recipient]
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
trace_table = Terminal::Table.new(
|
42
|
+
headings: ['Sender IP', 'Sender Host', 'Advertised Sender', 'Recipient'],
|
43
|
+
title: 'Trace',
|
44
|
+
rows: data
|
45
|
+
)
|
46
|
+
|
47
|
+
puts trace_table
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def format_origin_data(input_data)
|
53
|
+
types = [
|
54
|
+
['From', :from],
|
55
|
+
['Message ID', :message_id],
|
56
|
+
['Return Path', :return_path],
|
57
|
+
]
|
58
|
+
|
59
|
+
types.inject([]) do |output, (description, type)|
|
60
|
+
output << [description, input_data[:origin][type].join(', ')]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|