Created
March 19, 2015 23:43
-
-
Save NGMarmaduke/a088943edbe4e703129d to your computer and use it in GitHub Desktop.
Revisions
-
NGMarmaduke created this gist
Mar 19, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,194 @@ class OfficeAPIError < StandardError; end; class OfficeAPITimoutError < StandardError def initialize(msg = "Office API timed out") super(msg) end end class OfficeAPI attr_accessor :access_token, :messages_filter, :mail_box, :fetch_from def initialize(mail_box) @mail_box = mail_box end def get_root_path "EWS/ODATA/users/#{@mail_box}" end def message_endpoint end_point = "/folders/inbox/messages?" + "$select=Id,Subject,BodyPreview,UniqueBody,HasAttachments,Sender,DateTimeReceived,DateTimeSent" end_point += "&$filter=DateTimeReceived ge #{@fetch_from}" if @fetch_from return end_point end def fetch_from_date(date) @fetch_from = (date+1.second).strftime("%Y-%m-%dT%H:%M:%SZ") end def request_messages begin t1 = Time.now res = api_connection.get do |req| req.url "#{get_root_path}#{message_endpoint}" req.headers = OfficeAPI.request_headers end t2 = Time.now OfficeAPI.do_log "Polling request time: #{((t2 - t1) * 1000.0).to_i}ms" return (JSON.parse res.body)['value'] rescue StandardError => e OfficeAPI.log_exception(e) OfficeAPI.do_log("Response: #{res.inspect}", 'E') return [] end end def request_message(id) filters = "?$select=Id,Subject,BodyPreview,Body,UniqueBody,HasAttachments,Sender,DateTimeReceived,DateTimeSent" res = api_connection.get do |req| req.url "#{get_root_path}/messages/#{id}#{filters}" req.headers = OfficeAPI.request_headers end OfficeAPI.do_log "#{res.inspect}".red return (JSON.parse res.body) end def mark_as_read(id) res = api_connection.patch do |req| req.url "#{get_root_path}/messages/#{id}" req.headers = OfficeAPI.request_headers req.body = '{ "IsRead": true }' end return (res.status == 200) end def request_attachment_details(id) res = api_connection.get do |req| req.url "#{get_root_path}/messages/#{id}/attachments" req.headers = OfficeAPI.request_headers end return (JSON.parse res.body)['value'] end def request_attachment_data(message_id, attachment_id) res = api_connection.get do |req| req.url "#{get_root_path}/messages/#{message_id}/attachments/#{attachment_id}" req.headers = OfficeAPI.request_headers end return (JSON.parse res.body)['ContentBytes'] end def api_connection Faraday.new(:url => 'https://outlook.office365.com') do |faraday| faraday.adapter :net_http # make requests with Net::HTTP faraday.options[:timeout] = 10 end end class << self def cert_path File.join(Rails.root, "certs", "office_365") end def client_key pk = File.join(cert_path, "pk.pem") return OpenSSL::PKey::RSA.new(File.read(pk)) end def request_headers { :user_agent => 'spreadyO365Poller/1.0', 'client-request-id' => SecureRandom.uuid, 'Date' => Time.now.httpdate, 'Content-Type' => 'application/json', 'Authorization' => "Bearer #{get_jwt}" } end def get_jwt request_token unless access_token_valid? @access_token['access_token'] end def access_token_valid? return (@access_token.present? and DateTime.now < DateTime.strptime(@access_token['expires_on'], '%s') - 1.minute) end def request_token login = Faraday.new(:url => 'https://login.windows.net') do |faraday| faraday.request :url_encoded # form-encode POST param faraday.adapter :net_http # make requests with Net::HTTP end self.do_log "Reqesting OAuth Token" response = login.post '/TENANT_ID/oauth2/token?api-version=1.0', { :grant_type => 'client_credentials', :redirect_uri => 'http://spready.dev', :resource => 'https://outlook.office365.com/', :client_id => 'YOUR CLIENT ID', :client_assertion_type => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer', :client_assertion => generate_jwt } @access_token = (JSON.parse response.body) self.do_log "Recieved Token".green self.do_log @access_token.inspect end def generate_jwt header = { 'alg' => 'RS256', 'x5t' => 'CERT_THUMBPRINT' }.to_json payload = { 'aud' => 'https://login.windows.net/TENANT_ID/oauth2/token', 'nbf' => Time.now.to_i, 'exp' => (Time.now + 15.minutes).to_i, 'jti' => SecureRandom.uuid, 'sub' => 'YOUR CLIENT ID', 'iss' => 'YOUR CLIENT ID', }.to_json base64_token = "#{Base64.strict_encode64(header)}.#{Base64.strict_encode64(payload)}" digest = OpenSSL::Digest::SHA256.new signature = client_key.sign digest, base64_token base64_signature = Base64.strict_encode64(signature) @request_token = "#{base64_token}.#{base64_signature}" end def logger=(logger) @logger = logger end def logger @logger || Rails.logger end def log_exception(e) do_log("Exception occured while retrieving messages:".red, "E") do_log([e, *e.backtrace].join("\n"), "E") if e.class == Net::ReadTimeout || e.class == Faraday::Error::TimeoutError airbrakeException = OfficeAPITimoutError.new() else airbrakeException = OfficeAPIError.new() end airbrakeException.set_backtrace e.backtrace Airbrake.notify(airbrakeException) end def do_log(message, flag='I') logger.info "#{flag}: #{DateTime.now}" + " #{message}" end end end