viewpoint 1.0.0.beta.1 → 1.0.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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +16 -11
  3. data/lib/ews/connection.rb +15 -6
  4. data/lib/ews/convert_accessors.rb +56 -0
  5. data/lib/ews/errors.rb +56 -0
  6. data/lib/ews/ews_client.rb +33 -3
  7. data/lib/ews/exceptions/exceptions.rb +2 -0
  8. data/lib/ews/folder_accessors.rb +66 -1
  9. data/lib/ews/impersonation.rb +30 -0
  10. data/lib/ews/item_accessors.rb +77 -3
  11. data/lib/ews/mailbox_accessors.rb +6 -1
  12. data/lib/ews/message_accessors.rb +9 -2
  13. data/lib/ews/room_accessors.rb +48 -0
  14. data/lib/ews/roomlist_accessors.rb +47 -0
  15. data/lib/ews/soap.rb +1 -0
  16. data/lib/ews/soap/builders/ews_builder.rb +303 -48
  17. data/lib/ews/soap/ews_response.rb +2 -1
  18. data/lib/ews/soap/ews_soap_free_busy_response.rb +13 -3
  19. data/lib/ews/soap/ews_soap_response.rb +1 -1
  20. data/lib/ews/soap/ews_soap_room_response.rb +53 -0
  21. data/lib/ews/soap/ews_soap_roomlist_response.rb +54 -0
  22. data/lib/ews/soap/exchange_data_services.rb +49 -11
  23. data/lib/ews/soap/exchange_synchronization.rb +93 -0
  24. data/lib/ews/soap/exchange_time_zones.rb +56 -0
  25. data/lib/ews/soap/exchange_web_service.rb +36 -66
  26. data/lib/ews/soap/parsers/ews_sax_document.rb +8 -4
  27. data/lib/ews/soap/response_message.rb +3 -1
  28. data/lib/ews/soap/responses/create_attachment_response_message.rb +2 -1
  29. data/lib/ews/soap/responses/send_notification_response_message.rb +2 -1
  30. data/lib/{extensions/string.rb → ews/soap/responses/sync_folder_hierarchy_response_message.rb} +18 -17
  31. data/lib/ews/soap/responses/sync_folder_items_response_message.rb +36 -0
  32. data/lib/ews/templates/calendar_item.rb +78 -0
  33. data/lib/ews/templates/message.rb +8 -1
  34. data/lib/ews/templates/task.rb +74 -0
  35. data/lib/ews/types.rb +59 -11
  36. data/lib/ews/types/calendar_folder.rb +42 -0
  37. data/lib/ews/types/calendar_item.rb +93 -1
  38. data/lib/ews/types/export_items_response_message.rb +52 -0
  39. data/lib/ews/types/generic_folder.rb +70 -2
  40. data/lib/ews/types/item.rb +64 -4
  41. data/lib/ews/types/item_attachment.rb +41 -3
  42. data/lib/ews/types/item_field_uri_map.rb +1 -1
  43. data/lib/ews/types/task.rb +30 -0
  44. data/lib/ews/types/tasks_folder.rb +19 -0
  45. data/lib/viewpoint.rb +14 -14
  46. data/lib/viewpoint/logging.rb +27 -0
  47. data/lib/viewpoint/logging/config.rb +24 -0
  48. data/lib/viewpoint/string_utils.rb +76 -0
  49. metadata +82 -76
@@ -49,10 +49,15 @@ module Viewpoint::EWS::MailboxAccessors
49
49
  # @option opts [DateTime] :end_time
50
50
  # @option opts [Symbol] :requested_view :merged_only/:free_busy/
51
51
  # :free_busy_merged/:detailed/:detailed_merged
52
+ # @option opts [Hash] :time_zone The TimeZone data
53
+ # Example: {:bias => 'UTC offset in minutes',
54
+ # :standard_time => {:bias => 480, :time => '02:00:00',
55
+ # :day_order => 5, :month => 10, :day_of_week => 'Sunday'},
56
+ # :daylight_time => {same options as :standard_time}}
52
57
  def get_user_availability(emails, opts)
53
58
  opts = opts.clone
54
59
  args = get_user_availability_args(emails, opts)
55
- resp = ews.get_user_availability(args)
60
+ resp = ews.get_user_availability(args.merge(opts))
56
61
  get_user_availability_parser(resp)
57
62
  end
58
63
 
@@ -26,12 +26,15 @@ module Viewpoint::EWS::MessageAccessors
26
26
  # @option opts [Array] :to_recipients An array of e-mail addresses to send to
27
27
  # @option opts [Array] :cc_recipients An array of e-mail addresses to send to
28
28
  # @option opts [Array] :bcc_recipients An array of e-mail addresses to send to
29
+ # @option opts [Array] :extended_properties An array of extended properties
30
+ # [{extended_field_uri: {epros}, value: <val>}] or values: [<val>, <val>]
29
31
  # @option opts [Boolean] :draft if true it will save to the draft folder
