viewpoint2 1.3.0

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