ruby_outlook 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|