class RulesEvaluator def evaluate(email) RuleSet.enabled.each do |rule_set| if evaluate_rule_set(email, rule_set) rule_set.actions.enabled.each do |action| klass = action.class_name.constantize email = klass.new.process(email) # rescue NameError => ex # # TODO: log a warning end end end email end def evaluate_rule_set(email, rule_set) rules_state = true rule_set.rules.enabled.each do |rule| subjects = prepare_subjects(email, rule) result = apply_rule(subjects, rule) result = ! result if rule.inverted? rules_state = apply_operator(rules_state, rule_set.operator, result) break unless rules_state end rules_state end private def prepare_subjects(email, rule) case rule.subject_type.downcase when "header" Array(email.header_values(rule.subject_value)) when "body" Array(email.plain_body) else raise ArgumentError, "Unrecognized subject type '#{rule.subject_type}'" end end def apply_rule(subjects, rule) case rule.condition_type.downcase when "match", "matches" subjects.any? { |subject| pattern = Regexp.new(rule.condition_value) subject.match? } when "equal", "equals" subjects.any? { |subject| subject == rule.condition_value } when "start", "starts" subjects.any? { |subject| subject.starts_with? rule.condition_value } when "end", "ends" subjects.any? { |subject| subject.ends_with? rule.condition_value } when "contain", "contains" subjects.any? { |subject| subject.include? rule.condition_value } when "exist", "exists" subjects.any? { |subject| subject.exists? } when "empty" subjects.all? { |subject| subject.empty? } when "date_before" # subjects.all? { |subject| # subject.empty? # } when "date_after" # subjects.all? { |subject| # subject.empty? # } else true end def apply_operator(state, operator, result) case operator.upcase when "AND" (state and result) when "OR" (state or result) when "XOR" (state or result) and not (rules_state and result) else raise ArgumentError, "Unrecognized logic '#{rule_set.operator}'" end end end end