viewpoint 0.0.5 → 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.
Files changed (59) hide show
  1. data/README +84 -45
  2. data/Rakefile +7 -5
  3. data/TODO +6 -0
  4. data/VERSION +1 -1
  5. data/lib/exceptions/exceptions.rb +34 -0
  6. data/lib/extensions/string.rb +37 -0
  7. data/lib/model/calendar_folder.rb +45 -0
  8. data/lib/model/calendar_item.rb +145 -0
  9. data/lib/model/contact.rb +58 -0
  10. data/lib/model/contacts_folder.rb +35 -0
  11. data/lib/model/distribution_list.rb +26 -0
  12. data/lib/model/event.rb +118 -0
  13. data/lib/model/folder.rb +36 -0
  14. data/lib/model/generic_folder.rb +302 -0
  15. data/lib/model/item.rb +126 -0
  16. data/lib/model/mailbox_user.rb +107 -0
  17. data/lib/model/meeting_cancellation.rb +28 -0
  18. data/lib/{viewpoint/errors.rb → model/meeting_message.rb} +10 -14
  19. data/lib/model/meeting_request.rb +26 -0
  20. data/lib/model/meeting_response.rb +26 -0
  21. data/lib/model/message.rb +73 -0
  22. data/lib/model/model.rb +161 -0
  23. data/lib/model/search_folder.rb +36 -0
  24. data/lib/model/task.rb +62 -0
  25. data/lib/model/task_list.rb +19 -0
  26. data/lib/model/tasks_folder.rb +33 -0
  27. data/lib/soap/handsoap/builder.rb +22 -0
  28. data/lib/soap/handsoap/builders/ews_build_helpers.rb +317 -0
  29. data/lib/soap/handsoap/builders/ews_builder.rb +86 -0
  30. data/lib/soap/handsoap/ews_service.rb +646 -0
  31. data/lib/soap/handsoap/parser.rb +106 -0
  32. data/lib/soap/handsoap/parsers/ews_parser.rb +165 -0
  33. data/lib/soap/soap_provider.rb +75 -0
  34. data/lib/viewpoint.rb +98 -3
  35. data/preamble +1 -1
  36. data/test/spec/basic_functions.spec +51 -0
  37. data/test/spec/folder_subscriptions.spec +35 -0
  38. data/test/spec/folder_synchronization.spec +28 -0
  39. data/utils/ewsWSDL2rb.rb +29 -0
  40. metadata +101 -43
  41. data/lib/exchwebserv.rb +0 -6
  42. data/lib/soap/viewpoint.conf +0 -3
  43. data/lib/viewpoint/calendar.rb +0 -128
  44. data/lib/viewpoint/calendar_item.rb +0 -118
  45. data/lib/viewpoint/event.rb +0 -0
  46. data/lib/viewpoint/exchange_headers.rb +0 -49
  47. data/lib/viewpoint/exchwebserv.rb +0 -236
  48. data/lib/viewpoint/folder.rb +0 -358
  49. data/lib/viewpoint/item.rb +0 -101
  50. data/lib/viewpoint/mail.rb +0 -117
  51. data/lib/viewpoint/message.rb +0 -132
  52. data/lib/viewpoint/task.rb +0 -0
  53. data/lib/viewpoint/tasks.rb +0 -0
  54. data/lib/wsdl/defaultMappingRegistry.rb +0 -10680
  55. data/lib/wsdl/exchangeServiceBinding.rb +0 -349
  56. data/lib/wsdl/exchangeServiceTypes.rb +0 -11013
  57. data/test/spec/basic_features_spec.rb +0 -37
  58. data/test/test_client.rb +0 -13
  59. data/test/testrestrict.rb +0 -75
