stxt-viewpoint 1.0.0.beta.3

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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.txt +1004 -0
  3. data/README.md +201 -0
  4. data/TODO +17 -0
  5. data/lib/ews/calendar_accessors.rb +46 -0
  6. data/lib/ews/connection.rb +120 -0
  7. data/lib/ews/connection_helper.rb +35 -0
  8. data/lib/ews/convert_accessors.rb +56 -0
  9. data/lib/ews/errors.rb +56 -0
  10. data/lib/ews/ews_client.rb +101 -0
  11. data/lib/ews/exceptions/exceptions.rb +61 -0
  12. data/lib/ews/folder_accessors.rb +264 -0
  13. data/lib/ews/impersonation.rb +30 -0
  14. data/lib/ews/item_accessors.rb +231 -0
  15. data/lib/ews/mailbox_accessors.rb +92 -0
  16. data/lib/ews/message_accessors.rb +93 -0
  17. data/lib/ews/push_subscription_accessors.rb +33 -0
  18. data/lib/ews/room_accessors.rb +48 -0
  19. data/lib/ews/roomlist_accessors.rb +47 -0
  20. data/lib/ews/soap/builders/ews_builder.rb +1257 -0
  21. data/lib/ews/soap/ews_response.rb +84 -0
  22. data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
  23. data/lib/ews/soap/ews_soap_free_busy_response.rb +119 -0
  24. data/lib/ews/soap/ews_soap_response.rb +103 -0
  25. data/lib/ews/soap/ews_soap_room_response.rb +53 -0
  26. data/lib/ews/soap/ews_soap_roomlist_response.rb +54 -0
  27. data/lib/ews/soap/exchange_availability.rb +61 -0
  28. data/lib/ews/soap/exchange_data_services.rb +780 -0
  29. data/lib/ews/soap/exchange_notification.rb +146 -0
  30. data/lib/ews/soap/exchange_synchronization.rb +93 -0
  31. data/lib/ews/soap/exchange_time_zones.rb +56 -0
  32. data/lib/ews/soap/exchange_user_configuration.rb +33 -0
  33. data/lib/ews/soap/exchange_web_service.rb +264 -0
  34. data/lib/ews/soap/parsers/ews_parser.rb +43 -0
  35. data/lib/ews/soap/parsers/ews_sax_document.rb +70 -0
  36. data/lib/ews/soap/response_message.rb +80 -0
  37. data/lib/ews/soap/responses/create_attachment_response_message.rb +47 -0
  38. data/lib/ews/soap/responses/create_item_response_message.rb +25 -0
  39. data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
  40. data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
  41. data/lib/ews/soap/responses/send_notification_response_message.rb +59 -0
  42. data/lib/ews/soap/responses/subscribe_response_message.rb +35 -0
  43. data/lib/ews/soap/responses/sync_folder_hierarchy_response_message.rb +36 -0
  44. data/lib/ews/soap/responses/sync_folder_items_response_message.rb +36 -0
  45. data/lib/ews/soap.rb +63 -0
  46. data/lib/ews/templates/calendar_item.rb +78 -0
  47. data/lib/ews/templates/forward_item.rb +24 -0
  48. data/lib/ews/templates/message.rb +73 -0
  49. data/lib/ews/templates/reply_to_item.rb +25 -0
  50. data/lib/ews/templates/task.rb +74 -0
  51. data/lib/ews/types/attachment.rb +77 -0
  52. data/lib/ews/types/attendee.rb +27 -0
  53. data/lib/ews/types/calendar_folder.rb +50 -0
  54. data/lib/ews/types/calendar_item.rb +122 -0
  55. data/lib/ews/types/contact.rb +7 -0
  56. data/lib/ews/types/contacts_folder.rb +8 -0
  57. data/lib/ews/types/copied_event.rb +51 -0
  58. data/lib/ews/types/created_event.rb +24 -0
  59. data/lib/ews/types/deleted_event.rb +24 -0
  60. data/lib/ews/types/distribution_list.rb +7 -0
  61. data/lib/ews/types/event.rb +62 -0
  62. data/lib/ews/types/export_items_response_message.rb +52 -0
  63. data/lib/ews/types/file_attachment.rb +65 -0
  64. data/lib/ews/types/folder.rb +60 -0
  65. data/lib/ews/types/free_busy_changed_event.rb +24 -0
  66. data/lib/ews/types/generic_folder.rb +420 -0
  67. data/lib/ews/types/item.rb +438 -0
  68. data/lib/ews/types/item_attachment.rb +84 -0
  69. data/lib/ews/types/item_field_uri_map.rb +224 -0
  70. data/lib/ews/types/mailbox_user.rb +156 -0
  71. data/lib/ews/types/meeting_cancellation.rb +7 -0
  72. data/lib/ews/types/meeting_message.rb +7 -0
  73. data/lib/ews/types/meeting_request.rb +7 -0
  74. data/lib/ews/types/meeting_response.rb +7 -0
  75. data/lib/ews/types/message.rb +7 -0
  76. data/lib/ews/types/modified_event.rb +48 -0
  77. data/lib/ews/types/moved_event.rb +51 -0
  78. data/lib/ews/types/new_mail_event.rb +24 -0
  79. data/lib/ews/types/out_of_office.rb +147 -0
  80. data/lib/ews/types/search_folder.rb +8 -0
  81. data/lib/ews/types/status_event.rb +39 -0
  82. data/lib/ews/types/task.rb +37 -0
  83. data/lib/ews/types/tasks_folder.rb +27 -0
  84. data/lib/ews/types.rb +191 -0
  85. data/lib/viewpoint/logging/config.rb +24 -0
  86. data/lib/viewpoint/logging.rb +27 -0
  87. data/lib/viewpoint/string_utils.rb +44 -0
  88. data/lib/viewpoint.rb +109 -0
  89. metadata +191 -0
