-
-
Save jbsmith86/3db66ff792a973a481da to your computer and use it in GitHub Desktop.
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 characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment