diff options
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.rb | 61 |
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 |