30
32
  # without sending the message.
31
33
  # @option opts [String,Symbol,Hash] saved_item_folder_id Either a
32
34
  # FolderId(String) or a DistinguishedFolderId(Symbol). You can also pass a
33
35
  # Hash in the form: {id: <fold_id>, change_key: <change_key>}
34
- # @option opts [Array<File>] :file_attachments an Array of File objects
36
+ # @option opts [Array<File>] :file_attachments an Array of File or Tempfile objects
37
+ # @option opts [Array<File>] :inline_attachments an Array of Inline File or Tempfile objects
35
38
  # @return [Message,Boolean] Returns true if the message is sent, false if
36
39
  # nothing is returned from EWS or if draft is true it will return the
37
40
  # Message object. Finally, if something goes wrong, it raises an error
@@ -45,9 +48,13 @@ module Viewpoint::EWS::MessageAccessors
45
48
  msg.draft = true
46
49
  resp = parse_create_item(ews.create_item(msg.to_ews))
47
50
  msg.file_attachments.each do |f|
48
- next unless f.kind_of?(File)
51
+ next unless f.kind_of?(File) or f.kind_of?(Tempfile)
49
52
  resp.add_file_attachment(f)
50
53
  end
54
+ msg.inline_attachments.each do |f|
55
+ next unless f.kind_of?(File) or f.kind_of?(Tempfile)
56
+ resp.add_inline_attachment(f)
57
+ end
51
58
  if draft
52
59
  resp.submit_attachments!
53
60
  resp
@@ -0,0 +1,48 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2013 Camille Baldock <viewpoint@camillebaldock.co.uk>
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::RoomAccessors
20
+ include Viewpoint::EWS
21
+
22
+ # Gets the rooms that are available within the specified room distribution list
23
+ # @see http://msdn.microsoft.com/en-us/library/dd899415.aspx
24
+ # @param [String] roomDistributionList
25
+ def get_rooms(roomDistributionList)
26
+ resp = ews.get_rooms(roomDistributionList)
27
+ get_rooms_parser(resp)
28
+ end
29
+
30
+ def room_name( room )
31
+ room[:room][:elems][:id][:elems][0][:name][:text]
32
+ end
33
+
34
+ def room_email( room )
35
+ room[:room][:elems][:id][:elems][1][:email_address][:text]
36
+ end
37
+
38
+ private
39
+
40
+ def get_rooms_parser(resp)
41
+ if resp.success?
42
+ resp
43
+ else
44
+ raise EwsError, "GetRooms produced an error: #{resp.code}: #{resp.message}"
45
+ end
46
+ end
47
+
48
+ end # Viewpoint::EWS::RoomAccessors
@@ -0,0 +1,47 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2013 Camille Baldock <viewpoint@camillebaldock.co.uk>
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::RoomlistAccessors
20
+ include Viewpoint::EWS
21
+
22
+ # Gets the room lists that are available within the Exchange organization.
23
+ # @see http://msdn.microsoft.com/en-us/library/dd899416.aspx
24
+ def get_room_lists
25
+ resp = ews.get_room_lists
26
+ get_room_lists_parser(resp)
27
+ end
28
+
29
+ def roomlist_name( roomlist )
30
+ roomlist[:address][:elems][:name][:text]
31
+ end
32
+
33
+ def roomlist_email( roomlist )
34
+ roomlist[:address][:elems][:email_address][:text]
35
+ end
36
+
37
+ private
38
+
39
+ def get_room_lists_parser(resp)
40
+ if resp.success?
41
+ resp
42
+ else
43
+ raise EwsError, "GetRoomLists produced an error: #{resp.code}: #{resp.message}"
44
+ end
45
+ end
46
+
47
+ end # Viewpoint::EWS::RoomlistAccessors
@@ -47,6 +47,7 @@ module Viewpoint
47
47
  VERSION_2010_SP1 = 'Exchange2010_SP1'
48
48
  VERSION_2010_SP2 = 'Exchange2010_SP2'
49
49
  VERSION_2013 = 'Exchange2013'
50
+ VERSION_2013_SP1 = 'Exchange2013_SP1'
50
51
  VERSION_NONE = 'none'
51
52
 
52
53
  HARD_DELETE = 'HardDelete'
@@ -21,6 +21,8 @@ module Viewpoint::EWS::SOAP
21
21
  # know how to build themselves so each parent element can delegate creation of
22
22
  # subelements to a method of the same name with a '!' after it.
23
23
  class EwsBuilder
24
+ include Viewpoint::EWS
25
+ include Viewpoint::StringUtils
24
26
 
25
27
  attr_reader :nbuild
26
28
  def initialize
@@ -34,6 +36,7 @@ module Viewpoint::EWS::SOAP
34
36
  # @param [Hash] opts
35
37
  # @option opts [String] :server_version The version string that should get
36
38
  # set in the Header. See ExchangeWebService#initialize
39
+ # @option opts [Hash] :time_zone_context TimeZoneDefinition. Format: !{id: time_zone_identifier}
37
40
  # @example
