aboutsummaryrefslogtreecommitdiffstats
path: root/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb')
-rw-r--r--app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb61
1 files changed, 61 insertions, 0 deletions
diff --git a/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb b/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb
new file mode 100644
index 0000000000..4d194a3e00
--- /dev/null
+++ b/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb
@@ -0,0 +1,61 @@
+class ActionMailbox::Ingresses::Mailgun::InboundEmailsController < ActionMailbox::BaseController
+ before_action :ensure_authenticated
+
+ def create
+ ActionMailbox::InboundEmail.create_and_extract_message_id! raw_email
+ head :ok
+ end
+
+ private
+ def raw_email
+ StringIO.new params.require("body-mime")
+ end
+
+
+ def ensure_authenticated
+ head :unauthorized unless authenticated?
+ end
+
+ def authenticated?
+ Authenticator.new(authentication_params).authenticated?
+ rescue ArgumentError
+ false
+ end
+
+ def authentication_params
+ params.permit(:timestamp, :token, :signature).to_h.symbolize_keys
+ end
+
+
+ class Authenticator
+ cattr_accessor :key
+
+ attr_reader :timestamp, :token, :signature
+
+ def initialize(timestamp:, token:, signature:)
+ @timestamp, @token, @signature = timestamp, token, signature
+ end
+
+ def authenticated?
+ signed? && recent?
+ end
+
+ private
+ def signed?
+ ActiveSupport::SecurityUtils.secure_compare signature, expected_signature
+ end
+
+ # Allow for 10 minutes of drift between Mailgun time and local server time.
+ def recent?
+ time >= 10.minutes.ago
+ end
+
+ def expected_signature
+ OpenSSL::HMAC.hexdigest OpenSSL::Digest::SHA256.new, key, "#{timestamp}#{token}"
+ end
+
+ def time
+ Time.at Integer(timestamp)
+ end
+ end
+end