aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/action_mailroom/router.rb22
-rw-r--r--lib/action_mailroom/router/route.rb26
-rw-r--r--lib/action_mailroom/test_helper.rb2
-rw-r--r--test/unit/router_test.rb43
4 files changed, 89 insertions, 4 deletions
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
diff --git a/test/unit/router_test.rb b/test/unit/router_test.rb
index 8cc7bd8810..25a2651bb6 100644
--- a/test/unit/router_test.rb
+++ b/test/unit/router_test.rb
@@ -13,6 +13,12 @@ end
class SecondMailbox < RootMailbox
end
+class FirstMailboxAddress
+ def match?(inbound_email)
+ inbound_email.mail.to.include?("replies-class@example.com")
+ end
+end
+
module ActionMailroom
class RouterTest < ActiveSupport::TestCase
setup do
@@ -42,5 +48,42 @@ module ActionMailroom
assert_equal "SecondMailbox", $processed_by
assert_equal inbound_email.mail, $processed_mail
end
+
+ test "single regexp route" do
+ @router.add_routes(/replies-\w+@example.com/ => :first, "replies-nowhere@example.com" => :second)
+
+ inbound_email = create_inbound_email_from_mail(to: "replies-okay@example.com", subject: "This is a reply")
+ @router.route inbound_email
+ assert_equal "FirstMailbox", $processed_by
+ end
+
+ test "single proc route" do
+ @router.add_route \
+ ->(inbound_email) { inbound_email.mail.to.include?("replies-proc@example.com") },
+ to: :second
+
+ @router.route create_inbound_email_from_mail(to: "replies-proc@example.com", subject: "This is a reply")
+ assert_equal "SecondMailbox", $processed_by
+ end
+
+ test "address class route" do
+ @router.add_route FirstMailboxAddress.new, to: :first
+ @router.route create_inbound_email_from_mail(to: "replies-class@example.com", subject: "This is a reply")
+ assert_equal "FirstMailbox", $processed_by
+ end
+
+ test "missing route" do
+ assert_raises(ActionMailroom::Router::RoutingError) do
+ inbound_email = create_inbound_email_from_mail(to: "going-nowhere@example.com", subject: "This is a reply")
+ @router.route inbound_email
+ end
+ end
+
+ test "invalid address" do
+ assert_raises(ActionMailroom::Router::Route::InvalidAddressError) do
+ @router.add_route Array.new, to: :first
+ @router.route create_inbound_email_from_mail(to: "replies-nowhere@example.com", subject: "This is a reply")
+ end
+ end
end
end