forwarded_email_parser 0.2.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.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForwardedEmailParser
4
+ class ParsedEmail
5
+ attr_accessor :forwarded, :message, :email, :subject, :date, :from, :to, :cc, :body
6
+
7
+ def initialize(forwarded, message, email)
8
+ @forwarded = forwarded
9
+ @message = message
10
+ @email = email
11
+
12
+ @subject = email[:subject]
13
+ @date = email[:date]
14
+ @from = email[:from]
15
+ @to = email[:to]
16
+ @cc = email[:cc]
17
+ @body = email[:body]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForwardedEmailParser
4
+ class Parser
5
+ # Constructor
6
+ def initialize
7
+ @parser = EmailParser.new
8
+ end
9
+
10
+ # Attempts to parse a forwarded email
11
+ # @param [String] body
12
+ # @param [String, nil] subject
13
+ # @return [Hash] The parsed email
14
+ def parse(body, subject = nil)
15
+ email = {}
16
+ result = {}
17
+
18
+ # Check if email was forwarded or not (via the subject)
19
+
20
+ parsed_subject = @parser.parse_subject(subject) if subject
21
+ forwarded = !subject.nil? && !parsed_subject.nil?
22
+
23
+ # Check if email was forwarded or not (via the body)
24
+ if !subject || forwarded
25
+ result = @parser.parse_body(body, forwarded)
26
+ if result[:email]
27
+ forwarded = true
28
+ email = @parser.parse_original_email(result[:email], result[:body])
29
+ end
30
+ end
31
+
32
+ email[:subject] = parsed_subject if (email[:subject].nil? || email[:subject].empty?) && parsed_subject
33
+ ParsedEmail.new(forwarded, result[:message], email)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForwardedEmailParser
4
+ class Utils
5
+ class << self
6
+ # Executes multiple regular expressions until one succeeds
7
+ # @param regexes [Array<Regexp, String>] Array of regexes or regex strings
8
+ # @param str [String] The string to match against
9
+ # @param mode [String] The mode of operation ('match', 'split', or 'replace')
10
+ # @param highest_position [Boolean] Whether to find the highest position match
11
+ # @return [Array, String] The result of the first successful regular expression
12
+ def loop_regexes(regexes, str, mode = "match", highest_position = true)
13
+ match = nil
14
+ min_length = mode == "split" ? 1 : 0
15
+ max_length = str.length
16
+
17
+ regexes.each do |regex|
18
+ regex = Regexp.new(regex) if regex.is_a?(String)
19
+
20
+ current_match = case mode
21
+ when "match"
22
+ str.match(regex)
23
+ when "split"
24
+ str.split(regex)
25
+ when "replace"
26
+ str.gsub(regex, "")
27
+ end || ""
28
+
29
+ if mode == "replace"
30
+ match = current_match
31
+ break if match.length < max_length
32
+ elsif %w[split match].include?(mode)
33
+ if (current_match || []).length > min_length
34
+ if highest_position
35
+ if !match
36
+ match = current_match
37
+ else
38
+ higher = if mode == "match"
39
+ match.begin(0) > current_match.begin(0)
40
+ else
41
+ match[0].length > current_match[0].length
42
+ end
43
+ match = current_match if higher
44
+ end
45
+ else
46
+ match = current_match
47
+ break
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ mode == "replace" ? (match || "") : (match || [])
54
+ end
55
+
56
+ # Reconciliates match substrings after a "split" operation
57
+ # @param match [Array] The match result
58
+ # @param min_substrings [Integer] Minimum number of substrings
59
+ # @param default_substrings [Array<Integer>] Indices of default substrings
60
+ # @param exclude_proc [Proc] Optional proc to determine substring exclusion
61
+ # @return [String] The reconciliated string
62
+ def reconciliate_split_match(match, min_substrings, default_substrings, exclude_proc = nil)
63
+ str = ""
64
+
65
+ default_substrings.each do |index|
66
+ str += match[index]
67
+ end
68
+
69
+ if match.length > min_substrings
70
+ (min_substrings...match.length).each do |i|
71
+ exclude = exclude_proc&.call(i)
72
+ str += match[i] unless exclude
73
+ end
74
+ end
75
+
76
+ str
77
+ end
78
+
79
+ # Trims a string
80
+ # @param str [String] The string to trim
81
+ # @return [String] The trimmed string
82
+ def trim_string(str)
83
+ (str || "").strip
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForwardedEmailParser
4
+ VERSION = "0.2.1"
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "forwarded_email_parser/parsed_email"
4
+ require_relative "forwarded_email_parser/version"
5
+ require_relative "forwarded_email_parser/utils"
6
+ require_relative "forwarded_email_parser/email_parser"
7
+ require_relative "forwarded_email_parser/parser"
8
+
9
+ module ForwardedEmailParser
10
+ class Error < StandardError; end
11
+ end
@@ -0,0 +1,4 @@
1
+ module ForwardedEmailParser
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: forwarded_email_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Clayton Lengel-Zigich
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Extract information from forwarded emails. Cloned from https://github.com/crisp-oss/email-forward-parser.
14
+ email:
15
+ - 6334+clayton@users.noreply.github.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".byebug_history"
21
+ - ".rubocop.yml"
22
+ - CHANGELOG.md
23
+ - CODE_OF_CONDUCT.md
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - lib/forwarded_email_parser.rb
28
+ - lib/forwarded_email_parser/email_parser.rb
29
+ - lib/forwarded_email_parser/parsed_email.rb
30
+ - lib/forwarded_email_parser/parser.rb
31
+ - lib/forwarded_email_parser/utils.rb
32
+ - lib/forwarded_email_parser/version.rb
33
+ - sig/email_forward_parser.rbs
34
+ homepage: https://github.com/clayton/forwarded_email_parser
35
+ licenses:
36
+ - MIT
37
+ metadata:
38
+ allowed_push_host: https://rubygems.org
39
+ homepage_uri: https://github.com/clayton/forwarded_email_parser
40
+ source_code_uri: https://github.com/clayton/forwarded_email_parser
41
+ changelog_uri: https://github.com/clayton/forwarded_email_parser/CHANGELOG.md
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 3.0.0
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubygems_version: 3.5.17
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Parses forwarded emails.
61
+ test_files: []