From d14f54b0e085128b5305c806a4fe01f07b97b8fa Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 20 Sep 2018 17:16:19 -0700 Subject: Expand router with real routing object and 4-way address options --- lib/action_mailroom/router.rb | 22 ++++++++++++++++++---- lib/action_mailroom/router/route.rb | 26 ++++++++++++++++++++++++++ lib/action_mailroom/test_helper.rb | 2 ++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 lib/action_mailroom/router/route.rb (limited to 'lib') diff --git a/lib/action_mailroom/router.rb b/lib/action_mailroom/router.rb index bf0001f1ae..c3fa183438 100644 --- a/lib/action_mailroom/router.rb +++ b/lib/action_mailroom/router.rb @@ -1,20 +1,34 @@ class ActionMailroom::Router + class RoutingError < StandardError; end + def initialize - @routes = {} + @routes = [] end def add_routes(routes) - @routes.merge!(routes) + routes.each do |(address, mailbox_name)| + add_route address, to: mailbox_name + end + end + + def add_route(address, to:) + routes.append Route.new(address, to: to) end def route(inbound_email) - locate_mailbox(inbound_email).receive(inbound_email) + if mailbox = locate_mailbox(inbound_email) + mailbox.receive(inbound_email) + else + raise RoutingError + end end private attr_reader :routes def locate_mailbox(inbound_email) - "#{routes[inbound_email.mail.to.first].to_s.capitalize}Mailbox".constantize + routes.detect { |route| route.match?(inbound_email) }.try(:mailbox_class) end end + +require "action_mailroom/router/route" diff --git a/lib/action_mailroom/router/route.rb b/lib/action_mailroom/router/route.rb new file mode 100644 index 0000000000..316c77d711 --- /dev/null +++ b/lib/action_mailroom/router/route.rb @@ -0,0 +1,26 @@ +class ActionMailroom::Router::Route + class InvalidAddressError < StandardError; end + + attr_reader :address, :mailbox_name + + def initialize(address, to:) + @address, @mailbox_name = address, to + end + + def match?(inbound_email) + case address + when String + inbound_email.mail.to.include?(address) + when Regexp + inbound_email.mail.to.detect { |recipient| address.match?(recipient) } + when Proc + address.call(inbound_email) + else + address.try(:match?, inbound_email) || raise(InvalidAddressError) + end + end + + def mailbox_class + "#{mailbox_name.to_s.capitalize}Mailbox".constantize + end +end diff --git a/lib/action_mailroom/test_helper.rb b/lib/action_mailroom/test_helper.rb index fbfb2797d9..33d32ec899 100644 --- a/lib/action_mailroom/test_helper.rb +++ b/lib/action_mailroom/test_helper.rb @@ -1,3 +1,5 @@ +require "mail" + module ActionMailroom module TestHelper # Create an InboundEmail record using an eml fixture in the format of message/rfc822 -- cgit v1.2.3