@@ -0,0 +1,438 @@
1
+ module Viewpoint::EWS::Types
2
+ module Item
3
+ include Viewpoint::EWS
4
+ include Viewpoint::EWS::Types
5
+ include ItemFieldUriMap
6
+
7
+ def self.included(klass)
8
+ klass.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def init_simple_item(ews, id, change_key = nil, parent = nil)
13
+ ews_item = {item_id: {attribs: {id: id, change_key: change_key}}}
14
+ self.new ews, ews_item, parent
15
+ end
16
+ end
17
+
18
+ ITEM_KEY_PATHS = {
19
+ item_id: [:item_id, :attribs],
20
+ id: [:item_id, :attribs, :id],
21
+ change_key: [:item_id, :attribs, :change_key],
22
+ subject: [:subject, :text],
23
+ sensitivity: [:sensitivity, :text],
24
+ size: [:size, :text],
25
+ date_time_sent: [:date_time_sent, :text],
26
+ date_time_created: [:date_time_created, :text],
27
+ mime_content: [:mime_content, :text],
28
+ has_attachments?:[:has_attachments, :text],
29
+ is_associated?: [:is_associated, :text],
30
+ is_read?: [:is_read, :text],
31
+ is_draft?: [:is_draft, :text],
32
+ is_submitted?: [:is_submitted, :text],
33
+ conversation_id:[:conversation_id, :attribs, :id],
34
+ categories: [:categories, :elems],
35
+ internet_message_id:[:internet_message_id, :text],
36
+ internet_message_headers:[:internet_message_headers, :elems],
37
+ sender: [:sender, :elems, 0, :mailbox, :elems],
38
+ from: [:from, :elems, 0, :mailbox, :elems],
39
+ to_recipients: [:to_recipients, :elems],
40
+ cc_recipients: [:cc_recipients, :elems],
41
+ attachments: [:attachments, :elems],
42
+ importance: [:importance, :text],
43
+ conversation_index: [:conversation_index, :text],
44
+ conversation_topic: [:conversation_topic, :text],
45
+ body_type: [:body, :attribs, :body_type],
46
+ body: [:body, :text]
47
+ }
48
+
49
+ ITEM_KEY_TYPES = {
50
+ size: ->(str){str.to_i},
51
+ date_time_sent: ->(str){DateTime.parse(str)},
52
+ date_time_created: ->(str){DateTime.parse(str)},
53
+ has_attachments?: ->(str){str.downcase == 'true'},
54
+ is_associated?: ->(str){str.downcase == 'true'},
55
+ is_read?: ->(str){str.downcase == 'true'},
56
+ is_draft?: ->(str){str.downcase == 'true'},
57
+ is_submitted?: ->(str){str.downcase == 'true'},
58
+ categories: ->(obj){obj.collect{|s| s[:string][:text]}},
59
+ internet_message_headers: ->(obj){obj.collect{|h|
60
+ {h[:internet_message_header][:attribs][:header_name] =>
61
+ h[:internet_message_header][:text]} } },
62
+ sender: :build_mailbox_user,
63
+ from: :build_mailbox_user,
64
+ to_recipients: :build_mailbox_users,
65
+ cc_recipients: :build_mailbox_users,
66
+ attachments: :build_attachments,
67
+ }
68
+
69
+ ITEM_KEY_ALIAS = {
70
+ :read? => :is_read?,
71
+ :draft? => :is_draft?,
72
+ :submitted? => :is_submitted?,
73
+ :associated? => :is_associated?,
74
+ }
75
+
76
+ attr_reader :ews_item, :parent
77
+
78
+ # @param ews [SOAP::ExchangeWebService] the EWS reference
79
+ # @param ews_item [Hash] the EWS parsed response document
80
+ # @param parent [GenericFolder] an optional parent object
81
+ def initialize(ews, ews_item, parent = nil)
82
+ super(ews, ews_item)
83
+ @parent = parent
84
+ @body_type = false
85
+ simplify!
86
+ @new_file_attachments = []
87
+ @new_item_attachments = []
88
+ @new_inline_attachments = []
89
+ end
90
+
91
+ # Specify a body_type to fetch this item with if it hasn't already been fetched.
92
+ # @param body_type [String, Symbol, FalseClass] must be :best, :text, or
93
+ # :html. You can also set it to false to make it use the default.
94
+ def default_body_type=(body_type)
95
+ @body_type = body_type
96
+ end
97
+
98
+ def delete!(deltype = :hard, opts = {})
99
+ opts = {
100
+ :delete_type => delete_type(deltype),
101
+ :item_ids => [{:item_id => {:id => id}}]
102
+ }.merge(opts)
103
+
104
+ resp = @ews.delete_item(opts)
105
+ rmsg = resp.response_messages[0]
106
+ unless rmsg.success?
107
+ raise EwsError, "Could not delete #{self.class}. #{rmsg.response_code}: #{rmsg.message_text}"
108
+ end
109
+ true
110
+ end
111
+
112
+ def recycle!
113
+ delete! :recycle
114
+ end
115
+
116
+ def get_all_properties!
117
+ @ews_item = get_item(base_shape: 'AllProperties')
118
+ simplify!
119
+ end
120
+
121
+ # Mark an item as read or if you pass false, unread
122
+ # @param [Boolean] read mark read if true, unread if not.
123
+ def mark_read!(read = true)
124
+ resp = update_is_read_status read
125
+ end
126
+
127
+ # Move this item to a new folder
128
+ # @param [String,Symbol,GenericFolder] new_folder The new folder to move it to. This should
129
+ # be a subclass of GenericFolder, a DistinguishedFolderId (must me a Symbol) or a FolderId (String)
130
+ # @return [String] the new Id of the moved item
131
+ def move!(new_folder)
132
+ new_folder = new_folder.id if new_folder.kind_of?(GenericFolder)
133
+ move_opts = {
134
+ :to_folder_id => {:id => new_folder},
135
+ :item_ids => [{:item_id => {:id => self.id}}]
136
+ }
137
+ resp = @ews.move_item(move_opts)
138
+ rmsg = resp.response_messages[0]
139
+
140
+ if rmsg.success?
141
+ obj = rmsg.items.first
142
+ itype = obj.keys.first
143
+ obj[itype][:elems][0][:item_id][:attribs][:id]
144
+ else
145
+ raise EwsError, "Could not move item. #{resp.code}: #{resp.message}"
146
+ end
147
+ end
148
+
149
+ # Copy this item to a new folder
150
+ # @param [String,Symbol,GenericFolder] new_folder The new folder to move it to. This should
151
+ # be a subclass of GenericFolder, a DistinguishedFolderId (must me a Symbol) or a FolderId (String)
152
+ # @return [String] the new Id of the copied item
153
+ def copy(new_folder)
154
+ new_folder = new_folder.id if new_folder.kind_of?(GenericFolder)
155
+ copy_opts = {
156
+ :to_folder_id => {:id => new_folder},
157
+ :item_ids => [{:item_id => {:id => self.id}}]
158
+ }
159
+ resp = @ews.copy_item(copy_opts)
160
+ rmsg = resp.response_messages[0]
161
+
162
+ if rmsg.success?
163
+ obj = rmsg.items.first
164
+ itype = obj.keys.first
165
+ obj[itype][:elems][0][:item_id][:attribs][:id]
166
+ else
167
+ raise EwsError, "Could not copy item. #{rmsg.response_code}: #{rmsg.message_text}"
168
+ end
169
+ end
170
+
171
+ def add_file_attachment(file)
172
+ fa = OpenStruct.new
173
+ fa.name = File.basename(file.path)
174
+ fa.content = Base64.encode64(file.read)
175
+ @new_file_attachments << fa
176
+ end
177
+
178
+ def add_item_attachment(other_item, name = nil)
179
+ ia = OpenStruct.new
180
+ ia.name = (name ? name : other_item.subject)
181
+ ia.item = {id: other_item.id, change_key: other_item.change_key}
182
+ @new_item_attachments << ia
183
+ end
184
+
185
+ def add_inline_attachment(file)
186
+ fi = OpenStruct.new
187
+ fi.name = File.basename(file.path)
188
+ fi.content = Base64.encode64(file.read)
189
+ @new_inline_attachments << fi
190
+ end
191
+
192
+ def submit!
193
+ if draft?
194
+ submit_attachments!
195
+ resp = ews.send_item(item_ids: [{item_id: {id: self.id, change_key: self.change_key}}])
196
+ rm = resp.response_messages[0]
197
+ if rm.success?
198
+ true
199
+ else
200
+ raise EwsSendItemError, "#{rm.code}: #{rm.message_text}"
201
+ end
202
+ else
203
+ false
204
+ end
205
+ end
206
+
207
+ def submit_attachments!
208
+ return false unless draft? && !(@new_file_attachments.empty? && @new_item_attachments.empty? && @new_inline_attachments.empty?)
209
+
210
+ opts = {
211
+ parent_id: {id: self.id, change_key: self.change_key},
212
+ files: @new_file_attachments,
213
+ items: @new_item_attachments,
214
+ inline_files: @new_inline_attachments
215
+ }
216
+ resp = ews.create_attachment(opts)
217
+ set_change_key resp.response_messages[0].attachments[0].parent_change_key
218
+ @new_file_attachments = []
219
+ @new_item_attachments = []
220
+ @new_inline_attachments = []
221
+ end
222
+
223
+ # If you want to add to the body set #new_body_content. If you set #body
224
+ # it will override the body that is there.
225
+ # @see MessageAccessors#send_message for options
226
+ # additional options:
227
+ # :new_body_content, :new_body_type
228
+ # @example
229
+ # item.forward do |i|
230
+ # i.new_body_content = "Add this to the top"
231
+ # i.to_recipients << 'test@example.com'
232
+ # end
233
+ def forward(opts = {})
234
+ msg = Template::ForwardItem.new opts.clone
235
+ yield msg if block_given?
236
+ msg.reference_item_id = {id: self.id, change_key: self.change_key}
237
+ dispatch_create_item! msg
238
+ end
239
+
240
+ def reply_to(opts = {})
241
+ msg = Template::ReplyToItem.new opts.clone
242
+ yield msg if block_given?
243
+ msg.reference_item_id = {id: self.id, change_key: self.change_key}
244
+ dispatch_create_item! msg
245
+ end
246
+
247
+ def reply_to_all(opts = {})
248
+ msg = Template::ReplyToItem.new opts.clone
249
+ yield msg if block_given?
250
+ msg.reference_item_id = {id: self.id, change_key: self.change_key}
251
+ msg.ews_type = :reply_all_to_item
252
+ dispatch_create_item! msg
253
+ end
254
+
255
+
256
+ private
257
+
258
+ def key_paths
259
+ super.merge(ITEM_KEY_PATHS)
260
+ end
261
+
262
+ def key_types
263
+ super.merge(ITEM_KEY_TYPES)
264
+ end
265
+
266
+ def key_alias
267
+ super.merge(ITEM_KEY_ALIAS)
268
+ end
269
+
270
+ def update_is_read_status(read)
271
+ field = :is_read
272
+ opts = {item_changes:
273
+ [
274
+ { item_id: {id: id, change_key: change_key},
275
+ updates: [
276
+ {set_item_field: {field_uRI: {field_uRI: FIELD_URIS[field][:text]},
277
+ message: {sub_elements: [{field => {text: read}}]}}}
278
+ ]
279
+ }
280
+ ]
281
+ }
282
+ resp = ews.update_item({conflict_resolution: 'AutoResolve'}.merge(opts))
283
+ rmsg = resp.response_messages[0]
284
+ unless rmsg.success?
285
+ raise EwsError, "#{rmsg.response_code}: #{rmsg.message_text}"
286
+ end
287
+ true
288
+ end
289
+
290
+ def simplify!
291
+ return unless @ews_item.has_key?(:elems)
292
+ @ews_item = @ews_item[:elems].inject({}) do |o,i|
293
+ key = i.keys.first
294
+ if o.has_key?(key)
295
+ if o[key].is_a?(Array)
296
+ o[key] << i[key]
297
+ else
298
+ o[key] = [o.delete(key), i[key]]
299
+ end
300
+ else
301
+ o[key] = i[key]
302
+ end
303
+ o
304
+ end
305
+ end
306
+
307
+ # Get a specific item by its ID.
308
+ # @param [Hash] opts Misc options to control request
309
+ # @option opts [String] :base_shape IdOnly/Default/AllProperties
310
+ # @raise [EwsError] raised when the backend SOAP method returns an error.
311
+ def get_item(opts = {})
312
+ args = get_item_args(opts)
313
+ resp = ews.get_item(args)
314
+ get_item_parser(resp)
315
+ end
316
+
317
+ # Build up the arguements for #get_item
318
+ # @todo: should we really pass the ChangeKey or do we want the freshest obj?
319
+ def get_item_args(opts)
320
+ opts[:base_shape] ||= 'Default'
321
+ default_args = {
322
+ item_shape: {base_shape: opts[:base_shape]},
323
+ item_ids: [{item_id:{id: id, change_key: change_key}}]
324
+ }
325
+ default_args[:item_shape][:body_type] = @body_type if @body_type
326
+ default_args
327
+ end
328
+
329
+ def get_item_parser(resp)
330
+ rm = resp.response_messages[0]
331
+ if(rm.status == 'Success')
332
+ rm.items[0].values.first
333
+ else
334
+ raise EwsError, "Could not retrieve #{self.class}. #{rm.code}: #{rm.message_text}"
335
+ end
336
+ end
337
+
338
+ # Map a delete type to what EWS expects
339
+ # @param [Symbol] type. Must be :hard, :soft, or :recycle
340
+ def delete_type(type)
341
+ case type
342
+ when :hard then 'HardDelete'
343
+ when :soft then 'SoftDelete'
344
+ when :recycle then 'MoveToDeletedItems'
345
+ else 'MoveToDeletedItems'
346
+ end
347
+ end
348
+
349
+ def build_deleted_occurrences(occurrences)
350
+ occurrences.collect{|a| DateTime.parse a[:deleted_occurrence][:elems][0][:start][:text]}
351
+ end
352
+
353
+ def build_modified_occurrences(occurrences)
354
+ {}.tap do |h|
355
+ occurrences.collect do |a|
356
+ elems = a[:occurrence][:elems]
357
+
358
+ h[DateTime.parse(elems.find{|e| e[:original_start]}[:original_start][:text])] = {
359
+ start: elems.find{|e| e[:start]}[:start][:text],
360
+ end: elems.find{|e| e[:end]}[:end][:text]
361
+ }
362
+ end
363
+ end
364
+ end
365
+
366
+ def build_mailbox_user(mbox_ews)
367
+ MailboxUser.new(ews, mbox_ews)
368
+ end
369
+
370
+ def build_mailbox_users(users)
371
+ users.collect{|u| build_mailbox_user(u[:mailbox][:elems])}
372
+ end
373
+
374
+ def build_attendees_users(users)
375
+ users.collect do |u|
376
+ u[:attendee][:elems].collect do |a|
377
+ build_mailbox_user(a[:mailbox][:elems]) if a[:mailbox]
378
+ end
379
+ end.flatten.compact
380
+ end
381
+
382
+ def build_attachments(attachments)
383
+ attachments.collect do |att|
384
+ key = att.keys.first
385
+ class_by_name(key).new(self, att[key])
386
+ end
387
+ end
388
+
389
+ def set_change_key(ck)
390
+ p = resolve_key_path(ews_item, key_paths[:change_key][0..-2])
391
+ p[:change_key] = ck
392
+ end
393
+
394
+ # Handles the CreateItem call for Forward, ReplyTo, and ReplyAllTo
395
+ # It will handle the neccessary actions for adding attachments.
396
+ def dispatch_create_item!(msg)
397
+ if msg.has_attachments?
398
+ draft = msg.draft
399
+ msg.draft = true
400
+ resp = validate_created_item(ews.create_item(msg.to_ews))
401
+ msg.file_attachments.each do |f|
402
+ next unless f.kind_of?(File)
403
+ resp.add_file_attachment(f)
404
+ end
405
+ if draft
406
+ resp.submit_attachments!
407
+ resp
408
+ else
409
+ resp.submit!
410
+ end
411
+ else
412
+ resp = ews.create_item(msg.to_ews)
413
+ validate_created_item resp
414
+ end
415
+ end
416
+
417
+ # validate the CreateItem response.
418
+ # @return [Boolean, Item] returns true if items is empty and status is
419
+ # "Success" if items is not empty it will return the first Item since
420
+ # we are only dealing with single items here.
421
+ # @raise EwsCreateItemError on failure
422
+ def validate_created_item(response)
423
+ msg = response.response_messages[0]
424
+
425
+ if(msg.status == 'Success')
426
+ msg.items.empty? ? true : parse_created_item(msg.items.first)
427
+ else
428
+ raise EwsCreateItemError, "#{msg.code}: #{msg.message_text}"
429
+ end
430
+ end
431
+
432
+ def parse_created_item(msg)
433
+ mtype = msg.keys.first
434
+ message = class_by_name(mtype).new(ews, msg[mtype])
435
+ end
436
+
437
+ end
438
+ end
@@ -0,0 +1,84 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::EWS::Types
20
+ class ItemAttachment < Attachment
21
+
22
+ ITEM_ATTACH_KEY_PATHS = {
23
+ item: [:item],
24
+ message: [:message],
25
+ calendar_item: [:calendar_item],
26
+ contact: [:contact],
27
+ task: [:task],
28
+ meeting_message: [:meeting_message],
29
+ meeting_request: [:meeting_request],
30
+ meeting_response: [:meeting_response],
31
+ meeting_cancellation: [:meeting_cancellation]
32
+ }
33
+
34
+ ITEM_ATTACH_KEY_TYPES = {
35
+ message: :build_message,
36
+ calendar_item: :build_calendar_item,
37
+ contact: :build_contact,
38
+ task: :build_task,
39
+ meeting_message: :build_meeting_message,
40
+ meeting_request: :build_meeting_request,
41
+ meeting_response: :build_meeting_response,
42
+ meeting_cancellation: :build_meeting_cancellation
43
+ }
44
+
45
+ ITEM_ATTACH_KEY_ALIAS = { }
46
+
47
+ def get_all_properties!
48
+ resp = ews.get_attachment attachment_ids: [self.id]
49
+ @ews_item.merge!(parse_response(resp))
50
+ end
51
+
52
+ private
53
+
54
+ def self.method_missing(method, *args, &block)
55
+ if method.to_s =~ /^build_(.+)$/
56
+ class_by_name($1).new(ews, args[0])
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ def key_paths
63
+ super.merge(ITEM_ATTACH_KEY_PATHS)
64
+ end
65
+
66
+ def key_types
67
+ super.merge(ITEM_ATTACH_KEY_TYPES)
68
+ end
69
+
70
+ def key_alias
71
+ super.merge(ITEM_ATTACH_KEY_ALIAS)
72
+ end
73
+
74
+ def parse_response(resp)
75
+ if(resp.status == 'Success')
76
+ resp.response_message[:elems][:attachments][:elems][0][:item_attachment][:elems].inject(&:merge)
77
+ else
78
+ raise EwsError, "Could not retrieve #{self.class}. #{resp.code}: #{resp.message}"
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+