Class: Cloudfuji::Mailroute

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudfuji/mail_route.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMailroute

Returns a new instance of Mailroute.



95
96
97
# File 'lib/cloudfuji/mail_route.rb', line 95

def initialize
  @routes ||= ActiveSupport::OrderedHash.new
end

Instance Attribute Details

#constraintsObject

Returns the value of attribute constraints.



67
68
69
# File 'lib/cloudfuji/mail_route.rb', line 67

def constraints
  @constraints
end

#current_targetObject

Returns the value of attribute current_target.



67
68
69
# File 'lib/cloudfuji/mail_route.rb', line 67

def current_target
  @current_target
end

#paramsObject

Returns the value of attribute params.



67
68
69
# File 'lib/cloudfuji/mail_route.rb', line 67

def params
  @params
end

#replyObject

Returns the value of attribute reply.



67
68
69
# File 'lib/cloudfuji/mail_route.rb', line 67

def reply
  @reply
end

#routesObject

Returns the value of attribute routes.



67
68
69
# File 'lib/cloudfuji/mail_route.rb', line 67

def routes
  @routes
end

Class Method Details

.clear_routes!Object



14
15
16
# File 'lib/cloudfuji/mail_route.rb', line 14

def clear_routes!
  @@routes = nil
end

.field_matcher(*field_names) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/cloudfuji/mail_route.rb', line 53

def field_matcher(*field_names)
  class_eval do
    field_names.each do |field_name|
      define_method field_name do |line, *args|
        constraints = args.first || {}
        required    = args[1]

        add_route_rule(field_name.to_s, build_matcher(line, constraints), required)
      end
    end
  end
end

.map {|routes| ... } ⇒ Object

Yields:

Raises:

  • (StandardError)


4
5
6
7
8
# File 'lib/cloudfuji/mail_route.rb', line 4

def map(&block)
  raise StandardError.new("Mailroute only supported in Ruby >= 1.9.1") if RUBY_VERSION < "1.9.1"

  yield routes
end

.pretty_print_contraint(constraint, prefix = "") ⇒ Object



35
36
37
38
# File 'lib/cloudfuji/mail_route.rb', line 35

def pretty_print_contraint(constraint, prefix="")
  output = "#{prefix}Constraint: #{constraint.inspect}"
  puts output
end

.pretty_print_routesObject



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/cloudfuji/mail_route.rb', line 18

def pretty_print_routes
  routes.routes.each_pair do |route_name, definition|
    puts "#{route_name} => "
    definition[:rules].each do |rule|
      pretty_print_rule(rule, "\t\t")
    end
    definition[:constraints].each do |constraint|
      pretty_print_contraint(constraint, "\t\t")
    end
  end
end

.pretty_print_rule(rule, prefix = "") ⇒ Object



30
31
32
33
# File 'lib/cloudfuji/mail_route.rb', line 30

def pretty_print_rule(rule, prefix="")
  output = "#{prefix}#{rule.first} => #{string_to_regex(rule[1]).inspect}, required? #{rule.last == true}"
  puts output
end

.routesObject



10
11
12
# File 'lib/cloudfuji/mail_route.rb', line 10

def routes
  @@routes ||= new
end

.string_to_regex(string) ⇒ Object

Taken from somewhere on stackoverflow, props to the author!



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/cloudfuji/mail_route.rb', line 41

def string_to_regex(string)
  return nil unless string.strip.match(/\A\/(.*)\/(.*)\Z/mx)
  regexp , flags = $1 , $2
  return nil if !regexp || flags =~ /[^xim]/m

  x = /x/.match(flags) && Regexp::EXTENDED
  i = /i/.match(flags) && Regexp::IGNORECASE
  m = /m/.match(flags) && Regexp::MULTILINE

  Regexp.new regexp , [x,i,m].inject(0){|a,f| f ? a+f : a }
end

Instance Method Details

#add_constraint(params_field_name, requirement_type) ⇒ Object

Maybe add_requirement is better? Constraint procs must return true if the mail should be allowed

Raises:

  • (StandardError)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/cloudfuji/mail_route.rb', line 106

def add_constraint(params_field_name, requirement_type)
  checkers = {
    :not_allowed => Proc.new { |params| params[params_field_name.to_s].nil? },
    :required    => Proc.new { |params| not params[params_field_name.to_s].nil? },
    :custom      => Proc.new { |params| requirement_type.call(params[params_field_name.to_s]) }
  }

  checker = requirement_type.is_a?(Proc) ? checkers[:custom] : checkers[requirement_type]

  raise StandardError if checker.nil?

  @routes[@current_target][:constraints] << checker
  @routes[@current_target][:constraints].flatten! # In case we've added a nil
end

#ampmObject

Regex shortcuts



71
72
73
# File 'lib/cloudfuji/mail_route.rb', line 71

def ampm
  /\d+[apmAPM]{2}/
end

#monthObject



87
88
89
# File 'lib/cloudfuji/mail_route.rb', line 87

def month
  /((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))/
end

#numberObject



79
80
81
# File 'lib/cloudfuji/mail_route.rb', line 79

def number
  /\d+/
end

#process(mail) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/cloudfuji/mail_route.rb', line 121

def process(mail)
  @params = preprocess_mail(mail)

  # Iterate through the routes and test each rule for each route against current mail
  @routes.each_pair do |route_name, definition|
    _matches = true

    # route: {'name-of-route' => {:rules => [[:field, matcher]], :constraints => []}}
    definition[:rules].each do |matcher|
      result = self.class.string_to_regex(matcher[1]).match(mail[matcher.first])
      if result.nil?
        _matches = false
        break
      end

      # Only Ruby 1.9 support named capture groups
      result.names.each { |key| @params[key] = result[key] }
    end

    # Run param-based constraints
    if _matches and constraints_pass?(definition[:constraints], params)
      @params['mail'] = mail
      puts "Firing: #{@params.inspect}, #{route_name}"
      return Cloudfuji::Data.fire(params, "mail_#{route_name.gsub('.', '_')}")
      break
    end

  end
end

#route(target) {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:



99
100
101
102
# File 'lib/cloudfuji/mail_route.rb', line 99

def route(target, &block)
  @routes[@current_target = target] = {:rules => [], :constraints => []}
  yield self
end

#wordObject



75
76
77
# File 'lib/cloudfuji/mail_route.rb', line 75

def word
  /\w+/
end

#words_and_spacesObject



83
84
85
# File 'lib/cloudfuji/mail_route.rb', line 83

def words_and_spaces
  /[\w|\s]+/
end

#yearObject



91
92
93
# File 'lib/cloudfuji/mail_route.rb', line 91

def year
  /((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])/
end