ruby_outlook 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+
7
+ # Standard to msysgit
8
+ *.doc diff=astextplain
9
+ *.DOC diff=astextplain
10
+ *.docx diff=astextplain
11
+ *.DOCX diff=astextplain
12
+ *.dot diff=astextplain
13
+ *.DOT diff=astextplain
14
+ *.pdf diff=astextplain
15
+ *.PDF diff=astextplain
16
+ *.rtf diff=astextplain
17
+ *.RTF diff=astextplain
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby_outlook.gemspec
4
+ gemspec
@@ -0,0 +1,25 @@
1
+ ruby-outlook https://github.com/jasonjoh/ruby-outlook
2
+
3
+ Copyright (c) Microsoft Corporation
4
+ All rights reserved.
5
+
6
+ MIT License:
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ ""Software""), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,121 @@
1
+ # RubyOutlook
2
+
3
+ The RubyOutlook gem is a light-weight implementation of the Office 365 [Mail](https://msdn.microsoft.com/office/office365/APi/mail-rest-operations), [Calendar](https://msdn.microsoft.com/office/office365/APi/calendar-rest-operations), and [Contacts](https://msdn.microsoft.com/office/office365/APi/contacts-rest-operations) REST APIs. It provides basic CRUD functionality for all three APIs, along with the ability to extend functionality by making any arbitrary API call.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ruby_outlook'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ruby_outlook
20
+
21
+ ## Usage
22
+
23
+ ### Create the client
24
+
25
+ All functionality is accessed via the `Client` class. Create a new instance of the class to use it:
26
+
27
+ ```ruby
28
+ require 'ruby_outlook'
29
+ outlook_client = RubyOutlook::Client.new
30
+ ```
31
+
32
+ In addition, you can set the `enable_fiddler` property on the `Client` to true if you want to capture Fiddler traces. Setting this property to true sets the proxy for all traffic to `http://127.0.0.1:8888` (the default Fiddler proxy value), and turns off SSL verification. Note that if you set this property to true and do not have Fiddler running, all requests will fail.
33
+
34
+ ### Using a built-in function
35
+
36
+ All of the built-in functions have a required `token` parameter and an optional `user` parameter. The `token` parameter is the OAuth2 access token required for authentication. The `user` parameter is an email address. If passed, the library will make the call to that user's mailbox using the `/Users/user@domain.com/` URL. If omitted, the library will make the call using the `'/Me'` URL.
37
+
38
+ Other parameters are specific to the call being made. For example, here's how to call `get_contacts`:
39
+
40
+ ```ruby
41
+ # A valid access token retrieved via OAuth2
42
+ token = 'eyJ0eXAiOiJKV1QiLCJhbGciO...'
43
+ # Maximum 30 results per page.
44
+ view_size = 30
45
+ # Set the page from the query parameter.
46
+ page = 1
47
+ # Only retrieve display name.
48
+ fields = [
49
+ "DisplayName"
50
+ ]
51
+ # Sort by display name
52
+ sort = { :sort_field => 'DisplayName', :sort_order => 'ASC' }
53
+
54
+ contacts = outlook_client.get_contacts token,
55
+ view_size, page, fields, sort
56
+ ```
57
+
58
+ ### Extending functionality
59
+
60
+ All of the built-in functions wrap the `make_api_call` function. If there is not a built-in function that suits your needs, you can use the `make_api_call` function to implement any API call you want.
61
+
62
+ ```ruby
63
+ # method (string): The HTTP method to use for the API call.
64
+ # Must be 'GET', 'POST', 'PATCH', or 'DELETE'
65
+ # url (string): The URL to use for the API call. Must not contain
66
+ # the host. For example: '/api/v1.0/me/messages'
67
+ # token (string): access token
68
+ # params (hash) a Ruby hash containing any query parameters needed for the API call
69
+ # payload (hash): a JSON hash representing the API call's payload. Only used
70
+ # for POST or PATCH.
71
+ def make_api_call(method, url, token, params = nil, payload = nil)
72
+ ```
73
+
74
+ As an example, here's how the library implements `get_contacts`:
75
+
76
+ ```ruby
77
+ # token (string): access token
78
+ # view_size (int): maximum number of results
79
+ # page (int): What page to fetch (multiple of view size)
80
+ # fields (array): An array of field names to include in results
81
+ # sort (hash): { sort_on => field_to_sort_on, sort_order => 'ASC' | 'DESC' }
82
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
83
+ def get_contacts(token, view_size, page, fields = nil, sort = nil, user = nil)
84
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Contacts"
85
+ request_params = {
86
+ '$top' => view_size,
87
+ '$skip' => (page - 1) * view_size
88
+ }
89
+
90
+ if not fields.nil?
91
+ request_params['$select'] = fields.join(',')
92
+ end
93
+
94
+ if not sort.nil?
95
+ request_params['$orderby'] = sort[:sort_field] + " " + sort[:sort_order]
96
+ end
97
+
98
+ get_contacts_response = make_api_call "GET", request_url, token, request_params
99
+
100
+ return JSON.parse(get_contacts_response)
101
+ end
102
+ ```
103
+
104
+ Follow the same pattern to implement your own calls.
105
+
106
+ ## Contributing
107
+
108
+ 1. Fork it ( https://github.com/jasonjoh/ruby_outlook/fork )a
109
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
110
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
111
+ 4. Push to the branch (`git push origin my-new-feature`)
112
+ 5. Create a new Pull Request
113
+
114
+ ## Copyright ##
115
+
116
+ Copyright (c) Microsoft. All rights reserved.
117
+
118
+ ----------
119
+ Connect with me on Twitter [@JasonJohMSFT](https://twitter.com/JasonJohMSFT)
120
+
121
+ Follow the [Exchange Dev Blog](http://blogs.msdn.com/b/exchangedev/)
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruby_outlook"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,414 @@
1
+ require "ruby_outlook/version"
2
+ require "faraday"
3
+ require "uuidtools"
4
+ require "json"
5
+
6
+ module RubyOutlook
7
+
8
+ class Client
9
+ # User agent
10
+ attr_reader :user_agent
11
+ # The server to make API calls to.
12
+ # Always "https://outlook.office365.com"
13
+ attr_writer :api_host
14
+ attr_writer :enable_fiddler
15
+
16
+ # method (string): The HTTP method to use for the API call.
17
+ # Must be 'GET', 'POST', 'PATCH', or 'DELETE'
18
+ # url (string): The URL to use for the API call. Must not contain
19
+ # the host. For example: '/api/v1.0/me/messages'
20
+ # token (string): access token
21
+ # params (hash) a Ruby hash containing any query parameters needed for the API call
22
+ # payload (hash): a JSON hash representing the API call's payload. Only used
23
+ # for POST or PATCH.
24
+ def make_api_call(method, url, token, params = nil, payload = nil)
25
+
26
+ conn_params = {
27
+ :url => 'https://outlook.office365.com'
28
+ }
29
+
30
+ if @enable_fiddler
31
+ conn_params[:proxy] = 'http://127.0.0.1:8888'
32
+ conn_params[:ssl] = {:verify => false}
33
+ end
34
+
35
+ conn = Faraday.new(conn_params) do |faraday|
36
+ # Uses the default Net::HTTP adapter
37
+ faraday.adapter Faraday.default_adapter
38
+
39
+ end
40
+
41
+ conn.headers = {
42
+ 'Authorization' => "Bearer #{token}",
43
+ 'Accept' => "application/json",
44
+
45
+ # Client instrumentation
46
+ # See https://msdn.microsoft.com/EN-US/library/office/dn720380(v=exchg.150).aspx
47
+ 'User-Agent' => @user_agent,
48
+ 'client-request-id' => UUIDTools::UUID.timestamp_create.to_str,
49
+ 'return-client-request-id' => "true"
50
+ }
51
+
52
+ case method.upcase
53
+ when "GET"
54
+ response = conn.get do |request|
55
+ request.url url, params
56
+ end
57
+ when "POST"
58
+ conn.headers['Content-Type'] = "application/json"
59
+ response = conn.post do |request|
60
+ request.url url, params
61
+ request.body = JSON.dump(payload)
62
+ end
63
+ when "PATCH"
64
+ conn.headers['Content-Type'] = "application/json"
65
+ response = conn.patch do |request|
66
+ request.url url, params
67
+ request.body = JSON.dump(payload)
68
+ end
69
+ when "DELETE"
70
+ response = conn.delete do |request|
71
+ request.url url, params
72
+ end
73
+ end
74
+
75
+ if response.status >= 300
76
+ return JSON.dump({ 'ruby_outlook_error' => response.status})
77
+ end
78
+
79
+ return response.body
80
+ end
81
+
82
+ #----- Begin Contacts API -----#
83
+
84
+ # token (string): access token
85
+ # view_size (int): maximum number of results
86
+ # page (int): What page to fetch (multiple of view size)
87
+ # fields (array): An array of field names to include in results
88
+ # sort (hash): { sort_on => field_to_sort_on, sort_order => 'ASC' | 'DESC' }
89
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
90
+ def get_contacts(token, view_size, page, fields = nil, sort = nil, user = nil)
91
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Contacts"
92
+ request_params = {
93
+ '$top' => view_size,
94
+ '$skip' => (page - 1) * view_size
95
+ }
96
+
97
+ if not fields.nil?
98
+ request_params['$select'] = fields.join(',')
99
+ end
100
+
101
+ if not sort.nil?
102
+ request_params['$orderby'] = sort[:sort_field] + " " + sort[:sort_order]
103
+ end
104
+
105
+ get_contacts_response = make_api_call "GET", request_url, token, request_params
106
+
107
+ return JSON.parse(get_contacts_response)
108
+ end
109
+
110
+ # token (string): access token
111
+ # id (string): The Id of the contact to retrieve
112
+ # fields (array): An array of field names to include in results
113
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
114
+ def get_contact_by_id(token, id, fields = nil, user = nil)
115
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Contacts/" << id
116
+ request_params = nil
117
+
118
+ if not fields.nil?
119
+ request_params = { '$select' => fields.join(',') }
120
+ end
121
+
122
+ get_contact_response = make_api_call "GET", request_url, token, request_params
123
+
124
+ return JSON.parse(get_contact_response)
125
+ end
126
+
127
+ # token (string): access token
128
+ # payload (hash): a JSON hash representing the contact entity
129
+ # folder_id (string): The Id of the contact folder to create the contact in.
130
+ # If nil, contact is created in the default contacts folder.
131
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
132
+ def create_contact(token, payload, folder_id = nil, user = nil)
133
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user))
134
+ if not folder_id.nil?
135
+ request_url << "/ContactFolders/" << folder_id
136
+ end
137
+ request_url << "/Contacts"
138
+
139
+ create_contact_response = make_api_call "POST", request_url, token, nil, payload
140
+
141
+ return JSON.parse(create_contact_response)
142
+ end
143
+
144
+ # token (string): access token
145
+ # payload (hash): a JSON hash representing the updated contact fields
146
+ # id (string): The Id of the contact to update.
147
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
148
+ def update_contact(token, payload, id, user = nil)
149
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Contacts/" << id
150
+
151
+ update_contact_response = make_api_call "PATCH", request_url, token, nil, payload
152
+
153
+ return JSON.parse(update_contact_response)
154
+ end
155
+
156
+ # token (string): access token
157
+ # id (string): The Id of the contact to delete.
158
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
159
+ def delete_contact(token, id, user = nil)
160
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Contacts/" << id
161
+
162
+ delete_response = make_api_call "DELETE", request_url, token
163
+
164
+ if not delete_response.nil? and not delete_response.empty?
165
+ return JSON.parse(delete_response)
166
+ else
167
+ return nil
168
+ end
169
+ end
170
+
171
+ #----- End Contacts API -----#
172
+
173
+ #----- Begin Mail API -----#
174
+
175
+ # token (string): access token
176
+ # view_size (int): maximum number of results
177
+ # page (int): What page to fetch (multiple of view size)
178
+ # fields (array): An array of field names to include in results
179
+ # sort (hash): { sort_on => field_to_sort_on, sort_order => 'ASC' | 'DESC' }
180
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
181
+ def get_messages(token, view_size, page, fields = nil, sort = nil, user = nil)
182
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Messages"
183
+ request_params = {
184
+ '$top' => view_size,
185
+ '$skip' => (page - 1) * view_size
186
+ }
187
+
188
+ if not fields.nil?
189
+ request_params['$select'] = fields.join(',')
190
+ end
191
+
192
+ if not sort.nil?
193
+ request_params['$orderby'] = sort[:sort_field] + " " + sort[:sort_order]
194
+ end
195
+
196
+ get_messages_response = make_api_call "GET", request_url, token, request_params
197
+
198
+ return JSON.parse(get_messages_response)
199
+ end
200
+
201
+ # token (string): access token
202
+ # id (string): The Id of the message to retrieve
203
+ # fields (array): An array of field names to include in results
204
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
205
+ def get_message_by_id(token, id, fields = nil, user = nil)
206
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Messages/" << id
207
+ request_params = nil
208
+
209
+ if not fields.nil?
210
+ request_params = { '$select' => fields.join(',') }
211
+ end
212
+
213
+ get_message_response = make_api_call "GET", request_url, token, request_params
214
+
215
+ return JSON.parse(get_message_response)
216
+ end
217
+
218
+ # token (string): access token
219
+ # payload (hash): a JSON hash representing the contact entity
220
+ # folder_id (string): The Id of the folder to create the message in.
221
+ # If nil, message is created in the default drafts folder.
222
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
223
+ def create_message(token, payload, folder_id = nil, user = nil)
224
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user))
225
+ if not folder_id.nil?
226
+ request_url << "/Folders/" << folder_id
227
+ end
228
+ request_url << "/Messages"
229
+
230
+ create_message_response = make_api_call "POST", request_url, token, nil, payload
231
+
232
+ return JSON.parse(create_message_response)
233
+ end
234
+
235
+ # token (string): access token
236
+ # payload (hash): a JSON hash representing the updated message fields
237
+ # id (string): The Id of the message to update.
238
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
239
+ def update_message(token, payload, id, user = nil)
240
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Messages/" << id
241
+
242
+ update_message_response = make_api_call "PATCH", request_url, token, nil, payload
243
+
244
+ return JSON.parse(update_message_response)
245
+ end
246
+
247
+ # token (string): access token
248
+ # id (string): The Id of the message to delete.
249
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
250
+ def delete_message(token, id, user = nil)
251
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Messages/" << id
252
+
253
+ delete_response = make_api_call "DELETE", request_url, token
254
+
255
+ if not delete_response.nil? and not delete_response.empty?
256
+ return JSON.parse(delete_response)
257
+ else
258
+ return nil
259
+ end
260
+ end
261
+
262
+ # token (string): access token
263
+ # payload (hash): a JSON hash representing the message to send
264
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
265
+ def send_message(token, payload, save_to_sentitems = true, user = nil)
266
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/SendMail"
267
+
268
+ # Wrap message in the sendmail JSON structure
269
+ send_mail_json = {
270
+ 'Message' => payload,
271
+ 'SaveToSentItems' => save_to_sentitems
272
+ }
273
+
274
+ send_response = make_api_call "POST", request_url, token, nil, send_mail_json
275
+
276
+ if not send_response.nil? and not send_response.empty?
277
+ return JSON.parse(send_response)
278
+ else
279
+ return nil
280
+ end
281
+ end
282
+
283
+ #----- End Mail API -----#
284
+
285
+ #----- Begin Calendar API -----#
286
+
287
+ # token (string): access token
288
+ # view_size (int): maximum number of results
289
+ # page (int): What page to fetch (multiple of view size)
290
+ # fields (array): An array of field names to include in results
291
+ # sort (hash): { sort_on => field_to_sort_on, sort_order => 'ASC' | 'DESC' }
292
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
293
+ def get_events(token, view_size, page, fields = nil, sort = nil, user = nil)
294
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Events"
295
+ request_params = {
296
+ '$top' => view_size,
297
+ '$skip' => (page - 1) * view_size
298
+ }
299
+
300
+ if not fields.nil?
301
+ request_params['$select'] = fields.join(',')
302
+ end
303
+
304
+ if not sort.nil?
305
+ request_params['$orderby'] = sort[:sort_field] + " " + sort[:sort_order]
306
+ end
307
+
308
+ get_events_response = make_api_call "GET", request_url, token, request_params
309
+
310
+ return JSON.parse(get_events_response)
311
+ end
312
+
313
+ # token (string): access token
314
+ # id (string): The Id of the event to retrieve
315
+ # fields (array): An array of field names to include in results
316
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
317
+ def get_event_by_id(token, id, fields = nil, user = nil)
318
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Events/" << id
319
+ request_params = nil
320
+
321
+ if not fields.nil?
322
+ request_params = { '$select' => fields.join(',') }
323
+ end
324
+
325
+ get_event_response = make_api_call "GET", request_url, token, request_params
326
+
327
+ return JSON.parse(get_event_response)
328
+ end
329
+
330
+ # token (string): access token
331
+ # window_start (DateTime): The earliest time (UTC) to include in the view
332
+ # window_end (DateTime): The latest time (UTC) to include in the view
333
+ # id (string): The Id of the calendar to view
334
+ # If nil, the default calendar is used
335
+ # fields (array): An array of field names to include in results
336
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
337
+ def get_calendar_view(token, window_start, window_end, id = nil, fields = nil, user = nil)
338
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user))
339
+
340
+ if not id.nil?
341
+ request_url << "/Calendars/" << id
342
+ end
343
+
344
+ request_url << "/CalendarView"
345
+
346
+ request_params = {
347
+ 'startDateTime' => window_start.strftime('%Y-%m-%dT00:00:00Z'),
348
+ 'endDateTime' => window_end.strftime('%Y-%m-%dT00:00:00Z')
349
+ }
350
+
351
+ if not fields.nil?
352
+ request_params['$select'] = fields.join(',')
353
+ end
354
+
355
+ get_view_response =make_api_call "GET", request_url, token, request_params
356
+
357
+ return JSON.parse(get_view_response)
358
+ end
359
+
360
+ # token (string): access token
361
+ # payload (hash): a JSON hash representing the event entity
362
+ # folder_id (string): The Id of the calendar folder to create the event in.
363
+ # If nil, event is created in the default calendar folder.
364
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
365
+ def create_event(token, payload, folder_id = nil, user = nil)
366
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user))
367
+ if not folder_id.nil?
368
+ request_url << "/Calendars/" << folder_id
369
+ end
370
+ request_url << "/Events"
371
+
372
+ create_event_response = make_api_call "POST", request_url, token, nil, payload
373
+
374
+ return JSON.parse(create_event_response)
375
+ end
376
+
377
+ # token (string): access token
378
+ # payload (hash): a JSON hash representing the updated event fields
379
+ # id (string): The Id of the event to update.
380
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
381
+ def update_event(token, payload, id, user = nil)
382
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Events/" << id
383
+
384
+ update_event_response = make_api_call "PATCH", request_url, token, nil, payload
385
+
386
+ return JSON.parse(update_event_response)
387
+ end
388
+
389
+ # token (string): access token
390
+ # id (string): The Id of the event to delete.
391
+ # user (string): The user to make the call for. If nil, use the 'Me' constant.
392
+ def delete_event(token, id, user = nil)
393
+ request_url = "/api/v1.0/" << (user.nil? ? "Me" : ("users/" << user)) << "/Events/" << id
394
+
395
+ delete_response = make_api_call "DELETE", request_url, token
396
+
397
+ if not delete_response.nil? and not delete_response.empty?
398
+ return JSON.parse(delete_response)
399
+ else
400
+ return nil
401
+ end
402
+ end
403
+
404
+ #----- End Calendar API -----#
405
+
406
+ private
407
+ def initialize
408
+ @user_agent = "RubyOutlookGem/" << RubyOutlook::VERSION
409
+ @api_host = "https://outlook.office365.com"
410
+ @enable_fiddler = false
411
+ super
412
+ end
413
+ end
414
+ end
@@ -0,0 +1,3 @@
1
+ module RubyOutlook
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,270 @@
1
+ require './ruby_outlook'
2
+ require 'json'
3
+
4
+ # TODO: Copy a valid, non-expired access token here.
5
+ access_token = 'eyJ0eXAiOiJKV1QiLCJhbGciO...'
6
+
7
+ def do_contact_api_tests(token)
8
+ # TODO: Copy a valid ID for a contact here
9
+ contact_id = 'AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOABGAAAAAAC_IsPnAGUWR4fYhDeYtiNFBwCDgDrpyW-uTL4a3VuSIF6OAAAAAAEOAACDgDrpyW-uTL4a3VuSIF6OAAAZHKwnAAA='
10
+
11
+ new_contact_payload = '{
12
+ "GivenName": "Pavel",
13
+ "Surname": "Bansky",
14
+ "EmailAddresses": [
15
+ {
16
+ "Address": "pavelb@a830edad9050849NDA1.onmicrosoft.com",
17
+ "Name": "Pavel Bansky"
18
+ }
19
+ ],
20
+ "BusinessPhones": [
21
+ "+1 732 555 0102"
22
+ ]
23
+ }'
24
+
25
+ update_contact_payload = '{
26
+ "HomeAddress": {
27
+ "Street": "Some street",
28
+ "City": "Seattle",
29
+ "State": "WA",
30
+ "PostalCode": "98121"
31
+ },
32
+ "Birthday": "1974-07-22"
33
+ }'
34
+
35
+ outlook_client = RubyOutlook::Client.new
36
+
37
+ # Maximum 30 results per page.
38
+ view_size = 30
39
+ # Set the page from the query parameter.
40
+ page = 1
41
+ # Only retrieve display name.
42
+ fields = [
43
+ "DisplayName"
44
+ ]
45
+ # Sort by display name
46
+ sort = { :sort_field => 'DisplayName', :sort_order => 'ASC' }
47
+
48
+ puts 'Testing GET /me/contacts'
49
+ contacts = outlook_client.get_contacts token,
50
+ view_size, page, fields, sort
51
+
52
+ puts contacts
53
+ puts ""
54
+
55
+ puts 'Testing GET /me/contacts/id'
56
+ contact = outlook_client.get_contact_by_id token, contact_id
57
+
58
+ puts contact
59
+ puts ""
60
+
61
+ puts 'Testing POST /me/contacts'
62
+ new_contact_json = JSON.parse(new_contact_payload)
63
+ new_contact = outlook_client.create_contact token, new_contact_json
64
+
65
+ puts new_contact
66
+ puts ""
67
+
68
+ puts 'Testing PATCH /me/contacts/id'
69
+ update_contact_json = JSON.parse(update_contact_payload)
70
+ updated_contact = outlook_client.update_contact token, update_contact_json, new_contact['Id']
71
+
72
+ puts updated_contact
73
+ puts ""
74
+
75
+ puts 'Testing DELETE /me/contacts/id'
76
+ delete_response = outlook_client.delete_contact token, new_contact['Id']
77
+
78
+ puts delete_response.nil? ? "SUCCESS" : delete_response
79
+ puts ""
80
+ end
81
+
82
+ def do_mail_api_tests(token)
83
+ # TODO: Copy a valid ID for a message here
84
+ message_id = 'AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOABGAAAAAAC_IsPnAGUWR4fYhDeYtiNFBwCDgDrpyW-uTL4a3VuSIF6OAAAAAAEMAACDgDrpyW-uTL4a3VuSIF6OAAAZHKJNAAA='
85
+
86
+ new_message_payload = '{
87
+ "Subject": "Did you see last night\'s game?",
88
+ "Importance": "Low",
89
+ "Body": {
90
+ "ContentType": "HTML",
91
+ "Content": "They were <b>awesome</b>!"
92
+ },
93
+ "ToRecipients": [
94
+ {
95
+ "EmailAddress": {
96
+ "Address": "katiej@a830edad9050849NDA1.onmicrosoft.com"
97
+ }
98
+ }
99
+ ]
100
+ }'
101
+
102
+ update_message_payload = '{
103
+ "Subject": "UPDATED"
104
+ }'
105
+
106
+ send_message_payload = '{
107
+ "Subject": "Meet for lunch?",
108
+ "Body": {
109
+ "ContentType": "Text",
110
+ "Content": "The new cafeteria is open."
111
+ },
112
+ "ToRecipients": [
113
+ {
114
+ "EmailAddress": {
115
+ "Address": "allieb@contoso.com"
116
+ }
117
+ }
118
+ ],
119
+ "Attachments": [
120
+ {
121
+ "@odata.type": "#Microsoft.OutlookServices.FileAttachment",
122
+ "Name": "menu.txt",
123
+ "ContentBytes": "bWFjIGFuZCBjaGVlc2UgdG9kYXk="
124
+ }
125
+ ]
126
+ }'
127
+
128
+ outlook_client = RubyOutlook::Client.new
129
+
130
+ # Maximum 30 results per page.
131
+ view_size = 30
132
+ # Set the page from the query parameter.
133
+ page = 1
134
+ # Only retrieve display name.
135
+ fields = [
136
+ "Subject"
137
+ ]
138
+ # Sort by display name
139
+ sort = { :sort_field => 'Subject', :sort_order => 'ASC' }
140
+
141
+ puts 'Testing GET /me/messages'
142
+ messages = outlook_client.get_messages token,
143
+ view_size, page, fields, sort
144
+
145
+ puts messages
146
+ puts ""
147
+
148
+ puts 'Testing GET /me/messages/id'
149
+ message = outlook_client.get_message_by_id token, message_id
150
+
151
+ puts message
152
+ puts ""
153
+
154
+ puts 'Testing POST /me/messages'
155
+ new_message_json = JSON.parse(new_message_payload)
156
+ new_message = outlook_client.create_message token, new_message_json
157
+
158
+ puts new_message
159
+ puts ""
160
+
161
+ puts 'Testing PATCH /me/messages/id'
162
+ update_message_json = JSON.parse(update_message_payload)
163
+ updated_message = outlook_client.update_message token, update_message_json, new_message['Id']
164
+
165
+ puts updated_message
166
+ puts ""
167
+
168
+ puts 'Testing DELETE /me/messages/id'
169
+ delete_response = outlook_client.delete_message token, new_message['Id']
170
+
171
+ puts delete_response.nil? ? "SUCCESS" : delete_response
172
+ puts ""
173
+
174
+ puts 'Testing POST /me/sendmail'
175
+ send_message_json = JSON.parse(send_message_payload)
176
+ send_response = outlook_client.send_message token, send_message_json
177
+
178
+ puts send_response.nil? ? "SUCCESS" : send_response
179
+ puts ""
180
+ end
181
+
182
+ def do_calendar_api_tests(token)
183
+ # TODO: Copy a valid ID for an event here
184
+ event_id = 'AAMkADNhMjcxM2U5LWY2MmItNDRjYy05YzgwLWQwY2FmMTU1MjViOABGAAAAAAC_IsPnAGUWR4fYhDeYtiNFBwCDgDrpyW-uTL4a3VuSIF6OAAAAAAENAACDgDrpyW-uTL4a3VuSIF6OAAAXZ15oAAA='
185
+
186
+ new_event_payload = '{
187
+ "Subject": "Discuss the Calendar REST API",
188
+ "Body": {
189
+ "ContentType": "HTML",
190
+ "Content": "I think it will meet our requirements!"
191
+ },
192
+ "Start": "2014-07-02T18:00:00Z",
193
+ "End": "2014-07-02T19:00:00Z",
194
+ "Attendees": [
195
+ {
196
+ "EmailAddress": {
197
+ "Address": "janets@a830edad9050849NDA1.onmicrosoft.com",
198
+ "Name": "Janet Schorr"
199
+ },
200
+ "Type": "Required"
201
+ }
202
+ ]
203
+ }'
204
+
205
+ update_event_payload = '{
206
+ "Location": {
207
+ "DisplayName": "Your office"
208
+ }
209
+ }'
210
+
211
+ outlook_client = RubyOutlook::Client.new
212
+
213
+
214
+ puts 'Testing GET /me/CalendarView'
215
+
216
+ start_time = DateTime.parse('2015-03-03T00:00:00Z')
217
+ end_time = DateTime.parse('2015-03-10T00:00:00Z')
218
+ view = outlook_client.get_calendar_view token, start_time, end_time
219
+
220
+ puts view
221
+ puts ""
222
+
223
+ # Maximum 30 results per page.
224
+ view_size = 30
225
+ # Set the page from the query parameter.
226
+ page = 1
227
+ # Only retrieve display name.
228
+ fields = [
229
+ "Subject"
230
+ ]
231
+ # Sort by display name
232
+ sort = { :sort_field => 'Subject', :sort_order => 'ASC' }
233
+
234
+ puts 'Testing GET /me/events'
235
+ events = outlook_client.get_events token,
236
+ view_size, page, fields, sort
237
+
238
+ puts events
239
+ puts ""
240
+
241
+ puts 'Testing GET /me/events/id'
242
+ event = outlook_client.get_event_by_id token, event_id
243
+
244
+ puts event
245
+ puts ""
246
+
247
+ puts 'Testing POST /me/events'
248
+ new_event_json = JSON.parse(new_event_payload)
249
+ new_event = outlook_client.create_event token, new_event_json
250
+
251
+ puts new_event
252
+ puts ""
253
+
254
+ puts 'Testing PATCH /me/events/id'
255
+ update_event_json = JSON.parse(update_event_payload)
256
+ updated_event = outlook_client.update_event token, update_event_json, new_event['Id']
257
+
258
+ puts updated_event
259
+ puts ""
260
+
261
+ puts 'Testing DELETE /me/events/id'
262
+ delete_response = outlook_client.delete_event token, new_event['Id']
263
+
264
+ puts delete_response.nil? ? "SUCCESS" : delete_response
265
+ puts ""
266
+ end
267
+
268
+ do_contact_api_tests access_token
269
+ do_mail_api_tests access_token
270
+ do_calendar_api_tests access_token
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby_outlook/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ruby_outlook"
8
+ spec.version = RubyOutlook::VERSION
9
+ spec.authors = ["Jason Johnston"]
10
+ spec.email = ["jasonjoh@microsoft.com"]
11
+
12
+ spec.summary = %q{A ruby gem to invoke the Office 365 REST APIs.}
13
+ spec.description = %q{This ruby gem provides functions for common operations with the Office 365 Mail, Calendar, and Contacts APIs.}
14
+ spec.homepage = "https://github.com/jasonjoh/ruby_outlook"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server."
23
+ end
24
+
25
+ spec.add_dependency "faraday"
26
+ spec.add_dependency "uuidtools"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.8"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_outlook
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jason Johnston
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2015-03-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: uuidtools
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.8'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '10.0'
78
+ description: This ruby gem provides functions for common operations with the Office
79
+ 365 Mail, Calendar, and Contacts APIs.
80
+ email:
81
+ - jasonjoh@microsoft.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitattributes
87
+ - .gitignore
88
+ - .travis.yml
89
+ - Gemfile
90
+ - LICENSE.TXT
91
+ - README.md
92
+ - Rakefile
93
+ - bin/console
94
+ - bin/setup
95
+ - lib/ruby_outlook.rb
96
+ - lib/ruby_outlook/version.rb
97
+ - lib/run-tests.rb
98
+ - ruby_outlook.gemspec
99
+ homepage: https://github.com/jasonjoh/ruby_outlook
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.29
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: A ruby gem to invoke the Office 365 REST APIs.
123
+ test_files: []