Module: Mailmate::FilterClassifier Private
- Defined in:
- lib/mailmate/filter_classifier.rb
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
Constant Summary collapse
- INDEX_BACKED_HEADS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Heads served by an on-disk index in Database.noindex/Headers/<name>.
%w[ #flags ##tags #date #date-received #date-sent #date-last-viewed ].freeze
- HEADER_HEADS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Heads that resolve from .eml header bytes (vs. body).
%w[ from to cc bcc reply-to sender resent-from resent-to resent-cc resent-bcc subject list-id message-id in-reply-to references x-mailer user-agent x-newsreader received delivered-to #recipient #any-address #mailer ##thread-id ].freeze
- BODY_HEADS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Heads that require the body to resolve.
%w[#unquoted #quoted #common #commonplus].freeze
- PREFILTER_HEADS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Heads whose literals appear textually in the .eml header bytes (so they’re safe pre-filter candidates).
%w[ from to cc bcc reply-to sender subject list-id message-id in-reply-to references x-mailer user-agent x-newsreader #recipient #any-address #mailer ].freeze
Class Method Summary collapse
-
.collect_path_heads(ast) ⇒ Object
private
—- internals —-.
-
.combine_tiers(*tiers) ⇒ Object
private
Combine multiple tiers; the strictest wins.
-
.header_literals(ast) ⇒ Object
private
ASCII literals from top-level AND-chained header-path comparisons, which are guaranteed to appear (substring-wise) in any matching message’s raw header bytes.
- .literal_from(node) ⇒ Object private
-
.tier(ast) ⇒ Object
private
Returns one of :index, :header, :full.
-
.tier_for_paths(paths) ⇒ Object
private
Same idea but for a list of attribute paths (e.g. fields the user wants output, or paths the user-search specs reference).
- .walk(ast) {|ast| ... } ⇒ Object private
- .walk_top_and(ast) ⇒ Object private
Class Method Details
.collect_path_heads(ast) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
—- internals —-
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/mailmate/filter_classifier.rb', line 81 def self.collect_path_heads(ast) heads = [] walk(ast) do |n| case n when AST::CompareNode, AST::ExistsNode heads << n.path[0] when AST::VarRefNode # var refs are evaluated by walking the referenced mailbox, # which is its own search. The OUTER caller doesn't need to load # body for a var ref — only headers/index, depending on the # path's head on the LHS side. The inner mailbox walk classifies # itself when it runs (via VarResolver's own header-only scan). end end heads end |
.combine_tiers(*tiers) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Combine multiple tiers; the strictest wins. (full > header > index)
65 66 67 68 69 |
# File 'lib/mailmate/filter_classifier.rb', line 65 def self.combine_tiers(*tiers) return :full if tiers.include?(:full) return :header if tiers.include?(:header) :index end |
.header_literals(ast) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
ASCII literals from top-level AND-chained header-path comparisons, which are guaranteed to appear (substring-wise) in any matching message’s raw header bytes. Skips OR branches (literals there are alternatives, not requirements) and skips negated comparisons.
75 76 77 |
# File 'lib/mailmate/filter_classifier.rb', line 75 def self.header_literals(ast) walk_top_and(ast).flat_map { |node| literal_from(node) }.compact.uniq end |
.literal_from(node) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
113 114 115 116 117 118 119 120 121 |
# File 'lib/mailmate/filter_classifier.rb', line 113 def self.literal_from(node) return [] unless node.is_a?(AST::CompareNode) return [] if %w[!= !~].include?(node.op) return [] unless PREFILTER_HEADS.include?(node.path[0]) return [] unless node.value.is_a?(AST::LiteralStringNode) s = node.value.value return [] unless s.bytesize >= 3 && s.ascii_only? [s.downcase] end |
.tier(ast) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns one of :index, :header, :full.
48 49 50 51 52 53 |
# File 'lib/mailmate/filter_classifier.rb', line 48 def self.tier(ast) heads = collect_path_heads(ast) return :full if heads.any? { |h| BODY_HEADS.include?(h) } return :index if heads.all? { |h| INDEX_BACKED_HEADS.include?(h) } :header end |
.tier_for_paths(paths) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Same idea but for a list of attribute paths (e.g. fields the user wants output, or paths the user-search specs reference).
57 58 59 60 61 62 |
# File 'lib/mailmate/filter_classifier.rb', line 57 def self.tier_for_paths(paths) heads = paths.map { |p| Array(p).first }.compact return :full if heads.any? { |h| BODY_HEADS.include?(h) } return :index if !heads.empty? && heads.all? { |h| INDEX_BACKED_HEADS.include?(h) } :header end |
.walk(ast) {|ast| ... } ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
98 99 100 101 102 103 104 |
# File 'lib/mailmate/filter_classifier.rb', line 98 def self.walk(ast, &blk) yield ast case ast when AST::AndNode, AST::OrNode then ast.children.each { |c| walk(c, &blk) } when AST::NotNode then walk(ast.child, &blk) end end |
.walk_top_and(ast) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
106 107 108 109 110 111 |
# File 'lib/mailmate/filter_classifier.rb', line 106 def self.walk_top_and(ast) case ast when AST::AndNode then ast.children.flat_map { |c| walk_top_and(c) } else [ast] end end |