@@ -0,0 +1,86 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ require 'builders/ews_build_helpers.rb'
21
+ module Viewpoint
22
+ module EWS
23
+ module SOAP
24
+
25
+ # This class includes all the build helpers and also contains some root
26
+ # level methods to help code reuse. The CreateItem operation is an example
27
+ # of this because the different item types share a lot but have a few subtle
28
+ # differences.
29
+ class EwsBuilder
30
+ include EwsBuildHelpers
31
+
32
+ def initialize(node, opts, &block)
33
+ @node, @opts = node, opts
34
+ instance_eval(&block) if block_given?
35
+ end
36
+
37
+ # @see ExchangeWebService#subscribe
38
+ def pull_subscription_request!(folder_ids, event_types, timeout)
39
+ @node.add("#{NS_EWS_MESSAGES}:PullSubscriptionRequest") do |ps|
40
+ folder_ids!(ps, folder_ids, nil, "#{NS_EWS_TYPES}:FolderIds")
41
+ event_types!(ps, event_types)
42
+ ps.add("#{NS_EWS_TYPES}:Timeout", timeout)
43
+ end
44
+ end
45
+
46
+ # @param [String] type The type of items in the items array message/calendar
47
+ # @todo Fix max_changes_returned to be more flexible
48
+ def create_item!(folder_id, items, message_disposition, send_invites, type)
49
+ @node.set_attr('MessageDisposition', message_disposition) if message_disposition
50
+ @node.set_attr('SendMeetingInvitations', send_invites) if send_invites
51
+
52
+ saved_item_folder_id!(@node, folder_id) unless folder_id.nil?
53
+ items!(@node, items, type)
54
+ end
55
+
56
+ def add_delegate!(owner, delegate, permissions)
57
+ d_user = {
58
+ :user_id => {:primary_smtp_address => {:text => delegate}},
59
+ :delegate_permissions => permissions
60
+ }
61
+
62
+ mailbox!(@node, {:email_address => {:text => owner}})
63
+ delegate_users!(@node, [d_user])
64
+ end
65
+
66
+ def remove_delegate!(owner, delegate)
67
+ mailbox!(@node, {:email_address => {:text => owner}})
68
+ @node.add("#{NS_EWS_MESSAGES}:UserIds") do |uids|
69
+ user_id!(uids, {:user_id => {:primary_smtp_address => {:text => delegate}}})
70
+ end
71
+ end
72
+
73
+ # This is forthcoming in Exchange 2010. It will replace much of the Restriction
74
+ # based code.
75
+ # @param [Array] An array of query strings
76
+ # @see http://msdn.microsoft.com/en-us/library/ee693615.aspx
77
+ def query_strings!(query_strings)
78
+ query_strings.each do |qs|
79
+ @node.add("#{NS_EWS_MESSAGES}:QueryString", qs)
80
+ end
81
+ end
82
+
83
+ end # EwsBuilder
84
+ end # SOAP
85
+ end # EWS
86
+ end # Viewpoint
@@ -0,0 +1,646 @@
1
+ #############################################################################
2
+ # Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
3
+ #
4
+ #
5
+ # This file is part of Viewpoint.
6
+ #
7
+ # Viewpoint is free software: you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or (at
10
+ # your option) any later version.
11
+ #
12
+ # Viewpoint is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15
+ # Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
19
+ #############################################################################
20
+ $: << File.dirname(__FILE__)
21
+ require 'handsoap'
22
+ require 'builder'
23
+ require 'parser'
24
+
25
+
26
+ Handsoap.http_driver = :http_client
27
+
28
+ module Viewpoint
29
+ module EWS
30
+ module SOAP
31
+ class ExchangeWebService < Handsoap::Service
32
+
33
+ SOAP_ACTION_PREFIX = "http://schemas.microsoft.com/exchange/services/2006/messages"
34
+
35
+ @@raw_soap = false
36
+
37
+ def initialize()
38
+ if $DEBUG
39
+ @debug = File.new('ews_debug.out', 'w')
40
+ @debug.sync = true
41
+ end
42
+ end
43
+
44
+ def self.set_auth(user,pass)
45
+ @@user = user
46
+ @@pass = pass
47
+ end
48
+
49
+ # Turn off parsing and just return the soap response
50
+ def self.raw_soap!
51
+ @@raw_soap = true
52
+ end
53
+
54
+ # ********* Begin Hooks *********
55
+ def on_create_document(doc)
56
+ doc.alias NS_EWS_TYPES, 'http://schemas.microsoft.com/exchange/services/2006/types'
57
+ doc.alias NS_EWS_MESSAGES, 'http://schemas.microsoft.com/exchange/services/2006/messages'
58
+ header = doc.find('Header')
59
+ header.add("#{NS_EWS_TYPES}:RequestServerVersion") { |rsv| rsv.set_attr('Version','Exchange2007_SP1') }
60
+ end
61
+
62
+ # Adds knowledge of namespaces to the response object. These have to be identical to the
63
+ # URIs returned in the XML response. For example, I had some issues with the 'soap'
64
+ # namespace because my original URI did not end in a '/'
65
+ # @example
66
+ # Won't work: http://schemas.xmlsoap.org/soap/envelope
67
+ # Works: http://schemas.xmlsoap.org/soap/envelope/
68
+ def on_response_document(doc)
69
+ doc.add_namespace NS_SOAP, 'http://schemas.xmlsoap.org/soap/envelope/'
70
+ doc.add_namespace NS_EWS_TYPES, 'http://schemas.microsoft.com/exchange/services/2006/types'
71
+ doc.add_namespace NS_EWS_MESSAGES, 'http://schemas.microsoft.com/exchange/services/2006/messages'
72
+ end
73
+
74
+ def on_after_create_http_request(req)
75
+ req.set_auth @@user, @@pass
76
+ end
77
+ # ********** End Hooks **********
78
+
79
+
80
+ # Resolve ambiguous e-mail addresses and display names
81
+ # @see http://msdn.microsoft.com/en-us/library/aa565329.aspx ResolveNames
82
+ # @see http://msdn.microsoft.com/en-us/library/aa581054.aspx UnresolvedEntry
83
+ #
84
+ # @param [String] name an unresolved entry
85
+ # @param [Boolean] full_contact_data whether or not to return full contact info
86
+ # @param [Hash] opts optional parameters to this method
87
+ # @option opts [String] :search_scope where to seach for this entry, one of
88
+ # SOAP::Contacts, SOAP::ActiveDirectory, SOAP::ActiveDirectoryContacts (default),
89
+ # SOAP::ContactsActiveDirectory
90
+ # @option opts [String, FolderId] :parent_folder_id either the name of a folder or
91
+ # it's numerical ID. @see http://msdn.microsoft.com/en-us/library/aa565998.aspx
92
+ def resolve_names(name, full_contact_data = true, opts = {})
93
+ action = "#{SOAP_ACTION_PREFIX}/ResolveNames"
94
+ resp = invoke("#{NS_EWS_MESSAGES}:ResolveNames", :soap_action => action) do |root|
95
+ build!(root) do
96
+ root.set_attr('ReturnFullContactData',full_contact_data)
97
+ root.add("#{NS_EWS_MESSAGES}:UnresolvedEntry",name)
98
+ end
99
+ end
100
+ parse!(resp)
101
+ end
102
+
103
+
104
+ # Exposes the full membership of distribution lists.
105
+ # @see http://msdn.microsoft.com/en-us/library/aa494152.aspx ExpandDL
106
+ #
107
+ # @param [String] dist_email The e-mail address associated with the Distribution List
108
+ # @todo Fully support all of the ExpandDL operations. Today it just supports
109
+ # taking an e-mail address as an argument
110
+ def expand_dl(dist_email)
111
+ action = "#{SOAP_ACTION_PREFIX}/ExpandDL"
112
+ resp = invoke("#{NS_EWS_MESSAGES}:ExpandDL", :soap_action => action) do |root|
113
+ build!(root) do
114
+ mailbox!(root, {:email_address => {:text => dist_email}})
115
+ end
116
+ end
117
+ parse!(resp)
118
+ end
119
+
120
+ # Find subfolders of an identified folder
121
+ # @see http://msdn.microsoft.com/en-us/library/aa563918.aspx
122
+ #
123
+ # @param [Array] parent_folder_ids An Array of folder ids, either a
124
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
125
+ # @param [String] traversal Shallow/Deep/SoftDeleted
126
+ # @param [Hash] folder_shape defines the FolderShape node
127
+ # See: http://msdn.microsoft.com/en-us/library/aa494311.aspx
128
+ # @option folder_shape [String] :base_shape IdOnly/Default/AllProperties
129
+ # @option folder_shape :additional_properties
130
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
131
+ # @param [Hash] opts optional parameters to this method
132
+ def find_folder(parent_folder_ids = [:root], traversal = 'Shallow', folder_shape = {:base_shape => 'Default'}, opts = {})
133
+ action = "#{SOAP_ACTION_PREFIX}/FindFolder"
134
+ resp = invoke("#{NS_EWS_MESSAGES}:FindFolder", :soap_action => action) do |root|
135
+ build!(root) do
136
+ root.set_attr('Traversal', traversal)
137
+ folder_shape!(root, folder_shape)
138
+ parent_folder_ids!(root, parent_folder_ids)
139
+ end
140
+ end
141
+ parse!(resp)
142
+ end
143
+
144
+ # Identifies items that are located in a specified folder
145
+ # @see http://msdn.microsoft.com/en-us/library/aa566107.aspx
146
+ #
147
+ # @param [Array] parent_folder_ids An Array of folder ids, either a
148
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
149
+ # @param [String] traversal Shallow/Deep/SoftDeleted
150
+ # @param [Hash] item_shape defines the FolderShape node
151
+ # See: http://msdn.microsoft.com/en-us/library/aa494311.aspx
152
+ # @option item_shape [String] :base_shape IdOnly/Default/AllProperties
153
+ # @option item_shape :additional_properties
154
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
155
+ # @param [Hash] opts optional parameters to this method
156
+ # @option opts [Hash] :calendar_view Limit FindItem by a start and end date
157
+ # {:calendar_view => {:max_entries_returned => 2, :start => <DateTime Obj>, :end => <DateTime Obj>}}
158
+ def find_item(parent_folder_ids, traversal = 'Shallow', item_shape = {:base_shape => 'Default'}, opts = {})
159
+ action = "#{SOAP_ACTION_PREFIX}/FindItem"
160
+ resp = invoke("#{NS_EWS_MESSAGES}:FindItem", :soap_action => action) do |root|
161
+ build!(root) do
162
+ root.set_attr('Traversal', traversal)
163
+ item_shape!(root, item_shape)
164
+ query_strings = opts.delete(:query_string)
165
+ restriction = opts.delete(:restriction)
166
+ if(opts.has_key?(:calendar_view))
167
+ cal_view = opts[:calendar_view]
168
+ cal_view.each_pair do |k,v|
169
+ cal_view[k] = v.to_s
170
+ end
171
+ end
172
+ add_hierarchy!(root, opts, NS_EWS_MESSAGES)
173
+ #query_strings!(query_strings)
174
+ root.add("#{NS_EWS_MESSAGES}:Restriction") do |r|
175
+ add_hierarchy!(r, restriction)
176
+ end unless restriction.nil?
177
+ parent_folder_ids!(root, parent_folder_ids)
178
+ end
179
+ end
180
+ parse!(resp)
181
+ end
182
+
183
+ # Gets folders from the Exchange store
184
+ # @see http://msdn.microsoft.com/en-us/library/aa580274.aspx
185
+ #
186
+ # @param [Array] folder_ids An Array of folder ids, either a
187
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
188
+ # @param [Hash] folder_shape defines the FolderShape node
189
+ # See: http://msdn.microsoft.com/en-us/library/aa494311.aspx
190
+ # @option folder_shape [String] :base_shape IdOnly/Default/AllProperties
191
+ # @option folder_shape :additional_properties
192
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
193
+ # @param [String,nil] act_as User to act on behalf as. This user must have been
194
+ # given delegate access to this folder or else this operation will fail.
195
+ # @param [Hash] opts optional parameters to this method
196
+ def get_folder(folder_ids, folder_shape = {:base_shape => 'Default'}, act_as = nil)
197
+ action = "#{SOAP_ACTION_PREFIX}/GetFolder"
198
+ resp = invoke("#{NS_EWS_MESSAGES}:GetFolder", :soap_action => action) do |root|
199
+ build!(root) do
200
+ folder_shape!(root, folder_shape)
201
+ folder_ids!(root, folder_ids, act_as)
202
+ end
203
+ end
204
+ parse!(resp)
205
+ end
206
+
207
+ def convert_id
208
+ action = "#{SOAP_ACTION_PREFIX}/ConvertId"
209
+ resp = invoke("#{NS_EWS_MESSAGES}:ConvertId", :soap_action => action) do |convert_id|
210
+ build_convert_id!(convert_id)
211
+ end
212
+ parse_convert_id(resp)
213
+ end
214
+
215
+ # Creates folders, calendar folders, contacts folders, tasks folders, and search folders.
216
+ # @see http://msdn.microsoft.com/en-us/library/aa563574.aspx CreateFolder
217
+ #
218
+ # @param [String,Symbol] parent_folder_id either the name of a folder or it's
219
+ # numerical ID. See: http://msdn.microsoft.com/en-us/library/aa565998.aspx
220
+ # @param [Array,String] folder_name The display name for the new folder or folders
221
+ def create_folder(parent_folder_id, folder_name)
222
+ action = "#{SOAP_ACTION_PREFIX}/CreateFolder"
223
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateFolder", :soap_action => action) do |root|
224
+ build!(root) do
225
+ root.add("#{NS_EWS_MESSAGES}:ParentFolderId") do |pfid|
226
+ folder_id!(pfid, parent_folder_id)
227
+ end
228
+ folder_name = (folder_name.is_a?(Array)) ? folder_name : [folder_name]
229
+ root.add("#{NS_EWS_MESSAGES}:Folders") do |fids|
230
+ folder_name.each do |f|
231
+ add_hierarchy!(fids, {:folder => {:display_name => {:text => f}}})
232
+ end
233
+ end
234
+ end
235
+ end
236
+ parse!(resp)
237
+ end
238
+
239
+ # Deletes folders from a mailbox.
240
+ # @see http://msdn.microsoft.com/en-us/library/aa564767.aspx DeleteFolder
241
+ #
242
+ # @param [Array,String,Symbol] folder_id either the name of a folder or it's
243
+ # numerical ID. See: http://msdn.microsoft.com/en-us/library/aa565998.aspx
244
+ # @param [String,nil] delete_type Type of delete to do: HardDelete/SoftDelete/MoveToDeletedItems
245
+ def delete_folder(folder_id, delete_type = 'MoveToDeletedItems')
246
+ action = "#{SOAP_ACTION_PREFIX}/DeleteFolder"
247
+ resp = invoke("#{NS_EWS_MESSAGES}:DeleteFolder", :soap_action => action) do |root|
248
+ root.set_attr('DeleteType', delete_type)
249
+ build!(root) do
250
+ folder_id = (folder_id.is_a?(Array)) ? folder_id : [folder_id]
251
+ folder_ids!(root, folder_id)
252
+ end
253
+ end
254
+ parse!(resp)
255
+ end
256
+
257
+ def update_folder
258
+ action = "#{SOAP_ACTION_PREFIX}/UpdateFolder"
259
+ resp = invoke("#{NS_EWS_MESSAGES}:UpdateFolder", :soap_action => action) do |update_folder|
260
+ build_update_folder!(update_folder)
261
+ end
262
+ parse_update_folder(resp)
263
+ end
264
+
265
+ def move_folder
266
+ action = "#{SOAP_ACTION_PREFIX}/MoveFolder"
267
+ resp = invoke("#{NS_EWS_MESSAGES}:MoveFolder", :soap_action => action) do |move_folder|
268
+ build_move_folder!(move_folder)
269
+ end
270
+ parse_move_folder(resp)
271
+ end
272
+
273
+ def copy_folder
274
+ action = "#{SOAP_ACTION_PREFIX}/CopyFolder"
275
+ resp = invoke("#{NS_EWS_MESSAGES}:CopyFolder", :soap_action => action) do |copy_folder|
276
+ build_copy_folder!(copy_folder)
277
+ end
278
+ parse_copy_folder(resp)
279
+ end
280
+
281
+ # Used to subscribe client applications to either push or pull notifications.
282
+ # @see http://msdn.microsoft.com/en-us/library/aa566188.aspx Subscribe on MSDN
283
+ #
284
+ # @param [Array] folder_ids An Array of folder ids, either a
285
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
286
+ # @param [Array] event_types An Array of EventTypes that we should track.
287
+ # Available types are, CopiedEvent, CreatedEvent, DeletedEvent, ModifiedEvent,
288
+ # MovedEvent, NewMailEvent, FreeBusyChangedEvent
289
+ # @param [Integer] timeout The number of minutes in which the subscription
290
+ # will timeout after not receiving a get_events operation.
291
+ # @todo Decide how/if to handle the optional SubscribeToAllFolders attribute of
292
+ # the PullSubscriptionRequest element.
293
+ def subscribe(folder_ids, event_types, timeout = 10)
294
+ action = "#{SOAP_ACTION_PREFIX}/Subscribe"
295
+ resp = invoke("#{NS_EWS_MESSAGES}:Subscribe", :soap_action => action) do |root|
296
+ build!(root) do
297
+ pull_subscription_request!(folder_ids, event_types, timeout)
298
+ end
299
+ end
300
+ parse!(resp)
301
+ end
302
+
303
+ # End a pull notification subscription.
304
+ # @see http://msdn.microsoft.com/en-us/library/aa564263.aspx
305
+ #
306
+ # @param [String] subscription_id The Id of the subscription
307
+ def unsubscribe(subscription_id)
308
+ action = "#{SOAP_ACTION_PREFIX}/Unsubscribe"
309
+ resp = invoke("#{NS_EWS_MESSAGES}:Unsubscribe", :soap_action => action) do |root|
310
+ build!(root) do
311
+ subscription_id!(root, subscription_id)
312
+ end
313
+ end
314
+ parse!(resp)
315
+ end
316
+
317
+ # Used by pull subscription clients to request notifications from the Client Access server
318
+ # @see http://msdn.microsoft.com/en-us/library/aa566199.aspx GetEvents on MSDN
319
+ #
320
+ # @param [String] subscription_id Subscription identifier
321
+ # @param [String] watermark Event bookmark in the events queue
322
+ def get_events(subscription_id, watermark)
323
+ action = "#{SOAP_ACTION_PREFIX}/GetEvents"
324
+ resp = invoke("#{NS_EWS_MESSAGES}:GetEvents", :soap_action => action) do |root|
325
+ build!(root) do
326
+ subscription_id!(root, subscription_id)
327
+ watermark!(root, watermark)
328
+ end
329
+ end
330
+ parse!(resp)
331
+ end
332
+
333
+ def sync_folder_hierarchy
334
+ action = "#{SOAP_ACTION_PREFIX}/SyncFolderHierarchy"
335
+ resp = invoke("#{NS_EWS_MESSAGES}:SyncFolderHierarchy", :soap_action => action) do |sync_folder_hierarchy|
336
+ build_sync_folder_hierarchy!(sync_folder_hierarchy)
337
+ end
338
+ parse_sync_folder_hierarchy(resp)
339
+ end
340
+
341
+ # Synchronizes items between the Exchange server and the client
342
+ # @see http://msdn.microsoft.com/en-us/library/aa563967.aspx
343
+ #
344
+ # @param [String, Symbol] folder_id either a DistinguishedFolderId
345
+ # (must me a Symbol) or a FolderId (String)
346
+ # @param [String] sync_state Base-64 encoded string used to determine
347
+ # where we are in the sync process.
348
+ # @param [Integer] max_changes The amount of items to sync per call
349
+ # to SyncFolderItems
350
+ # @param [Hash] item_shape defines the ItemShape node
351
+ # See: http://msdn.microsoft.com/en-us/library/aa565261.aspx
352
+ # @option item_shape [String] :base_shape IdOnly/Default/AllProperties
353
+ # @option item_shape :additional_properties
354
+ # See: http://msdn.microsoft.com/en-us/library/aa565261.aspx
355
+ # @param [Hash] opts optional parameters to this method
356
+ def sync_folder_items(folder_id, sync_state = nil, max_changes = 256, item_shape = {:base_shape => 'Default'}, opts = {})
357
+ action = "#{SOAP_ACTION_PREFIX}/SyncFolderItems"
358
+ resp = invoke("#{NS_EWS_MESSAGES}:SyncFolderItems", :soap_action => action) do |root|
359
+ build!(root) do
360
+ item_shape!(root, item_shape)
361
+ root.add("#{NS_EWS_MESSAGES}:SyncFolderId") do |sfid|
362
+ folder_id!(sfid, folder_id)
363
+ end
364
+ sync_state!(root, sync_state) unless sync_state.nil?
365
+ root.add("#{NS_EWS_MESSAGES}:MaxChangesReturned", max_changes)
366
+ end
367
+ end
368
+ parse!(resp)
369
+ end
370
+
371
+ # Gets items from the Exchange store
372
+ # @see http://msdn.microsoft.com/en-us/library/aa565934.aspx
373
+ #
374
+ # @param [Array] item_ids An Array of item ids
375
+ # @param [Hash] item_shape defines the ItemShape node
376
+ # See: http://msdn.microsoft.com/en-us/library/aa565261.aspx
377
+ # @option item_shape [String] :base_shape ('Default') IdOnly/Default/AllProperties
378
+ # @option item_shape :additional_properties
379
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
380
+ # @param [Hash] opts optional parameters to this method
381
+ def get_item(item_ids, item_shape = {:base_shape => 'Default'})
382
+ action = "#{SOAP_ACTION_PREFIX}/GetItem"
383
+ resp = invoke("#{NS_EWS_MESSAGES}:GetItem", :soap_action => action) do |root|
384
+ build!(root) do
385
+ item_shape!(root, item_shape)
386
+ item_ids!(root, item_ids)
387
+ end
388
+ end
389
+ parse!(resp)
390
+ end
391
+
392
+ # Operation is used to create e-mail messages
393
+ # This is actually a CreateItem operation but they differ for different types
394
+ # of Exchange objects so it is named appropriately here.
395
+ # @see http://msdn.microsoft.com/en-us/library/aa566468.aspx
396
+ #
397
+ # @param [String, Symbol] folder_id The folder to save this message in. Either a
398
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
399
+ # @param [Hash, Array] items An array of item Hashes or a single item Hash. Hash
400
+ # This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
401
+ # Values should be based on values found here: http://msdn.microsoft.com/en-us/library/aa494306.aspx
402
+ # @param [String] message_disposition "SaveOnly/SendOnly/SendAndSaveCopy"
403
+ # See: http://msdn.microsoft.com/en-us/library/aa565209.aspx
404
+ def create_message_item(folder_id, items, message_disposition = 'SaveOnly')
405
+ action = "#{SOAP_ACTION_PREFIX}/CreateItem"
406
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateItem", :soap_action => action) do |node|
407
+ build!(node) do
408
+ create_item!(folder_id, items, message_disposition, send_invites=false, 'message')
409
+ end
410
+ end
411
+ parse!(resp)
412
+ end
413
+
414
+ # Operation is used to create calendar items
415
+ # @see http://msdn.microsoft.com/en-us/library/aa564690.aspx
416
+ #
417
+ # @param [String, Symbol] folder_id The folder to create this item in. Either a
418
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
419
+ # @param [Hash, Array] items An array of item Hashes or a single item Hash. Hash
420
+ # This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
421
+ # Values should be based on values found here: http://msdn.microsoft.com/en-us/library/aa564765.aspx
422
+ # @param [String] send_invites "SendToNone/SendOnlyToAll/SendToAllAndSaveCopy"
423
+ def create_calendar_item(folder_id, items, send_invites = 'SendToAllAndSaveCopy')
424
+ action = "#{SOAP_ACTION_PREFIX}/CreateItem"
425
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateItem", :soap_action => action) do |node|
426
+ build!(node) do
427
+ create_item!(folder_id, items, message_disposition=false, send_invites, 'calendar')
428
+ end
429
+ end
430
+ parse!(resp)
431
+ end
432
+
433
+ # Operation is used to create task items
434
+ # This is actually a CreateItem operation but they differ for different types
435
+ # of Exchange objects so it is named appropriately here.
436
+ # @see http://msdn.microsoft.com/en-us/library/aa563439.aspx
437
+ #
438
+ # @param [String, Symbol] folder_id The folder to save this task in. Either a
439
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
440
+ # @param [Hash, Array] items An array of item Hashes or a single item Hash. Hash
441
+ # values should be based on values found here: http://msdn.microsoft.com/en-us/library/aa494306.aspx
442
+ # This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
443
+ # @param [String] message_disposition "SaveOnly/SendOnly/SendAndSaveCopy"
444
+ # See: http://msdn.microsoft.com/en-us/library/aa565209.aspx
445
+ def create_task_item(folder_id, items, message_disposition = 'SaveOnly')
446
+ action = "#{SOAP_ACTION_PREFIX}/CreateItem"
447
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateItem", :soap_action => action) do |node|
448
+ build!(node) do
449
+ create_item!(folder_id, items, message_disposition, send_invites=false, 'task')
450
+ end
451
+ end
452
+ parse!(resp)
453
+ end
454
+
455
+ # Delete an item from a mailbox in the Exchange store
456
+ # @see http://msdn.microsoft.com/en-us/library/aa562961.aspx
457
+ # @param [Array] item_ids An Array of item ids
458
+ # @param [String] delete_type Type of deletion: "HardDelete/SoftDelete/MoveToDeletedItems"
459
+ # @param [String, nil] send_meeting_cancellations "SendToNone/SendOnlyToAll/SendToAllAndSaveCopy"
460
+ # This is only applicable to CalendarItems and should be nil otherwise, which is the default
461
+ # @param [String, nil] affected_task_occurrences "AllOccurrences/SpecifiedOccurrenceOnly"
462
+ # This is really only related to tasks and can be nil otherwise, which is the default.
463
+ def delete_item(item_ids, delete_type, send_meeting_cancellations = nil, affected_task_occurrences = nil)
464
+ action = "#{SOAP_ACTION_PREFIX}/DeleteItem"
465
+ resp = invoke("#{NS_EWS_MESSAGES}:DeleteItem", :soap_action => action) do |root|
466
+ build!(root) do
467
+ root.set_attr('DeleteType', delete_type)
468
+ root.set_attr('SendMeetingCancellations', send_meeting_cancellations) unless send_meeting_cancellations.nil?
469
+ root.set_attr('AffectedTaskOccurrences', affected_task_occurrences) unless affected_task_occurrences.nil?
470
+ item_ids!(root, item_ids)
471
+ end
472
+ end
473
+ parse!(resp)
474
+ end
475
+
476
+ def update_item
477
+ action = "#{SOAP_ACTION_PREFIX}/UpdateItem"
478
+ resp = invoke("#{NS_EWS_MESSAGES}:UpdateItem", :soap_action => action) do |update_item|
479
+ build_update_item!(update_item)
480
+ end
481
+ parse_update_item(resp)
482
+ end
483
+
484
+ def send_item
485
+ action = "#{SOAP_ACTION_PREFIX}/SendItem"
486
+ resp = invoke("#{NS_EWS_MESSAGES}:SendItem", :soap_action => action) do |send_item|
487
+ build_send_item!(send_item)
488
+ end
489
+ parse_send_item(resp)
490
+ end
491
+
492
+ def move_item
493
+ action = "#{SOAP_ACTION_PREFIX}/MoveItem"
494
+ resp = invoke("#{NS_EWS_MESSAGES}:MoveItem", :soap_action => action) do |move_item|
495
+ build_move_item!(move_item)
496
+ end
497
+ parse_move_item(resp)
498
+ end
499
+
500
+ def copy_item
501
+ action = "#{SOAP_ACTION_PREFIX}/CopyItem"
502
+ resp = invoke("#{NS_EWS_MESSAGES}:CopyItem", :soap_action => action) do |copy_item|
503
+ build_copy_item!(copy_item)
504
+ end
505
+ parse_copy_item(resp)
506
+ end
507
+
508
+ def create_attachment
509
+ action = "#{SOAP_ACTION_PREFIX}/CreateAttachment"
510
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateAttachment", :soap_action => action) do |create_attachment|
511
+ build_create_attachment!(create_attachment)
512
+ end
513
+ parse_create_attachment(resp)
514
+ end
515
+
516
+ def delete_attachment
517
+ action = "#{SOAP_ACTION_PREFIX}/DeleteAttachment"
518
+ resp = invoke("#{NS_EWS_MESSAGES}:DeleteAttachment", :soap_action => action) do |delete_attachment|
519
+ build_delete_attachment!(delete_attachment)
520
+ end
521
+ parse_delete_attachment(resp)
522
+ end
523
+
524
+ def get_attachment
525
+ action = "#{SOAP_ACTION_PREFIX}/GetAttachment"
526
+ resp = invoke("#{NS_EWS_MESSAGES}:GetAttachment", :soap_action => action) do |get_attachment|
527
+ build_get_attachment!(get_attachment)
528
+ end
529
+ parse_get_attachment(resp)
530
+ end
531
+
532
+ def create_managed_folder
533
+ action = "#{SOAP_ACTION_PREFIX}/CreateManagedFolder"
534
+ resp = invoke("#{NS_EWS_MESSAGES}:CreateManagedFolder", :soap_action => action) do |create_managed_folder|
535
+ build_create_managed_folder!(create_managed_folder)
536
+ end
537
+ parse_create_managed_folder(resp)
538
+ end
539
+
540
+ # Retrieves the delegate settings for a specific mailbox.
541
+ # @see http://msdn.microsoft.com/en-us/library/bb799735.aspx
542
+ #
543
+ # @param [String] owner The user that is delegating permissions
544
+ def get_delegate(owner)
545
+ action = "#{SOAP_ACTION_PREFIX}/GetDelegate"
546
+ resp = invoke("#{NS_EWS_MESSAGES}:GetDelegate", :soap_action => action) do |root|
547
+ root.set_attr('IncludePermissions', 'true')
548
+ build!(root) do
549
+ mailbox!(root, {:email_address => {:text => owner}})
550
+ end
551
+ end
552
+ parse!(resp)
553
+ end
554
+
555
+ # Adds one or more delegates to a principal's mailbox and sets specific access permissions.
556
+ # @see http://msdn.microsoft.com/en-us/library/bb856527.aspx
557
+ #
558
+ # @param [String] owner The user that is delegating permissions
559
+ # @param [String] delegate The user that is being given delegate permission
560
+ # @param [Hash] permissions A hash of permissions that will be delegated.
561
+ # This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
562
+ def add_delegate(owner, delegate, permissions)
563
+ action = "#{SOAP_ACTION_PREFIX}/AddDelegate"
564
+ resp = invoke("#{NS_EWS_MESSAGES}:AddDelegate", :soap_action => action) do |root|
565
+ build!(root) do
566
+ add_delegate!(owner, delegate, permissions)
567
+ end
568
+ end
569
+ parse!(resp)
570
+ end
571
+
572
+ # Removes one or more delegates from a user's mailbox.
573
+ # @see http://msdn.microsoft.com/en-us/library/bb856564.aspx
574
+ #
575
+ # @param [String] owner The user that is delegating permissions
576
+ # @param [String] delegate The user that is being given delegate permission
577
+ def remove_delegate(owner, delegate)
578
+ action = "#{SOAP_ACTION_PREFIX}/RemoveDelegate"
579
+ resp = invoke("#{NS_EWS_MESSAGES}:RemoveDelegate", :soap_action => action) do |root|
580
+ build!(root) do
581
+ remove_delegate!(owner, delegate)
582
+ end
583
+ end
584
+ parse!(resp)
585
+ end
586
+
587
+ # Updates delegate permissions on a principal's mailbox
588
+ # @see http://msdn.microsoft.com/en-us/library/bb856529.aspx
589
+ #
590
+ # @param [String] owner The user that is delegating permissions
591
+ # @param [String] delegate The user that is being given delegate permission
592
+ # @param [Hash] permissions A hash of permissions that will be delegated.
593
+ # This Hash will eventually be passed to add_hierarchy! in the builder so it is in that format.
594
+ def update_delegate(owner, delegate, permissions)
595
+ action = "#{SOAP_ACTION_PREFIX}/UpdateDelegate"
596
+ resp = invoke("#{NS_EWS_MESSAGES}:UpdateDelegate", :soap_action => action) do |root|
597
+ build!(root) do
598
+ add_delegate!(owner, delegate, permissions)
599
+ end
600
+ end
601
+ parse!(resp)
602
+ end
603
+
604
+ def get_user_availability
605
+ action = "#{SOAP_ACTION_PREFIX}/GetUserAvailability"
606
+ resp = invoke("#{NS_EWS_MESSAGES}:GetUserAvailability", :soap_action => action) do |get_user_availability|
607
+ build_get_user_availability!(get_user_availability)
608
+ end
609
+ parse_get_user_availability(resp)
610
+ end
611
+
612
+ def get_user_oof_settings
613
+ action = "#{SOAP_ACTION_PREFIX}/GetUserOofSettings"
614
+ resp = invoke("#{NS_EWS_MESSAGES}:GetUserOofSettings", :soap_action => action) do |get_user_oof_settings|
615
+ build_get_user_oof_settings!(get_user_oof_settings)
616
+ end
617
+ parse_get_user_oof_settings(resp)
618
+ end
619
+
620
+ def set_user_oof_settings
621
+ action = "#{SOAP_ACTION_PREFIX}/SetUserOofSettings"
622
+ resp = invoke("#{NS_EWS_MESSAGES}:SetUserOofSettings", :soap_action => action) do |set_user_oof_settings|
623
+ build_set_user_oof_settings!(set_user_oof_settings)
624
+ end
625
+ parse_set_user_oof_settings(resp)
626
+ end
627
+
628
+
629
+
630
+ # Private Methods (Builders and Parsers)
631
+ private
632
+
633
+
634
+ def build!(node, opts = {}, &block)
635
+ EwsBuilder.new(node, opts, &block)
636
+ end
637
+
638
+ def parse!(response, opts = {})
639
+ return response if @@raw_soap
640
+ EwsParser.new(response).parse(opts)
641
+ end
642
+
643
+ end # class ExchangeWebService
644
+ end # module SOAP
645
+ end # EWS
646
+ end # Viewpoint