38
41
  # xb = EwsBuilder.new
39
42
  # xb.build! do |part, b|
@@ -48,6 +51,8 @@ module Viewpoint::EWS::SOAP
48
51
  node.parent.namespace = parent_namespace(node)
49
52
  node.Header {
50
53
  set_version_header! opts[:server_version]
54
+ set_impersonation! opts[:impersonation_type], opts[:impersonation_mail]
55
+ set_time_zone_context_header! opts[:time_zone_context]
51
56
  yield(:header, self) if block_given?
52
57
  }
53
58
  node.Body {
@@ -60,7 +65,8 @@ module Viewpoint::EWS::SOAP
60
65
  # Build XML from a passed in Hash or Array in a specified format.
61
66
  # @param [Array,Hash] elems The elements to add to the Builder. They must
62
67
  # be specified like so:
63
- # {:top =>
68
+ #
69
+ # !{:top =>
64
70
  # { :xmlns => 'http://stonesthrow/soap',
65
71
  # :sub_elements => [
66
72
  # {:elem1 => {:text => 'inside'}},
@@ -87,10 +93,14 @@ module Viewpoint::EWS::SOAP
87
93
  vals = vals.first.clone
88
94
  se = vals.delete(:sub_elements)
89
95
  txt = vals.delete(:text)
96
+ xmlns_attribute = vals.delete(:xmlns_attribute)
90
97
 
91
- @nbuild.send(keys.first.to_s.camel_case, txt, vals) {|x|
98
+ node = @nbuild.send(camel_case(keys.first), txt, vals) {|x|
92
99
  build_xml!(se) if se
93
100
  }
101
+
102
+ # Set node level namespace
103
+ node.xmlns = NAMESPACES["xmlns:#{xmlns_attribute}"] if xmlns_attribute
94
104
  when 'Array'
95
105
  elems.each do |e|
96
106
  build_xml!(e)
@@ -122,6 +132,7 @@ module Viewpoint::EWS::SOAP
122
132
  @nbuild[NS_EWS_MESSAGES].ItemShape {
123
133
  @nbuild.parent.default_namespace = @default_ns
124
134
  base_shape!(item_shape[:base_shape])
135
+ mime_content!(item_shape[:include_mime_content]) if item_shape.has_key?(:include_mime_content)
125
136
  body_type!(item_shape[:body_type]) if item_shape[:body_type]
126
137
  if(item_shape[:additional_properties])
127
138
  additional_properties!(item_shape[:additional_properties])
@@ -129,10 +140,23 @@ module Viewpoint::EWS::SOAP
129
140
  }
130
141
  end
131
142
 
143
+ # Build the IndexedPageItemView element
144
+ # @see http://msdn.microsoft.com/en-us/library/exchange/aa563549(v=exchg.150).aspx
145
+ # @todo needs peer check
146
+ def indexed_page_item_view!(indexed_page_item_view)
147
+ attribs = {}
148
+ indexed_page_item_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
149
+ @nbuild[NS_EWS_MESSAGES].IndexedPageItemView(attribs)
150
+ end
151
+
132
152
  # Build the BaseShape element
133
153
  # @see http://msdn.microsoft.com/en-us/library/aa580545.aspx
134
154
  def base_shape!(base_shape)
135
- @nbuild[NS_EWS_TYPES].BaseShape(base_shape.to_s.camel_case)
155
+ @nbuild[NS_EWS_TYPES].BaseShape(camel_case(base_shape))
156
+ end
157
+
158
+ def mime_content!(include_mime_content)
159
+ @nbuild[NS_EWS_TYPES].IncludeMimeContent(include_mime_content.to_s.downcase)
136
160
  end
137
161
 
138
162
  def body_type!(body_type)
@@ -228,6 +252,18 @@ module Viewpoint::EWS::SOAP
228
252
  }
229
253
  end
230
254
 
255
+ # @see http://msdn.microsoft.com/en-us/library/ff709503(v=exchg.140).aspx
256
+ def export_item_ids!(item_ids)
257
+ ns = @nbuild.parent.name.match(/subscription/i) ? NS_EWS_TYPES : NS_EWS_MESSAGES
258
+ @nbuild[ns].ExportItems{
259
+ @nbuild.ItemIds {
260
+ item_ids.each do |iid|
261
+ dispatch_item_id!(iid)
262
+ end
263
+ }
264
+ }
265
+ end
266
+
231
267
  # @see http://msdn.microsoft.com/en-us/library/aa580744(v=EXCHG.140).aspx
232
268
  def occurrence_item_id!(id)
233
269
  @nbuild[NS_EWS_TYPES].OccurrenceItemId {|x|
@@ -310,7 +346,7 @@ module Viewpoint::EWS::SOAP
310
346
  def additional_properties!(addprops)
311
347
  @nbuild[NS_EWS_TYPES].AdditionalProperties {
312
348
  addprops.each_pair {|k,v|
313
- dispatch_field_uri!({k => v})
349
+ dispatch_field_uri!({k => v}, NS_EWS_TYPES)
314
350
  }
315
351
  }
316
352
  end
@@ -354,8 +390,8 @@ module Viewpoint::EWS::SOAP
354
390
 
355
391
  def user_oof_settings!(opts)
356
392
  nbuild[NS_EWS_TYPES].UserOofSettings {
357
- nbuild.OofState(opts[:oof_state].to_s.camel_case)
358
- nbuild.ExternalAudience(opts[:external_audience].to_s.camel_case) if opts[:external_audience]
393
+ nbuild.OofState(camel_case(opts[:oof_state]))
394
+ nbuild.ExternalAudience(camel_case(opts[:external_audience])) if opts[:external_audience]
359
395
  duration!(opts[:duration]) if opts[:duration]
360
396
  nbuild.InternalReply {
361
397
  nbuild.Message(opts[:internal_reply])
@@ -368,30 +404,30 @@ module Viewpoint::EWS::SOAP
368
404
 
369
405
  def duration!(opts)
370
406
  nbuild.Duration {
371
- nbuild.StartTime(opts[:start_time].new_offset(0).strftime('%FT%H:%M:%SZ'))
372
- nbuild.EndTime(opts[:end_time].new_offset(0).strftime('%FT%H:%M:%SZ'))
407
+ nbuild.StartTime(format_time opts[:start_time])
408
+ nbuild.EndTime(format_time opts[:end_time])
373
409
  }
374
410
  end
375
411
 
376
412
  def mailbox_data!(md)
377
413
  nbuild[NS_EWS_TYPES].MailboxData {
378
- nbuild.Email {
414
+ nbuild[NS_EWS_TYPES].Email {
379
415
  mbox = md[:email]
380
416
  name!(mbox[:name]) if mbox[:name]
381
417
  address!(mbox[:address]) if mbox[:address] # for Availability query
382
418
  routing_type!(mbox[:routing_type]) if mbox[:routing_type]
383
419
  }
384
- nbuild.AttendeeType 'Required'
420
+ nbuild[NS_EWS_TYPES].AttendeeType 'Required'
385
421
  }
386
422
  end
387
423
 
388
424
  def free_busy_view_options!(opts)
389
425
  nbuild[NS_EWS_TYPES].FreeBusyViewOptions {
390
- nbuild.TimeWindow {
391
- nbuild.StartTime(opts[:time_window][:start_time])
392
- nbuild.EndTime(opts[:time_window][:end_time])
426
+ nbuild[NS_EWS_TYPES].TimeWindow {
427
+ nbuild[NS_EWS_TYPES].StartTime(format_time opts[:time_window][:start_time])
428
+ nbuild[NS_EWS_TYPES].EndTime(format_time opts[:time_window][:end_time])
393
429
  }
394
- nbuild.RequestedView(opts[:requested_view][:requested_free_busy_view].to_s.camel_case)
430
+ nbuild[NS_EWS_TYPES].RequestedView(camel_case(opts[:requested_view][:requested_free_busy_view]))
395
431
  }
396
432
  end
397
433
 
@@ -399,25 +435,92 @@ module Viewpoint::EWS::SOAP
399
435
  end
400
436
 
401
437
  def time_zone!(zone)
438
+ zone ||= {}
439
+ zone = {
440
+ bias: zone[:bias] || 480,
441
+ standard_time: {
442
+ bias: 0,
443
+ time: "02:00:00",
444
+ day_order: 5,
445
+ month: 10,
446
+ day_of_week: 'Sunday'
447
+ }.merge(zone[:standard_time] || {}),
448
+ daylight_time: {
449
+ bias: -60,
450
+ time: "02:00:00",
451
+ day_order: 1,
452
+ month: 4,
453
+ day_of_week: 'Sunday'
454
+ }.merge(zone[:daylight_time] || {})
455
+ }
456
+
402
457
  nbuild[NS_EWS_TYPES].TimeZone {
403
- nbuild.Bias(480)
404
- nbuild.StandardTime {
405
- nbuild.Bias(0)
406
- nbuild.Time("02:00:00")
407
- nbuild.DayOrder(5)
408
- nbuild.Month(10)
409
- nbuild.DayOfWeek('Sunday')
458
+ nbuild[NS_EWS_TYPES].Bias(zone[:bias])
459
+ nbuild[NS_EWS_TYPES].StandardTime {
460
+ nbuild[NS_EWS_TYPES].Bias(zone[:standard_time][:bias])
461
+ nbuild[NS_EWS_TYPES].Time(zone[:standard_time][:time])
462
+ nbuild[NS_EWS_TYPES].DayOrder(zone[:standard_time][:day_order])
463
+ nbuild[NS_EWS_TYPES].Month(zone[:standard_time][:month])
464
+ nbuild[NS_EWS_TYPES].DayOfWeek(zone[:standard_time][:day_of_week])
410
465
  }
411
- nbuild.DaylightTime {
412
- nbuild.Bias(-60)
413
- nbuild.Time("02:00:00")
414
- nbuild.DayOrder(1)
415
- nbuild.Month(4)
416
- nbuild.DayOfWeek('Sunday')
466
+ nbuild[NS_EWS_TYPES].DaylightTime {
467
+ nbuild[NS_EWS_TYPES].Bias(zone[:daylight_time][:bias])
468
+ nbuild[NS_EWS_TYPES].Time(zone[:daylight_time][:time])
469
+ nbuild[NS_EWS_TYPES].DayOrder(zone[:daylight_time][:day_order])
470
+ nbuild[NS_EWS_TYPES].Month(zone[:daylight_time][:month])
471
+ nbuild[NS_EWS_TYPES].DayOfWeek(zone[:daylight_time][:day_of_week])
417
472
  }
418
473
  }
419
474
  end
420
475
 
476
+ # Request all known time_zones from server
477
+ def get_server_time_zones!(get_time_zone_options)
478
+ nbuild[NS_EWS_MESSAGES].GetServerTimeZones('ReturnFullTimeZoneData' => get_time_zone_options[:full]) do
479
+ if get_time_zone_options[:ids] && get_time_zone_options[:ids].any?
480
+ nbuild[NS_EWS_MESSAGES].Ids do
481
+ get_time_zone_options[:ids].each do |id|
482
+ nbuild[NS_EWS_TYPES].Id id
483
+ end
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+ # Specifies an optional time zone for the start time
490
+ # @param [Hash] attributes
491
+ # @option attributes :id [String] ID of the Microsoft well known time zone
492
+ # @option attributes :name [String] Optional name of the time zone
493
+ # @todo Implement sub elements Periods, TransitionsGroups and Transitions to override zone
494
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899524.aspx
495
+ def start_time_zone!(zone)
496
+ attributes = {}
497
+ attributes['Id'] = zone[:id] if zone[:id]
498
+ attributes['Name'] = zone[:name] if zone[:name]
499
+ nbuild[NS_EWS_TYPES].StartTimeZone(attributes)
500
+ end
501
+
502
+ # Specifies an optional time zone for the end time
503
+ # @param [Hash] attributes
504
+ # @option attributes :id [String] ID of the Microsoft well known time zone
505
+ # @option attributes :name [String] Optional name of the time zone
506
+ # @todo Implement sub elements Periods, TransitionsGroups and Transitions to override zone
507
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899434.aspx
508
+ def end_time_zone!(zone)
509
+ attributes = {}
510
+ attributes['Id'] = zone[:id] if zone[:id]
511
+ attributes['Name'] = zone[:name] if zone[:name]
512
+ nbuild[NS_EWS_TYPES].EndTimeZone(attributes)
513
+ end
514
+
515
+ # Specify a time zone
516
+ # @todo Implement subelements Periods, TransitionsGroups and Transitions to override zone
517
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899488.aspx
518
+ def time_zone_definition!(zone)
519
+ attributes = {'Id' => zone[:id]}
520
+ attributes['Name'] = zone[:name] if zone[:name]
521
+ nbuild[NS_EWS_TYPES].TimeZoneDefinition(attributes)
522
+ end
523
+
421
524
  # Build the Restriction element
422
525
  # @see http://msdn.microsoft.com/en-us/library/aa563791.aspx
423
526
  # @param [Hash] restriction a well-formatted Hash that can be fed to #build_xml!
@@ -518,17 +621,26 @@ module Viewpoint::EWS::SOAP
518
621
  }
519
622
  end
520
623
 
624
+ def ews_types_builder
625
+ nbuild[NS_EWS_TYPES]
626
+ end
627
+
521
628
  def field_uRI(expr)
522
- nbuild[NS_EWS_TYPES].FieldURI('FieldURI' => expr[:field_uRI])
629
+ value = expr.is_a?(Hash) ? (expr[:field_uRI] || expr[:field_uri]) : expr
630
+ ews_types_builder.FieldURI('FieldURI' => value)
523
631
  end
524
632
 
633
+ alias_method :field_uri, :field_uRI
634
+
525
635
  def indexed_field_uRI(expr)
526
636
  nbuild[NS_EWS_TYPES].IndexedFieldURI(
527
- 'FieldURI' => expr[:field_uRI],
637
+ 'FieldURI' => (expr[:field_uRI] || expr[:field_uri]),
528
638
  'FieldIndex' => expr[:field_index]
529
639
  )
530
640
  end
531
641
 
642
+ alias_method :indexed_field_uri, :indexed_field_uRI
643
+
532
644
  def extended_field_uRI(expr)
533
645
  nbuild[NS_EWS_TYPES].ExtendedFieldURI {
534
646
  nbuild.parent['DistinguishedPropertySetId'] = expr[:distinguished_property_set_id] if expr[:distinguished_property_set_id]
@@ -540,6 +652,32 @@ module Viewpoint::EWS::SOAP
540
652
  }
541
653
  end
542
654
 
655
+ alias_method :extended_field_uri, :extended_field_uRI
656
+
657
+ def extended_properties!(eprops)
658
+ eprops.each {|ep| extended_property!(ep)}
659
+ end
660
+
661
+ def extended_property!(eprop)
662
+ nbuild[NS_EWS_TYPES].ExtendedProperty {
663
+ key = eprop.keys.grep(/extended/i).first
664
+ dispatch_field_uri!({key => eprop[key]}, NS_EWS_TYPES)
665
+ if eprop[:values]
666
+ nbuild.Values {
667
+ eprop[:values].each do |v|
668
+ value! v
669
+ end
670
+ }
671
+ elsif eprop[:value]
672
+ value! eprop[:value]
673
+ end
674
+ }
675
+ end
676
+
677
+ def value!(val)
678
+ nbuild[NS_EWS_TYPES].Value(val)
679
+ end
680
+
543
681
  def field_uRI_or_constant(expr)
544
682
  nbuild[NS_EWS_TYPES].FieldURIOrConstant {
545
683
  type = expr.keys.first
@@ -547,6 +685,8 @@ module Viewpoint::EWS::SOAP
547
685
  }
548
686
  end
549
687
 
688
+ alias_method :field_uri_or_constant, :field_uRI_or_constant
689
+
550
690
  def constant(expr)
551
691
  nbuild[NS_EWS_TYPES].Constant('Value' => expr[:value])
552
692
  end
@@ -554,14 +694,14 @@ module Viewpoint::EWS::SOAP
554
694
  # Build the CalendarView element
555
695
  def calendar_view!(cal_view)
556
696
  attribs = {}
557
- cal_view.each_pair {|k,v| attribs[k.to_s.camel_case] = v.to_s}
697
+ cal_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
558
698
  @nbuild[NS_EWS_MESSAGES].CalendarView(attribs)
559
699
  end
560
700
 
561
701
  # Build the ContactsView element
562
702
  def contacts_view!(con_view)
563
703
  attribs = {}
564
- con_view.each_pair {|k,v| attribs[k.to_s.camel_case] = v.to_s}
704
+ con_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
565
705
  @nbuild[NS_EWS_MESSAGES].ContactsView(attribs)
566
706
  end
567
707
 
@@ -569,7 +709,7 @@ module Viewpoint::EWS::SOAP
569
709
  def event_types!(evtypes)
570
710
  @nbuild[NS_EWS_TYPES].EventTypes {
571
711
  evtypes.each do |et|
572
- @nbuild[NS_EWS_TYPES].EventType(et.to_s.camel_case)
712
+ @nbuild[NS_EWS_TYPES].EventType(camel_case(et))
573
713
  end
574
714
  }
575
715
  end
@@ -673,6 +813,9 @@ module Viewpoint::EWS::SOAP
673
813
 
674
814
  def message!(item)
675
815
  nbuild[NS_EWS_TYPES].Message {
816
+ if item[:extended_properties]
817
+ extended_properties! item.delete(:extended_properties)
818
+ end
676
819
  item.each_pair {|k,v|
677
820
  self.send("#{k}!", v)
678
821
  }
@@ -687,6 +830,14 @@ module Viewpoint::EWS::SOAP
687
830
  }
688
831
  end
689
832
 
833
+ def task!(item)
834
+ nbuild[NS_EWS_TYPES].Task {
835
+ item.each_pair {|k,v|
836
+ self.send("#{k}!", v)
837
+ }
838
+ }
839
+ end
840
+
690
841
  def forward_item!(item)
691
842
  nbuild[NS_EWS_TYPES].ForwardItem {
692
843
  item.each_pair {|k,v|
@@ -722,6 +873,10 @@ module Viewpoint::EWS::SOAP
722
873
  nbuild[NS_EWS_TYPES].Subject(sub)
723
874
  end
724
875
 
876
+ def importance!(sub)
877
+ nbuild[NS_EWS_TYPES].Importance(sub)
878
+ end
879
+
725
880
  def body!(b)
726
881
  nbuild[NS_EWS_TYPES].Body(b[:text]) {|x|
727
882
  x.parent['BodyType'] = b[:body_type] if b[:body_type]
@@ -754,6 +909,12 @@ module Viewpoint::EWS::SOAP
754
909
  }
755
910
  end
756
911
 
912
+ def from!(f)
913
+ nbuild[NS_EWS_TYPES].From {
914
+ mailbox! f
915
+ }
916
+ end
917
+
757
918
  def required_attendees!(attendees)
758
919
  nbuild[NS_EWS_TYPES].RequiredAttendees {
759
920
  attendees.each {|a| attendee!(a[:attendee])}
@@ -772,10 +933,10 @@ module Viewpoint::EWS::SOAP
772
933
  }
773
934
  end
774
935
 
936
+ # @todo support ResponseType, LastResponseTime: http://msdn.microsoft.com/en-us/library/aa580339.aspx
775
937
  def attendee!(a)
776
938
  nbuild[NS_EWS_TYPES].Attendee {
777
939
  mailbox!(a[:mailbox])
778
- #@todo support ResponseType, LastResponseTime: http://msdn.microsoft.com/en-us/library/aa580339.aspx
779
940
  }
780
941
  end
781
942
 
@@ -787,6 +948,41 @@ module Viewpoint::EWS::SOAP
787
948
  nbuild[NS_EWS_TYPES].End(et[:text])
788
949
  end
789
950
 
951
+ def start_date!(sd)
952
+ nbuild[NS_EWS_TYPES].StartDate format_time(sd[:text])
953
+ end
954
+
955
+ def due_date!(dd)
956
+ nbuild[NS_EWS_TYPES].DueDate format_time(dd[:text])
957
+ end
958
+
959
+ def location!(loc)
960
+ nbuild[NS_EWS_TYPES].Location(loc)
961
+ end
962
+
963
+ def is_all_day_event!(all_day)
964
+ nbuild[NS_EWS_TYPES].IsAllDayEvent(all_day)
965
+ end
966
+
967
+ def reminder_is_set!(reminder)
968
+ nbuild[NS_EWS_TYPES].ReminderIsSet reminder
969
+ end
970
+
971
+ def reminder_due_by!(date)
972
+ nbuild[NS_EWS_TYPES].ReminderDueBy format_time(date)
973
+ end
974
+
975
+ def reminder_minutes_before_start!(minutes)
976
+ nbuild[NS_EWS_TYPES].ReminderMinutesBeforeStart minutes
977
+ end
978
+
979
+ # @see http://msdn.microsoft.com/en-us/library/aa566143(v=exchg.150).aspx
980
+ # possible values Exchange Server 2010 = [Free, Tentative, Busy, OOF, NoData]
981
+ # Exchange Server 2013 = [Free, Tentative, Busy, OOF, WorkingElsewhere, NoData]
982
+ def legacy_free_busy_status!(state)
983
+ nbuild[NS_EWS_TYPES].LegacyFreeBusyStatus(state)
984
+ end
985
+
790
986
  # @see http://msdn.microsoft.com/en-us/library/aa565428(v=exchg.140).aspx
791
987
  def item_changes!(changes)
792
988
  nbuild.ItemChanges {
@@ -830,9 +1026,9 @@ module Viewpoint::EWS::SOAP
830
1026
  uri = upd.select {|k,v| k =~ /_uri/i}
831
1027
  raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
832
1028
  upd.delete(uri.keys.first)
833
- @nbuild.SetItemField {
834
- dispatch_field_uri!(uri)
835
- dispatch_field_item!(upd)
1029
+ @nbuild[NS_EWS_TYPES].SetItemField {
1030
+ dispatch_field_uri!(uri, NS_EWS_TYPES)
1031
+ dispatch_field_item!(upd, NS_EWS_TYPES)
836
1032
  }
837
1033
  end
838
1034
 
@@ -840,8 +1036,8 @@ module Viewpoint::EWS::SOAP
840
1036
  def delete_item_field!(upd)
841
1037
  uri = upd.select {|k,v| k =~ /_uri/i}
842
1038
  raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
843
- @nbuild.DeleteItemField {
844
- dispatch_field_uri!(uri)
1039
+ @nbuild[NS_EWS_TYPES].DeleteItemField {
1040
+ dispatch_field_uri!(uri, NS_EWS_TYPES)
845
1041
  }
846
1042
  end
847
1043
 
@@ -850,17 +1046,26 @@ module Viewpoint::EWS::SOAP
850
1046
  @nbuild.ReturnNewItemIds(retval)
851
1047
  end
852
1048
 
1049
+ def inline_attachment!(fa)
1050
+ @nbuild[NS_EWS_TYPES].FileAttachment {
1051
+ @nbuild[NS_EWS_TYPES].Name(fa.name)
1052
+ @nbuild[NS_EWS_TYPES].ContentId(fa.name)
1053
+ @nbuild[NS_EWS_TYPES].IsInline(true)
1054
+ @nbuild[NS_EWS_TYPES].Content(fa.content)
1055
+ }
1056
+ end
1057
+
853
1058
  def file_attachment!(fa)
854
1059
  @nbuild[NS_EWS_TYPES].FileAttachment {
855
- @nbuild.Name(fa.name)
856
- @nbuild.Content(fa.content)
1060
+ @nbuild[NS_EWS_TYPES].Name(fa.name)
1061
+ @nbuild[NS_EWS_TYPES].Content(fa.content)
857
1062
  }
858
1063
  end
859
1064
 
860
1065
  def item_attachment!(ia)
861
1066
  @nbuild[NS_EWS_TYPES].ItemAttachment {
862
- @nbuild.Name(ia.name)
863
- @nbuild.Item {
1067
+ @nbuild[NS_EWS_TYPES].Name(ia.name)
1068
+ @nbuild[NS_EWS_TYPES].Item {
864
1069
  item_id!(ia.item)
865
1070
  }
866
1071
  }
@@ -949,21 +1154,25 @@ module Viewpoint::EWS::SOAP
949
1154
 
950
1155
  # A helper to dispatch to a FieldURI, IndexedFieldURI, or an ExtendedFieldURI
951
1156
  # @todo Implement ExtendedFieldURI
952
- def dispatch_field_uri!(uri)
1157
+ def dispatch_field_uri!(uri, ns=NS_EWS_MESSAGES)
953
1158
  type = uri.keys.first
954
1159
  vals = uri[type].is_a?(Array) ? uri[type] : [uri[type]]
955
1160
  case type
956
1161
  when :field_uRI, :field_uri
957
1162
  vals.each do |val|
958
- nbuild.FieldURI('FieldURI' => val[:field_uRI])
1163
+ value = val.is_a?(Hash) ? val[type] : val
1164
+ nbuild[ns].FieldURI('FieldURI' => value)
959
1165
  end
960
1166
  when :indexed_field_uRI, :indexed_field_uri
961
1167
  vals.each do |val|
962
- nbuild.IndexedFieldURI('FieldURI' => val[:field_uRI], 'FieldIndex' => val[:field_index])
1168
+ nbuild[ns].IndexedFieldURI(
1169
+ 'FieldURI' => (val[:field_uRI] || val[:field_uri]),
1170
+ 'FieldIndex' => val[:field_index]
1171
+ )
963
1172
  end
964
1173
  when :extended_field_uRI, :extended_field_uri
965
1174
  vals.each do |val|
966
- nbuild.ExtendedFieldURI {
1175
+ nbuild[ns].ExtendedFieldURI {
967
1176
  nbuild.parent['DistinguishedPropertySetId'] = val[:distinguished_property_set_id] if val[:distinguished_property_set_id]
968
1177
  nbuild.parent['PropertySetId'] = val[:property_set_id] if val[:property_set_id]
969
1178
  nbuild.parent['PropertyTag'] = val[:property_tag] if val[:property_tag]
@@ -975,13 +1184,24 @@ module Viewpoint::EWS::SOAP
975
1184
  else
976
1185
  raise EwsBadArgumentError, "Bad URI type. #{type}"
977
1186
  end
978
-
979
1187
  end
980
1188
 
981
- def dispatch_field_item!(item)
1189
+ # Insert item, enforce xmlns attribute if prefix is present
1190
+ def dispatch_field_item!(item, ns_prefix = nil)
1191
+ item.values.first[:xmlns_attribute] = ns_prefix if ns_prefix
982
1192
  build_xml!(item)
983
1193
  end
984
1194
 
1195
+ def room_list!(cfg_prop)
1196
+ @nbuild[NS_EWS_MESSAGES].RoomList {
1197
+ email_address!(cfg_prop)
1198
+ }
1199
+ end
1200
+
1201
+ def room_lists!
1202
+ @nbuild[NS_EWS_MESSAGES].GetRoomLists
1203
+ end
1204
+
985
1205
 
986
1206
  private
987
1207
 
@@ -997,6 +1217,26 @@ private
997
1217
  end
998
1218
  end
999
1219
 
1220
+ def set_impersonation!(type, address)
1221
+ if type && type != ""
1222
+ nbuild[NS_EWS_TYPES].ExchangeImpersonation {
1223
+ nbuild[NS_EWS_TYPES].ConnectingSID {
1224
+ nbuild[NS_EWS_TYPES].method_missing type, address
1225
+ }
1226
+ }
1227
+ end
1228
+ end
1229
+
1230
+ # Set TimeZoneContext Header
1231
+ # @param time_zone_def [Hash] !{id: time_zone_identifier, name: time_zone_name}
1232
+ def set_time_zone_context_header!(time_zone_def)
1233
+ if time_zone_def
1234
+ nbuild[NS_EWS_TYPES].TimeZoneContext do
1235
+ time_zone_definition! time_zone_def
1236
+ end
1237
+ end
1238
+ end
1239
+
1000
1240
  # some methods need special naming so they use the '_r' suffix like 'and'
1001
1241
  def normalize_type(type)
1002
1242
  case type
@@ -1007,5 +1247,20 @@ private
1007
1247
  end
1008
1248
  end
1009
1249
 
1250
+ def format_time(time)
1251
+ case time
1252
+ when Time, Date, DateTime
1253
+ time.to_datetime.new_offset(0).iso8601
1254
+ when String
1255
+ begin
1256
+ DateTime.parse(time).new_offset(0).iso8601
1257
+ rescue ArgumentError
1258
+ raise EwsBadArgumentError, "Invalid Time argument (#{time})"
1259
+ end
1260
+ else
1261
+ raise EwsBadArgumentError, "Invalid Time argument (#{time})"
1262
+ end
1263
+ end
1264
+
1010
1265
  end # EwsBuilder
1011
1266
  end # Viewpoint::EWS::SOAP