phisher_phinder 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|