class PhisherPhinder::MailParser::Parser

Public Class Methods

new(enriched_ip_factory, line_ending) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 8
def initialize(enriched_ip_factory, line_ending)
  @line_ending = line_ending
  @enriched_ip_factory = enriched_ip_factory
end

Public Instance Methods

parse(contents) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 13
def parse(contents)
  original_headers, original_body = separate(contents)
  headers = extract_headers(original_headers)
  PhisherPhinder::Mail.new(
    original_email: contents,
    original_headers: original_headers,
    original_body: original_body,
    headers: headers,
    tracing_headers: generate_tracing_headers(headers),
    body: MailParser::BodyParser.new.parse(contents),
    authentication_headers: generate_authentication_headers(headers)
  )
end

Private Instance Methods

content_transfer_encoding_data(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 99
def content_transfer_encoding_data(headers)
  (headers[:content_transfer_encoding] && headers[:content_transfer_encoding].first[:data]) || nil
end
content_type_data(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 95
def content_type_data(headers)
  (headers[:content_type] && headers[:content_type].first[:data]) || nil
end
convert_header_name(header) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 51
def convert_header_name(header)
  header.gsub(/-/, '_').downcase.to_sym
end
enrich_header_value(value, sequence) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 55
def enrich_header_value(value, sequence)
  {data: HeaderValueParser.new.parse(value), sequence: sequence}
end
extract_headers(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 33
def extract_headers(headers)
  parse_headers(unfold_headers(headers).split(@line_ending))
end
generate_authentication_headers(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 103
def generate_authentication_headers(headers)
  auth_parser = MailParser::AuthenticationHeaders::Parser.new(
    authentication_results_parser: MailParser::AuthenticationHeaders::AuthResultsParser.new(
      ip_factory: @enriched_ip_factory
    ),
    received_spf_parser: MailParser::AuthenticationHeaders::ReceivedSpfParser.new(
      ip_factory: @enriched_ip_factory
    ),
  )
  auth_parser.parse(headers)
end
generate_tracing_headers(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 59
def generate_tracing_headers(headers)
  received_header_values = headers.inject([]) do |memo, (header_name, header_value)|
    [:received, :x_received].include?(header_name) ? memo + header_value : memo
  end

  {
    received: restore_sequence(received_header_values).map { |v| parse_received_header(v[:data]) }
  }
end
parse_headers(headers_array) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 41
def parse_headers(headers_array)
  headers_array.each_with_index.inject({}) do |memo, (header_string, index)|
    header, value = header_string.split(":", 2)
    sequence = headers_array.length - index - 1
    memo.merge(convert_header_name(header) => [enrich_header_value(value, sequence)]) do |_, existing, new|
      existing + new
    end
  end
end
parse_received_header(value) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 69
def parse_received_header(value)
  starttls_parser = MailParser::ReceivedHeaders::StarttlsParser.new
  parser = MailParser::ReceivedHeaders::Parser.new(
    by_parser: MailParser::ReceivedHeaders::ByParser.new(
      ip_factory: @enriched_ip_factory, starttls_parser: starttls_parser
    ),
    for_parser: MailParser::ReceivedHeaders::ForParser.new(starttls_parser: starttls_parser),
    from_parser: MailParser::ReceivedHeaders::FromParser.new(
      ip_factory: @enriched_ip_factory, starttls_parser: starttls_parser
    ),
    timestamp_parser: MailParser::ReceivedHeaders::TimestampParser.new,
    classifier: MailParser::ReceivedHeaders::Classifier.new
  )
  parser.parse(value)
end
restore_sequence(values) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 85
def restore_sequence(values)
  values.sort { |a,b| b[:sequence] <=> a[:sequence] }
end
separate(contents) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 29
def separate(contents)
  contents.split("#{@line_ending}#{@line_ending}", 2)
end
unfold_headers(headers) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 37
def unfold_headers(headers)
  headers.gsub(/#{@line_ending}[\s\t]+/, ' ')
end
valid_base64_decoded(text) click to toggle source
# File lib/phisher_phinder/mail_parser.rb, line 89
def valid_base64_decoded(text)
  if Base64.strict_encode64(Base64.decode64(text)) == text.gsub(/#{@line_ending}/, '')
    Base64.decode64(text)
  end
end