aboutsummaryrefslogblamecommitdiffstats
path: root/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb
blob: 46b097759229dbf4d2fbda09f7f323b14e13d465 (plain) (tree)
1
2
3
4
5
6
7
8



                                                                                                
                                                                                          


         




                                              




                                              

       

                         


                                                    
                                                                             










                                                                                   
                                                                                  
                   
                                             




                                                                                          

       
class ActionMailbox::Ingresses::Mailgun::InboundEmailsController < ActionMailbox::BaseController
  before_action :ensure_authenticated

  def create
    ActionMailbox::InboundEmail.create_and_extract_message_id! params.require("body-mime")
  end

  private
    def ensure_authenticated
      head :unauthorized unless authenticated?
    end

    def authenticated?
      Authenticator.new(
        timestamp: params.require(:timestamp),
        token:     params.require(:token),
        signature: params.require(:signature)
      ).authenticated?
    end

    class Authenticator
      cattr_accessor :key
      attr_reader :timestamp, :token, :signature

      def initialize(timestamp:, token:, signature:)
        @timestamp, @token, @signature = Integer(timestamp), token, signature
      end

      def authenticated?
        signed? && recent?
      end

      private
        def signed?
          ActiveSupport::SecurityUtils.secure_compare signature, expected_signature
        end

        # Allow for 2 minutes of drift between Mailgun time and local server time.
        def recent?
          Time.at(timestamp) >= 2.minutes.ago
        end

        def expected_signature
          OpenSSL::HMAC.hexdigest OpenSSL::Digest::SHA256.new, key, "#{timestamp}#{token}"
        end
    end
end