sfdcvp 0.0.1

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