ruby_outlook 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitattributes +17 -0
- data/.gitignore +10 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.TXT +25 -0
- data/README.md +121 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/ruby_outlook.rb +414 -0
- data/lib/ruby_outlook/version.rb +3 -0
- data/lib/run-tests.rb +270 -0
- data/ruby_outlook.gemspec +30 -0
- metadata +123 -0
data/.gitattributes
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.TXT
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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/)
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -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
|
data/bin/setup
ADDED
data/lib/ruby_outlook.rb
ADDED
@@ -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
|
data/lib/run-tests.rb
ADDED
@@ -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: []
|