viewpoint 0.1.27 → 1.0.0.beta.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 (93) hide show
  1. data/README.md +196 -0
  2. data/lib/ews/calendar_accessors.rb +34 -0
  3. data/lib/ews/connection.rb +117 -0
  4. data/lib/ews/connection_helper.rb +35 -0
  5. data/lib/ews/ews_client.rb +71 -0
  6. data/lib/ews/exceptions/exceptions.rb +59 -0
  7. data/lib/ews/folder_accessors.rb +199 -0
  8. data/lib/ews/item_accessors.rb +157 -0
  9. data/lib/ews/mailbox_accessors.rb +87 -0
  10. data/lib/ews/message_accessors.rb +86 -0
  11. data/lib/ews/push_subscription_accessors.rb +33 -0
  12. data/lib/ews/soap.rb +63 -0
  13. data/lib/ews/soap/builders/ews_builder.rb +1011 -0
  14. data/lib/ews/soap/ews_response.rb +83 -0
  15. data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
  16. data/lib/ews/soap/ews_soap_free_busy_response.rb +109 -0
  17. data/lib/ews/soap/ews_soap_response.rb +103 -0
  18. data/lib/ews/soap/exchange_availability.rb +61 -0
  19. data/lib/ews/soap/exchange_data_services.rb +742 -0
  20. data/lib/ews/soap/exchange_notification.rb +146 -0
  21. data/lib/ews/soap/exchange_user_configuration.rb +33 -0
  22. data/lib/ews/soap/exchange_web_service.rb +294 -0
  23. data/lib/{model/attendee.rb → ews/soap/parsers/ews_parser.rb} +20 -14
  24. data/lib/ews/soap/parsers/ews_sax_document.rb +66 -0
  25. data/lib/ews/soap/response_message.rb +78 -0
  26. data/lib/ews/soap/responses/create_attachment_response_message.rb +46 -0
  27. data/lib/{model/meeting_message.rb → ews/soap/responses/create_item_response_message.rb} +7 -10
  28. data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
  29. data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
  30. data/lib/ews/soap/responses/send_notification_response_message.rb +58 -0
  31. data/lib/{model/attachment.rb → ews/soap/responses/subscribe_response_message.rb} +17 -13
  32. data/lib/ews/templates/forward_item.rb +24 -0
  33. data/lib/ews/templates/message.rb +66 -0
  34. data/lib/ews/templates/reply_to_item.rb +25 -0
  35. data/lib/ews/types.rb +146 -0
  36. data/lib/ews/types/attachment.rb +77 -0
  37. data/lib/{model/meeting_cancellation.rb → ews/types/attendee.rb} +9 -8
  38. data/lib/ews/types/calendar_folder.rb +8 -0
  39. data/lib/ews/types/calendar_item.rb +37 -0
  40. data/lib/ews/types/contact.rb +7 -0
  41. data/lib/ews/types/contacts_folder.rb +8 -0
  42. data/lib/ews/types/copied_event.rb +51 -0
  43. data/lib/{soap/handsoap/builder.rb → ews/types/created_event.rb} +5 -2
  44. data/lib/{model/meeting_response.rb → ews/types/deleted_event.rb} +6 -6
  45. data/lib/ews/types/distribution_list.rb +7 -0
  46. data/lib/ews/types/event.rb +62 -0
  47. data/lib/ews/types/file_attachment.rb +65 -0
  48. data/lib/ews/types/folder.rb +60 -0
  49. data/lib/{model/distribution_list.rb → ews/types/free_busy_changed_event.rb} +6 -6
  50. data/lib/ews/types/generic_folder.rb +352 -0
  51. data/lib/ews/types/item.rb +381 -0
  52. data/lib/ews/types/item_attachment.rb +46 -0
  53. data/lib/{model → ews/types}/item_field_uri_map.rb +2 -2
  54. data/lib/ews/types/mailbox_user.rb +156 -0
  55. data/lib/ews/types/meeting_cancellation.rb +7 -0
  56. data/lib/ews/types/meeting_message.rb +7 -0
  57. data/lib/ews/types/meeting_request.rb +7 -0
  58. data/lib/ews/types/meeting_response.rb +7 -0
  59. data/lib/ews/types/message.rb +7 -0
  60. data/lib/ews/types/modified_event.rb +48 -0
  61. data/lib/{model/item_attachment.rb → ews/types/moved_event.rb} +33 -15
  62. data/lib/ews/types/new_mail_event.rb +24 -0
  63. data/lib/ews/types/out_of_office.rb +147 -0
  64. data/lib/ews/types/search_folder.rb +8 -0
  65. data/lib/ews/types/status_event.rb +39 -0
  66. data/lib/ews/types/task.rb +7 -0
  67. data/lib/ews/types/tasks_folder.rb +8 -0
  68. data/lib/viewpoint.rb +82 -106
  69. metadata +99 -67
  70. data/README +0 -114
  71. data/lib/exceptions/exceptions.rb +0 -46
  72. data/lib/model/calendar_folder.rb +0 -67
  73. data/lib/model/calendar_item.rb +0 -267
  74. data/lib/model/contact.rb +0 -238
  75. data/lib/model/contacts_folder.rb +0 -46
  76. data/lib/model/event.rb +0 -116
  77. data/lib/model/file_attachment.rb +0 -53
  78. data/lib/model/folder.rb +0 -47
  79. data/lib/model/generic_folder.rb +0 -471
  80. data/lib/model/item.rb +0 -313
  81. data/lib/model/mailbox_user.rb +0 -146
  82. data/lib/model/meeting_request.rb +0 -39
  83. data/lib/model/message.rb +0 -142
  84. data/lib/model/model.rb +0 -269
  85. data/lib/model/search_folder.rb +0 -48
  86. data/lib/model/task.rb +0 -121
  87. data/lib/model/tasks_folder.rb +0 -44
  88. data/lib/soap/handsoap/builders/ews_build_helpers.rb +0 -383
  89. data/lib/soap/handsoap/builders/ews_builder.rb +0 -146
  90. data/lib/soap/handsoap/ews_service.rb +0 -813
  91. data/lib/soap/handsoap/parser.rb +0 -104
  92. data/lib/soap/handsoap/parsers/ews_parser.rb +0 -246
  93. data/lib/soap/soap_provider.rb +0 -64
@@ -0,0 +1,83 @@
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::SOAP
20
+
21
+ # A Generic Class for SOAP returns.
22
+ class EwsResponse
23
+
24
+ def initialize(sax_hash)
25
+ @resp = sax_hash
26
+ simplify!
27
+ end
28
+
29
+ def envelope
30
+ @resp[:envelope][:elems]
31
+ end
32
+
33
+ def header
34
+ envelope[0][:header][:elems]
35
+ end
36
+
37
+ def body
38
+ envelope[1][:body][:elems]
39
+ end
40
+
41
+ def response
42
+ body[0]
43
+ end
44
+
45
+ def response_messages
46
+ return @response_messages if @response_messages
47
+
48
+ @response_messages = []
49
+ response_type = response.keys.first
50
+ response[response_type][:elems][0][:response_messages][:elems].each do |rm|
51
+ response_message_type = rm.keys[0]
52
+ rm_klass = class_by_name(response_message_type)
53
+ @response_messages << rm_klass.new(rm)
54
+ end
55
+ @response_messages
56
+ end
57
+
58
+
59
+ private
60
+
61
+
62
+ def simplify!
63
+ response_type = response.keys.first
64
+ response[response_type][:elems][0][:response_messages][:elems].each do |rm|
65
+ key = rm.keys.first
66
+ rm[key][:elems] = rm[key][:elems].inject(&:merge)
67
+ end
68
+ end
69
+
70
+ def class_by_name(cname)
71
+ begin
72
+ if(cname.instance_of? Symbol)
73
+ cname = cname.to_s.camel_case
74
+ end
75
+ Viewpoint::EWS::SOAP.const_get(cname)
76
+ rescue NameError => e
77
+ ResponseMessage
78
+ end
79
+ end
80
+
81
+ end # EwsSoapResponse
82
+
83
+ end # Viewpoint::EWS::SOAP
@@ -0,0 +1,58 @@
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::SOAP
20
+
21
+ # This is a speciality response class to handle the idiosynracies of
22
+ # Availability responses.
23
+ # @attr_reader [String] :message The text from the EWS element <m:ResponseCode>
24
+ class EwsSoapAvailabilityResponse < EwsSoapResponse
25
+
26
+ def response_messages
27
+ nil
28
+ end
29
+
30
+ def response
31
+ body[0][response_key]
32
+ end
33
+
34
+ def response_message
35
+ key = response.keys.first
36
+ response[key]
37
+ end
38
+
39
+ def response_code
40
+ response_message[:elems][:response_code][:text]
41
+ end
42
+ alias :code :response_code
43
+
44
+ def response_key
45
+ key = body[0].keys.first
46
+ end
47
+
48
+ private
49
+
50
+ def simplify!
51
+ key = response_key
52
+ body[0][key] = body[0][key][:elems].inject(:merge)
53
+ response_message[:elems] = response_message[:elems].inject(:merge)
54
+ end
55
+
56
+ end # EwsSoapAvailabilityResponse
57
+
58
+ end # Viewpoint::EWS::SOAP
@@ -0,0 +1,109 @@
1
+ =begin
2
+ This file is a cotribution to Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2013 Mark McCahill <mark.mccahill@duke.edu>
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::SOAP
20
+
21
+ class EwsSoapFreeBusyResponse < EwsSoapResponse
22
+
23
+ def initialize(sax_hash)
24
+ @resp = sax_hash
25
+ simplify!
26
+ end
27
+
28
+ def envelope
29
+ @resp[:envelope][:elems]
30
+ end
31
+
32
+ def header
33
+ envelope[0][:header][:elems]
34
+ end
35
+
36
+ def body
37
+ envelope[1][:body][:elems]
38
+ end
39
+
40
+ def get_user_availability_response
41
+ body.first[:get_user_availability_response][:elems].first[:free_busy_response_array][:elems].first[:free_busy_response][:elems]
42
+ end
43
+
44
+ def response
45
+ body
46
+ end
47
+
48
+ def calendar_event_array
49
+ get_user_availability_response[1][:free_busy_view][:elems][1][:calendar_event_array][:elems]
50
+ end
51
+
52
+ def working_hours
53
+ get_user_availability_response[1][:free_busy_view][:elems][2][:working_hours][:elems]
54
+ end
55
+
56
+ def response_message
57
+ get_user_availability_response.first[:response_message]
58
+ end
59
+
60
+ def response_class
61
+ response_message[:attribs][:response_class]
62
+ end
63
+ alias :status :response_class
64
+
65
+ def response_code
66
+ response_message[:elems].first[:response_code][:text]
67
+ end
68
+ alias :code :response_code
69
+
70
+ def response_message_text
71
+ guard_hash response_message[:elems], [:message_text, :text]
72
+ end
73
+ alias :message :response_message_text
74
+
75
+ def response_key
76
+ response_message[:elems]
77
+ end
78
+
79
+ def success?
80
+ response_class == "Success"
81
+ end
82
+
83
+ private
84
+
85
+ def simplify!
86
+ # key = response_key
87
+ # body[0][key] = body[0][key][:elems].inject(:merge)
88
+ # response_message[:elems] = response_message[:elems].inject(:merge)
89
+ end
90
+
91
+ # If the keys don't exist in the Hash return nil
92
+ # @param[Hash] hsh
93
+ # @param[Array<Symbol,String>] keys keys to follow in the array
94
+ # @return [Object, nil]
95
+ def guard_hash(hsh, keys)
96
+ key = keys.shift
97
+ return nil unless hsh.is_a?(Hash) && hsh.has_key?(key)
98
+
99
+ if keys.empty?
100
+ hsh[key]
101
+ else
102
+ guard_hash hsh[key], keys
103
+ end
104
+ end
105
+
106
+
107
+ end # EwsSoapFreeBusyResponse
108
+
109
+ end # Viewpoint::EWS::SOAP
@@ -0,0 +1,103 @@
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::SOAP
20
+
21
+ # A Generic Class for SOAP returns.
22
+ # @attr_reader [String] :message The text from the EWS element <m:ResponseCode>
23
+ class EwsSoapResponse
24
+
25
+ def initialize(sax_hash)
26
+ @resp = sax_hash
27
+ simplify!
28
+ end
29
+
30
+ def envelope
31
+ @resp[:envelope][:elems]
32
+ end
33
+
34
+ def header
35
+ envelope[0][:header][:elems]
36
+ end
37
+
38
+ def body
39
+ envelope[1][:body][:elems]
40
+ end
41
+
42
+ def response
43
+ body[0]
44
+ end
45
+
46
+ def response_messages
47
+ key = response.keys.first
48
+ response[key][:elems][0][:response_messages][:elems]
49
+ end
50
+
51
+ def response_message
52
+ key = response_messages[0].keys.first
53
+ response_messages[0][key]
54
+ end
55
+
56
+ def response_class
57
+ response_message[:attribs][:response_class]
58
+ end
59
+ alias :status :response_class
60
+
61
+ def response_code
62
+ response_message[:elems][:response_code][:text]
63
+ end
64
+ alias :code :response_code
65
+
66
+ def response_message_text
67
+ guard_hash response_message[:elems], [:message_text, :text]
68
+ end
69
+ alias :message :response_message_text
70
+
71
+ def success?
72
+ response_class == "Success"
73
+ end
74
+
75
+
76
+ private
77
+
78
+
79
+ def simplify!
80
+ response_messages.each do |rm|
81
+ key = rm.keys.first
82
+ rm[key][:elems] = rm[key][:elems].inject(&:merge)
83
+ end
84
+ end
85
+
86
+ # If the keys don't exist in the Hash return nil
87
+ # @param[Hash] hsh
88
+ # @param[Array<Symbol,String>] keys keys to follow in the array
89
+ # @return [Object, nil]
90
+ def guard_hash(hsh, keys)
91
+ key = keys.shift
92
+ return nil unless hsh.is_a?(Hash) && hsh.has_key?(key)
93
+
94
+ if keys.empty?
95
+ hsh[key]
96
+ else
97
+ guard_hash hsh[key], keys
98
+ end
99
+ end
100
+
101
+ end # EwsSoapResponse
102
+
103
+ end # Viewpoint::EWS::SOAP
@@ -0,0 +1,61 @@
1
+ module Viewpoint::EWS::SOAP
2
+
3
+ # Exchange Availability operations as listed in the EWS Documentation.
4
+ # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx
5
+ module ExchangeAvailability
6
+ include Viewpoint::EWS::SOAP
7
+
8
+ # -------------- Availability Operations -------------
9
+
10
+ # Gets a mailbox user's Out of Office (OOF) settings and messages.
11
+ # @see http://msdn.microsoft.com/en-us/library/aa563465.aspx
12
+ # @param [Hash] opts
13
+ # @option opts [String] :address the email address of the user
14
+ # @option opts [String] :name the user display name (optional)
15
+ # @option opts [String] :routing_type the routing protocol (optional and stupid)
16
+ def get_user_oof_settings(opts)
17
+ opts = opts.clone
18
+ [:address].each do |k|
19
+ validate_param(opts, k, true)
20
+ end
21
+ req = build_soap! do |type, builder|
22
+ if(type == :header)
23
+ else
24
+ builder.nbuild.GetUserOofSettingsRequest {|x|
25
+ x.parent.default_namespace = @default_ns
26
+ builder.mailbox!(opts)
27
+ }
28
+ end
29
+ end
30
+ do_soap_request(req, response_class: EwsSoapAvailabilityResponse)
31
+ end
32
+
33
+ # Sets a mailbox user's Out of Office (OOF) settings and message.
34
+ # @see http://msdn.microsoft.com/en-us/library/aa580294.aspx
35
+ # @param [Hash] opts
36
+ # @option opts [Hash] :mailbox the mailbox hash for the use
37
+ # @option opts [String,Symbol] :oof_state :enabled, :disabled, :scheduled
38
+ # @option opts [Hash] :duration {start_time: DateTime, end_time: DateTime}
39
+ # @option opts [String] :internal_reply
40
+ # @option opts [String] :external_reply
41
+ # @option opts [String,Symbol] :external_audience :none, :known, :all
42
+ def set_user_oof_settings(opts)
43
+ opts = opts.clone
44
+ [:mailbox, :oof_state].each do |k|
45
+ validate_param(opts, k, true)
46
+ end
47
+ req = build_soap! do |type, builder|
48
+ if(type == :header)
49
+ else
50
+ builder.nbuild.SetUserOofSettingsRequest {|x|
51
+ x.parent.default_namespace = @default_ns
52
+ builder.mailbox! opts.delete(:mailbox)
53
+ builder.user_oof_settings!(opts)
54
+ }
55
+ end
56
+ end
57
+ do_soap_request(req, response_class: EwsSoapAvailabilityResponse)
58
+ end
59
+
60
+ end #ExchangeAvailability
61
+ end
@@ -0,0 +1,742 @@
1
+ module Viewpoint::EWS::SOAP
2
+
3
+ # Exchange Data Service operations as listed in the EWS Documentation.
4
+ # @see http://msdn.microsoft.com/en-us/library/bb409286.aspx
5
+ module ExchangeDataServices
6
+ include Viewpoint::EWS::SOAP
7
+
8
+ # -------------- Item Operations -------------
9
+
10
+ # Identifies items that are located in a specified folder
11
+ # @see http://msdn.microsoft.com/en-us/library/aa566107.aspx
12
+ #
13
+ # @param [Hash] opts
14
+ # @option opts [Array<Hash>] :parent_folder_ids An Array of folder id Hashes, either a
15
+ # DistinguishedFolderId (must me a Symbol) or a FolderId (String)
16
+ # [{:id => <myid>, :change_key => <ck>}, {:id => :root}]
17
+ # @option opts [String] :traversal Shallow/Deep/SoftDeleted
18
+ # @option opts [Hash] :item_shape defines the ItemShape node
19
+ # @option item_shape [String] :base_shape IdOnly/Default/AllProperties
20
+ # @option item_shape :additional_properties
21
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
22
+ # @option opts [Hash] :calendar_view Limit FindItem by a start and end date
23
+ # {:calendar_view => {:max_entries_returned => 2, :start_date =>
24
+ # <DateTime Obj>, :end_date => <DateTime Obj>}}
25
+ # @option opts [Hash] :contacts_view Limit FindItem between contact names
26
+ # {:contacts_view => {:max_entries_returned => 2, :initial_name => 'Dan',
27
+ # :final_name => 'Wally'}}
28
+ # @example
29
+ # { :parent_folder_ids => [{:id => root}],
30
+ # :traversal => 'Shallow',
31
+ # :item_shape => {:base_shape => 'Default'} }
32
+ def find_item(opts)
33
+ opts = opts.clone
34
+ [:parent_folder_ids, :traversal, :item_shape].each do |k|
35
+ validate_param(opts, k, true)
36
+ end
37
+ req = build_soap! do |type, builder|
38
+ if(type == :header)
39
+ else
40
+ builder.nbuild.FindItem(:Traversal => opts[:traversal].to_s.camel_case) {
41
+ builder.nbuild.parent.default_namespace = @default_ns
42
+ builder.item_shape!(opts[:item_shape])
43
+ # @todo add FractionalPageFolderView
44
+ builder.calendar_view!(opts[:calendar_view]) if opts[:calendar_view]
45
+ builder.contacts_view!(opts[:contacts_view]) if opts[:contacts_view]
46
+ builder.restriction!(opts[:restriction]) if opts[:restriction]
47
+ builder.parent_folder_ids!(opts[:parent_folder_ids])
48
+ }
49
+ end
50
+ end
51
+ do_soap_request(req, response_class: EwsResponse)
52
+ end
53
+
54
+ # Gets items from the Exchange store
55
+ # @see http://msdn.microsoft.com/en-us/library/aa565934(v=EXCHG.140).aspx
56
+ #
57
+ # @param [Hash] opts
58
+ # @option opts [Hash] :item_shape The item shape properties
59
+ # Ex: {:base_shape => 'Default'}
60
+ # @option opts [Array<Hash>] :item_ids ItemIds Hash. The keys in these Hashes can be
61
+ # :item_id, :occurrence_item_id, or :recurring_master_item_id. Please see the
62
+ # Microsoft docs for more information.
63
+ # @example
64
+ # opts = {
65
+ # :item_shape => {:base_shape => 'Default'},
66
+ # :item_ids => [
67
+ # {:item_id => {:id => 'id1'}},
68
+ # {:occurrence_item_id => {:recurring_master_id => 'rid1', :change_key => 'ck', :instance_index => 1}},
69
+ # {:recurring_master_item_id => {:occurrence_id => 'oid1', :change_key => 'ck'}}
70
+ # ]}
71
+ def get_item(opts)
72
+ opts = opts.clone
73
+ [:item_shape, :item_ids].each do |k|
74
+ validate_param(opts, k, true)
75
+ end
76
+ req = build_soap! do |type, builder|
77
+ if(type == :header)
78
+ else
79
+ builder.nbuild.GetItem {
80
+ builder.nbuild.parent.default_namespace = @default_ns
81
+ builder.item_shape!(opts[:item_shape])
82
+ builder.item_ids!(opts[:item_ids])
83
+ }
84
+ end
85
+ end
86
+ do_soap_request(req, response_class: EwsResponse)
87
+ end
88
+
89
+ # Defines a request to create an item in the Exchange store.
90
+ # @see http://msdn.microsoft.com/en-us/library/aa565209(v=EXCHG.140).aspx
91
+ #
92
+ # @param [Hash] opts
93
+ # @option opts [String] :message_disposition How the item will be handled after it is created.
94
+ # Only applicable for to e-mail. Must be one of 'SaveOnly', 'SendOnly', or 'SendAndSaveCopy'
95
+ # @option opts [String] :send_meeting_invitations How meeting requests are handled after they
96
+ # are created. Required for calendar items. Must be one of 'SendToNone', 'SendOnlyToAll',
97
+ # 'SendToAllAndSaveCopy'
98
+ # @option opts [Hash] :saved_item_folder_id A well formatted folder_id Hash. Ex: {:id => :inbox}
99
+ # Will on work if 'SendOnly' is specified for :message_disposition
100
+ # @option opts [Array<Hash>] :items This is a complex Hash that conforms to various Item types.
101
+ # Please see the Microsoft documentation for this element.
102
+ # @example
103
+ # opts = {
104
+ # message_disposition: 'SendAndSaveCopy',
105
+ # items: [ {message:
106
+ # {subject: 'test2',
107
+ # body: {body_type: 'Text', text: 'this is a test'},
108
+ # to_recipients: [{mailbox: {email_address: 'dan.wanek@gmail.com'}}]
109
+ # }
110
+ # }]}
111
+ #
112
+ # opts = {
113
+ # send_meeting_invitations: 'SendToAllAndSaveCopy',
114
+ # items: [ {calendar_item:
115
+ # {subject: 'test cal item',
116
+ # body: {body_type: 'Text', text: 'this is a test cal item'},
117
+ # start: {text: Chronic.parse('tomorrow at 4pm').to_datetime.to_s},
118
+ # end: {text: Chronic.parse('tomorrow at 5pm').to_datetime.to_s},
119
+ # required_attendees: [
120
+ # {attendee: {mailbox: {email_address: 'dan.wanek@gmail.com'}}},
121
+ # ]
122
+ # }
123
+ # }]
124
+ def create_item(opts)
125
+ opts = opts.clone
126
+ [:items].each do |k|
127
+ validate_param(opts, k, true)
128
+ end
129
+ req = build_soap! do |type, builder|
130
+ attribs = {}
131
+ attribs['MessageDisposition'] = opts[:message_disposition] if opts[:message_disposition]
132
+ attribs['SendMeetingInvitations'] = opts[:send_meeting_invitations] if opts[:send_meeting_invitations]
133
+ if(type == :header)
134
+ else
135
+ builder.nbuild.CreateItem(attribs) {
136
+ builder.nbuild.parent.default_namespace = @default_ns
137
+ builder.saved_item_folder_id!(opts[:saved_item_folder_id]) if opts[:saved_item_folder_id]
138
+ builder.nbuild.Items {
139
+ opts[:items].each {|i|
140
+ # The key can be any number of item types like :message,
141
+ # :calendar, etc
142
+ ikey = i.keys.first
143
+ builder.send("#{ikey}!",i[ikey])
144
+ }
145
+ }
146
+ }
147
+ end
148
+ end
149
+ do_soap_request(req, response_class: EwsResponse)
150
+ end
151
+
152
+ # Used to modify the properties of an existing item in the Exchange store
153
+ # @see http://msdn.microsoft.com/en-us/library/aa581084(v=exchg.140).aspx
154
+ #
155
+ # @param [Hash] opts
156
+ # @option opts [String] :conflict_resolution Identifies the type of conflict resolution to
157
+ # try during an update. The default value is AutoResolve. Available options are
158
+ # 'NeverOverwrite', 'AutoResolve', 'AlwaysOverwrite'
159
+ # @option opts [String] :message_disposition How the item will be handled after it is updated.
160
+ # Only applicable for to e-mail. Must be one of 'SaveOnly', 'SendOnly', or 'SendAndSaveCopy'
161
+ # @option opts [String] :send_meeting_invitations_or_cancellations How meeting requests are
162
+ # handled after they are updated. Required for calendar items. Must be one of 'SendToNone',
163
+ # 'SendOnlyToAll', 'SendOnlyToChanged', 'SendToAllAndSaveCopy', 'SendToChangedAndSaveCopy'
164
+ # @option opts [Hash] :saved_item_folder_id A well formatted folder_id Hash. Ex: {:id => :sentitems}
165
+ # Will on work if 'SendOnly' is specified for :message_disposition
166
+ # @option opts [Array<Hash>] :item_changes an array of ItemChange elements that identify items
167
+ # and the updates to apply to the items. See the Microsoft docs for more information.
168
+ # @example
169
+ # opts = {
170
+ # :send_meeting_invitations_or_cancellations => 'SendOnlyToChangedAndSaveCopy',
171
+ # :item_changes => [
172
+ # { :item_id => {:id => 'id1'},
173
+ # :updates => [
174
+ # {:set_item_field => {
175
+ # :field_uRI => {:field_uRI => 'item:Subject'},
176
+ # # The following needs to conform to #build_xml! format for now
177
+ # :calendar_item => { :sub_elements => [{:subject => {:text => 'Test Subject'}}]}
178
+ # }}
179
+ # ]
180
+ # }
181
+ # ]
182
+ # }
183
+ def update_item(opts)
184
+ opts = opts.clone
185
+ [:item_changes].each do |k|
186
+ validate_param(opts, k, true)
187
+ end
188
+ req = build_soap! do |type, builder|
189
+ attribs = {}
190
+ attribs['MessageDisposition'] = opts[:message_disposition] if opts[:message_disposition]
191
+ attribs['ConflictResolution'] = opts[:conflict_resolution] if opts[:conflict_resolution]
192
+ attribs['SendMeetingInvitationsOrCancellations'] = opts[:send_meeting_invitations_or_cancellations] if opts[:send_meeting_invitations_or_cancellations]
193
+ if(type == :header)
194
+ else
195
+ builder.nbuild.UpdateItem(attribs) {
196
+ builder.nbuild.parent.default_namespace = @default_ns
197
+ builder.saved_item_folder_id!(opts[:saved_item_folder_id]) if opts[:saved_item_folder_id]
198
+ builder.item_changes!(opts[:item_changes])
199
+ }
200
+ end
201
+ end
202
+ do_soap_request(req, response_class: EwsResponse)
203
+ end
204
+
205
+ # Delete an item from a mailbox in the Exchange store
206
+ # @see http://msdn.microsoft.com/en-us/library/aa580484(v=exchg.140).aspx
207
+ #
208
+ # @param [Hash] opts
209
+ # @option opts [String] :delete_type Describes how an item is deleted. Must be one of
210
+ # 'HardDelete', 'SoftDelete', or 'MoveToDeletedItems'
211
+ # @option opts [String] :send_meeting_cancellations How meetings are handled after they
212
+ # are deleted. Required for calendar items. Must be one of 'SendToNone', 'SendOnlyToAll',
213
+ # 'SendToAllAndSaveCopy'
214
+ # @option opts [String] :affected_task_occurrences Describes whether a task instance or a
215
+ # task master is deleted by a DeleteItem Operation. This attribute is required when
216
+ # tasks are deleted. Must be one of 'AllOccurrences' or 'SpecifiedOccurrenceOnly'
217
+ # @option opts [Array<Hash>] :item_ids ItemIds Hash. The keys in these Hashes can be
218
+ # :item_id, :occurrence_item_id, or :recurring_master_item_id. Please see the
219
+ # Microsoft docs for more information.
220
+ # @example
221
+ # opts = {
222
+ # :delete_type => 'MoveToDeletedItems',
223
+ # :item_ids => [{:item_id => {:id => 'id1'}}]
224
+ # }
225
+ # inst.delete_item(opts)
226
+ def delete_item(opts)
227
+ opts = opts.clone
228
+ [:delete_type, :item_ids].each do |k|
229
+ validate_param(opts, k, true)
230
+ end
231
+ req = build_soap! do |type, builder|
232
+ attribs = {'DeleteType' => opts[:delete_type]}
233
+ attribs['SendMeetingCancellations'] = opts[:send_meeting_cancellations] if opts[:send_meeting_cancellations]
234
+ attribs['AffectedTaskOccurrences'] = opts[:affected_task_occurrences] if opts[:affected_task_occurrences]
235
+ if(type == :header)
236
+ else
237
+ builder.nbuild.DeleteItem(attribs) {
238
+ builder.nbuild.parent.default_namespace = @default_ns
239
+ builder.item_ids!(opts[:item_ids])
240
+ }
241
+ end
242
+ end
243
+ do_soap_request(req, response_class: EwsResponse)
244
+ end
245
+
246
+ # Used to move one or more items to a single destination folder.
247
+ # @see http://msdn.microsoft.com/en-us/library/aa565781(v=exchg.140).aspx
248
+ #
249
+ # @param [Hash] opts
250
+ # @option opts [Hash] :to_folder_id A well formatted folder_id Hash. Ex: {:id => :inbox}
251
+ # @option opts [Array<Hash>] :item_ids ItemIds Hash. The keys in these Hashes can be
252
+ # :item_id, :occurrence_item_id, or :recurring_master_item_id. Please see the
253
+ # Microsoft docs for more information.
254
+ # @option opts [Boolean] :return_new_item_ids Indicates whether the item identifiers of
255
+ # new items are returned in the response
256
+ # @example
257
+ # opts = {
258
+ # :to_folder_id => {:id => :inbox},
259
+ # :item_ids => [
260
+ # {:item_id => {:id => 'id1'}},
261
+ # {:item_id => {:id => 'id2'}},
262
+ # ],
263
+ # :return_new_item_ids => true
264
+ # }
265
+ # obj.move_item(opts)
266
+ def move_item(opts)
267
+ opts = opts.clone
268
+ [:to_folder_id, :item_ids].each do |k|
269
+ validate_param(opts, k, true)
270
+ end
271
+ return_new_ids = validate_param(opts, :return_new_item_ids, false, true)
272
+
273
+ req = build_soap! do |type, builder|
274
+ if(type == :header)
275
+ else
276
+ builder.nbuild.MoveItem {
277
+ builder.nbuild.parent.default_namespace = @default_ns
278
+ builder.to_folder_id!(opts[:to_folder_id])
279
+ builder.item_ids!(opts[:item_ids])
280
+ builder.return_new_item_ids!(return_new_ids)
281
+ }
282
+ end
283
+ end
284
+ do_soap_request(req, response_class: EwsResponse)
285
+ end
286
+
287
+ # Copies items and puts the items in a different folder
288
+ # @see http://msdn.microsoft.com/en-us/library/aa565012(v=exchg.140).aspx
289
+ #
290
+ # @param [Hash] opts
291
+ # @option opts [Hash] :to_folder_id A well formatted folder_id Hash. Ex: {:id => :inbox}
292
+ # @option opts [Array<Hash>] :item_ids ItemIds Hash. The keys in these Hashes can be
293
+ # :item_id, :occurrence_item_id, or :recurring_master_item_id. Please see the
294
+ # Microsoft docs for more information.
295
+ # @option opts [Boolean] :return_new_item_ids Indicates whether the item identifiers of
296
+ # new items are returned in the response
297
+ # @example
298
+ # opts = {
299
+ # :to_folder_id => {:id => :inbox},
300
+ # :item_ids => [
301
+ # {:item_id => {:id => 'id1'}},
302
+ # {:item_id => {:id => 'id2'}},
303
+ # ],
304
+ # :return_new_item_ids => true
305
+ # }
306
+ # obj.copy_item(opts)
307
+ def copy_item(opts)
308
+ opts = opts.clone
309
+ [:to_folder_id, :item_ids].each do |k|
310
+ validate_param(opts, k, true)
311
+ end
312
+ return_new_ids = validate_param(opts, :return_new_item_ids, false, true)
313
+
314
+ req = build_soap! do |type, builder|
315
+ if(type == :header)
316
+ else
317
+ builder.nbuild.CopyItem {
318
+ builder.nbuild.parent.default_namespace = @default_ns
319
+ builder.to_folder_id!(opts[:to_folder_id])
320
+ builder.item_ids!(opts[:item_ids])
321
+ builder.return_new_item_ids!(return_new_ids)
322
+ }
323
+ end
324
+ end
325
+ do_soap_request(req, response_class: EwsResponse)
326
+ end
327
+
328
+ # Used to send e-mail messages that are located in the Exchange store.
329
+ # @see http://msdn.microsoft.com/en-us/library/aa580238(v=exchg.140).aspx
330
+ #
331
+ # @param [Hash] opts
332
+ # @option opts [Boolean] :save_item_to_folder To save or not to save... save! :-)
333
+ # @option opts [Hash] :saved_item_folder_id A well formatted folder_id Hash. Ex: {:id => :sentitems}
334
+ # @option opts [Array<Hash>] :item_ids ItemIds Hash. The keys in these Hashes can be
335
+ # :item_id, :occurrence_item_id, or :recurring_master_item_id. Please see the
336
+ # Microsoft docs for more information.
337
+ # @example
338
+ # opts = {
339
+ # :save_item_to_folder => true,
340
+ # :saved_item_folder_id => {:id => :sentitems},
341
+ # :item_ids => [
342
+ # {:item_id => {:id => 'id1'}},
343
+ # {:item_id => {:id => 'id2'}},
344
+ # ]}
345
+ # obj.send_item(opts)
346
+ def send_item(opts)
347
+ opts = opts.clone
348
+ [:item_ids].each do |k|
349
+ validate_param(opts, k, true)
350
+ end
351
+
352
+ req = build_soap! do |type, builder|
353
+ attribs = {}
354
+ attribs['SaveItemToFolder'] = validate_param(opts, :save_item_to_folder, false, true)
355
+ if(type == :header)
356
+ else
357
+ builder.nbuild.SendItem(attribs) {
358
+ builder.nbuild.parent.default_namespace = @default_ns
359
+ builder.item_ids!(opts[:item_ids])
360
+ builder.saved_item_folder_id!(opts[:saved_item_folder_id]) if opts[:saved_item_folder_id]
361
+ }
362
+ end
363
+ end
364
+ do_soap_request(req, response_class: EwsResponse)
365
+ end
366
+
367
+
368
+ # ------------- Folder Operations ------------
369
+
370
+ # Creates folders, calendar folders, contacts folders, tasks folders, and search folders.
371
+ # @see http://msdn.microsoft.com/en-us/library/aa563574.aspx CreateFolder
372
+ #
373
+ # @param [Hash] opts
374
+ # @option opts [Hash] :parent_folder_id A hash with either the name of a
375
+ # folder or it's numerical ID.
376
+ # See: http://msdn.microsoft.com/en-us/library/aa565998.aspx
377
+ # {:id => :root} or {:id => 'myfolderid#'}
378
+ # @option opts [Array<Hash>] :folders An array of hashes of folder types
379
+ # that conform to input for build_xml!
380
+ # @example [
381
+ # {:folder =>
382
+ # {:display_name => "New Folder"}},
383
+ # {:calendar_folder =>
384
+ # {:folder_id => {:id => 'blah', :change_key => 'blah'}}}
385
+ def create_folder(opts)
386
+ opts = opts.clone
387
+ req = build_soap! do |type, builder|
388
+ if(type == :header)
389
+ else
390
+ builder.nbuild.CreateFolder {|x|
391
+ x.parent.default_namespace = @default_ns
392
+ builder.parent_folder_id!(opts[:parent_folder_id])
393
+ builder.folders!(opts[:folders])
394
+ }
395
+ end
396
+ end
397
+ do_soap_request(req)
398
+ end
399
+
400
+ # Defines a request to copy folders in the Exchange store
401
+ # @see http://msdn.microsoft.com/en-us/library/aa563949.aspx
402
+ # @param [Hash] to_folder_id The target FolderId
403
+ # {:id => <myid>, :change_key => <optional ck>}
404
+ # @param [Array<Hash>] *sources The source Folders
405
+ # {:id => <myid>, :change_key => <optional_ck>},
406
+ # {:id => <myid2>, :change_key => <optional_ck>}
407
+ def copy_folder(to_folder_id, *sources)
408
+ req = build_soap! do |type, builder|
409
+ if(type == :header)
410
+ else
411
+ builder.nbuild.CopyFolder {
412
+ builder.nbuild.parent.default_namespace = @default_ns
413
+ builder.to_folder_id!(to_folder_id)
414
+ builder.folder_ids!(sources.flatten)
415
+ }
416
+ end
417
+ end
418
+ do_soap_request(req)
419
+ end
420
+
421
+ # Deletes folders from a mailbox.
422
+ # @see http://msdn.microsoft.com/en-us/library/aa564767.aspx DeleteFolder
423
+ #
424
+ # @param [Hash] opts
425
+ # @option opts [Array<Hash>] :folder_ids An array of folder_ids in the form:
426
+ # [ {:id => 'myfolderID##asdfs', :change_key => 'asdfasdf'},
427
+ # {:id => :msgfolderroot} ] # Don't do this for real
428
+ # @option opts [String,nil] :delete_type Type of delete to do:
429
+ # HardDelete/SoftDelete/MoveToDeletedItems
430
+ # @option opts [String,nil] :act_as User to act on behalf as. This user
431
+ # must have been given delegate access to this folder or else this
432
+ # operation will fail.
433
+ def delete_folder(opts)
434
+ req = build_soap! do |type, builder|
435
+ if(type == :header)
436
+ else
437
+ builder.nbuild.DeleteFolder('DeleteType' => opts[:delete_type]) {
438
+ builder.nbuild.parent.default_namespace = @default_ns
439
+ builder.folder_ids!(opts[:folder_ids], opts[:act_as])
440
+ }
441
+ end
442
+ end
443
+ do_soap_request(req)
444
+ end
445
+
446
+ # Find subfolders of an identified folder
447
+ # @see http://msdn.microsoft.com/en-us/library/aa563918.aspx
448
+ #
449
+ # @param [Hash] opts
450
+ # @option opts [Array<Hash>] :parent_folder_ids An Array of folder id Hashes,
451
+ # either a DistinguishedFolderId (must me a Symbol) or a FolderId (String)
452
+ # [{:id => <myid>, :change_key => <ck>}, {:id => :root}]
453
+ # @option opts [String] :traversal Shallow/Deep/SoftDeleted
454
+ # @option opts [Hash] :folder_shape defines the FolderShape node
455
+ # See: http://msdn.microsoft.com/en-us/library/aa494311.aspx
456
+ # @option folder_shape [String] :base_shape IdOnly/Default/AllProperties
457
+ # @option folder_shape :additional_properties
458
+ # See: http://msdn.microsoft.com/en-us/library/aa563810.aspx
459
+ # @option opts [Hash] :restriction A well formatted restriction Hash.
460
+ # @example
461
+ # { :parent_folder_ids => [{:id => root}],
462
+ # :traversal => 'Deep',
463
+ # :folder_shape => {:base_shape => 'Default'} }
464
+ # @todo add FractionalPageFolderView
465
+ def find_folder(opts)
466
+ opts = opts.clone
467
+ [:parent_folder_ids, :traversal, :folder_shape].each do |k|
468
+ validate_param(opts, k, true)
469
+ end
470
+
471
+ req = build_soap! do |type, builder|
472
+ if(type == :header)
473
+ else
474
+ builder.nbuild.FindFolder(:Traversal => opts[:traversal].to_s.camel_case) {
475
+ builder.nbuild.parent.default_namespace = @default_ns
476
+ builder.folder_shape!(opts[:folder_shape])
477
+ builder.restriction!(opts[:restriction]) if opts[:restriction]
478
+ builder.parent_folder_ids!(opts[:parent_folder_ids])
479
+ }
480
+ end
481
+ end
482
+ do_soap_request(req)
483
+ end
484
+
485
+ # Gets folders from the Exchange store
486
+ # @see http://msdn.microsoft.com/en-us/library/aa580274.aspx
487
+ #
488
+ # @param [Hash] opts
489
+ # @option opts [Array<Hash>] :folder_ids An array of folder_ids in the form:
490
+ # [ {:id => 'myfolderID##asdfs', :change_key => 'asdfasdf'},
491
+ # {:id => :msgfolderroot} ]
492
+ # @option opts [Hash] :folder_shape defines the FolderShape node
493
+ # @option folder_shape [String] :base_shape IdOnly/Default/AllProperties
494
+ # @option folder_shape :additional_properties
495
+ # @option opts [String,nil] :act_as User to act on behalf as. This user must
496
+ # have been given delegate access to this folder or else this operation
497
+ # will fail.
498
+ # @example
499
+ # { :folder_ids => [{:id => :msgfolderroot}],
500
+ # :folder_shape => {:base_shape => 'Default'} }
501
+ def get_folder(opts)
502
+ opts = opts.clone
503
+ [:folder_ids, :folder_shape].each do |k|
504
+ validate_param(opts, k, true)
505
+ end
506
+ validate_param(opts[:folder_shape], :base_shape, true)
507
+ req = build_soap! do |type, builder|
508
+ if(type == :header)
509
+ else
510
+ builder.nbuild.GetFolder {
511
+ builder.nbuild.parent.default_namespace = @default_ns
512
+ builder.folder_shape!(opts[:folder_shape])
513
+ builder.folder_ids!(opts[:folder_ids], opts[:act_as])
514
+ }
515
+ end
516
+ end
517
+ do_soap_request(req)
518
+ end
519
+
520
+ # Defines a request to move folders in the Exchange store
521
+ # @see http://msdn.microsoft.com/en-us/library/aa566202.aspx
522
+ # @param [Hash] to_folder_id The target FolderId
523
+ # {:id => <myid>, :change_key => <optional ck>}
524
+ # @param [Array<Hash>] *sources The source Folders
525
+ # {:id => <myid>, :change_key => <optional_ck>},
526
+ # {:id => <myid2>, :change_key => <optional_ck>}
527
+ def move_folder(to_folder_id, *sources)
528
+ req = build_soap! do |type, builder|
529
+ if(type == :header)
530
+ else
531
+ builder.nbuild.MoveFolder {
532
+ builder.nbuild.parent.default_namespace = @default_ns
533
+ builder.to_folder_id!(to_folder_id)
534
+ builder.folder_ids!(sources.flatten)
535
+ }
536
+ end
537
+ end
538
+ do_soap_request(req)
539
+ end
540
+
541
+ # Update properties for a specified folder
542
+ # There is a lot more building in this method because most of the builders
543
+ # are only used for this operation so there was no need to externalize them
544
+ # for re-use.
545
+ # @see http://msdn.microsoft.com/en-us/library/aa580519(v=EXCHG.140).aspx
546
+ # @param [Array<Hash>] folder_changes an Array of well formatted Hashes
547
+ def update_folder(folder_changes)
548
+ req = build_soap! do |type, builder|
549
+ if(type == :header)
550
+ else
551
+ builder.nbuild.UpdateFolder {
552
+ builder.nbuild.parent.default_namespace = @default_ns
553
+ builder.nbuild.FolderChanges {
554
+ folder_changes.each do |fc|
555
+ builder[NS_EWS_TYPES].FolderChange {
556
+ builder.dispatch_folder_id!(fc)
557
+ builder[NS_EWS_TYPES].Updates {
558
+ # @todo finish implementation
559
+ }
560
+ }
561
+ end
562
+ }
563
+ }
564
+ end
565
+ end
566
+ do_soap_request(req)
567
+ end
568
+
569
+ # Empties folders in a mailbox.
570
+ # @see http://msdn.microsoft.com/en-us/library/ff709484.aspx
571
+ # @param [Hash] opts
572
+ # @option opts [String] :delete_type Must be one of
573
+ # ExchangeDataServices::HARD_DELETE, SOFT_DELETE, or MOVE_TO_DELETED_ITEMS
574
+ # @option opts [Boolean] :delete_sub_folders
575
+ # @option opts [Array<Hash>] :folder_ids An array of folder_ids in the form:
576
+ # [ {:id => 'myfolderID##asdfs', :change_key => 'asdfasdf'},
577
+ # {:id => 'blah'} ]
578
+ # @todo Finish
579
+ def empty_folder(opts)
580
+ validate_version(VERSION_2010_SP1)
581
+ ef_opts = {}
582
+ [:delete_type, :delete_sub_folders].each do |k|
583
+ ef_opts[k.to_s.camel_case] = validate_param(opts, k, true)
584
+ end
585
+ fids = validate_param opts, :folder_ids, true
586
+
587
+ req = build_soap! do |type, builder|
588
+ if(type == :header)
589
+ else
590
+ builder.nbuild.EmptyFolder(ef_opts) {|x|
591
+ builder.nbuild.parent.default_namespace = @default_ns
592
+ builder.folder_ids!(fids)
593
+ }
594
+ end
595
+ end
596
+ do_soap_request(req)
597
+ end
598
+
599
+ # ----------- Attachment Operations ----------
600
+
601
+ # Used to retrieve existing attachments on items in the Exchange store
602
+ # @see http://msdn.microsoft.com/en-us/library/aa494316.aspx
603
+ # @param [Hash] opts
604
+ # @option opts [Array] :attachment_ids Attachment Ids to fetch
605
+ # @option opts [Hash] :attachment_shape Attachment shape
606
+ # include_mime_content: true or false (optional)
607
+ # body_type: "Best" | "HTML" | "Text" (optional)
608
+ # filter_html_content: true or false (optional)
609
+ # additional_properties: @todo finish implementation
610
+ def get_attachment(opts)
611
+ opts = opts.clone
612
+ [:attachment_ids].each do |k|
613
+ validate_param(opts, k, true)
614
+ end
615
+ req = build_soap! do |type, builder|
616
+ if(type == :header)
617
+ else
618
+ builder.nbuild.GetAttachment {|x|
619
+ builder.nbuild.parent.default_namespace = @default_ns
620
+ builder.attachment_ids!(opts[:attachment_ids])
621
+ }
622
+ end
623
+ end
624
+ do_soap_request(req)
625
+ end
626
+
627
+ # Creates either an item or file attachment and attaches it to the specified item.
628
+ # @see http://msdn.microsoft.com/en-us/library/aa565877.aspx
629
+ # @param [Hash] opts
630
+ # @option opts [Hash] :parent_id {id: <id>, change_key: <ck>}
631
+ # @option opts [Array<Hash>] :files An Array of Base64 encoded Strings with
632
+ # an associated name:
633
+ # {:name => <name>, :content => <Base64 encoded string>}
634
+ # @option opts [Array] :items Exchange Items to attach to this Item
635
+ # @todo Need to implement attachment of Item types
636
+ def create_attachment(opts)
637
+ opts = opts.clone
638
+ [:parent_id].each do |k|
639
+ validate_param(opts, k, true)
640
+ end
641
+ validate_param(opts, :files, false, [])
642
+ validate_param(opts, :items, false, [])
643
+
644
+ req = build_soap! do |type, builder|
645
+ if(type == :header)
646
+ else
647
+ builder.nbuild.CreateAttachment {|x|
648
+ builder.nbuild.parent.default_namespace = @default_ns
649
+ builder.parent_item_id!(opts[:parent_id])
650
+ x.Attachments {
651
+ opts[:files].each do |fa|
652
+ builder.file_attachment!(fa)
653
+ end
654
+ opts[:items].each do |ia|
655
+ builder.item_attachment!(ia)
656
+ end
657
+ }
658
+ }
659
+ end
660
+ end
661
+ do_soap_request(req, response_class: EwsResponse)
662
+ end
663
+
664
+
665
+ # ------------ Utility Operations ------------
666
+
667
+ # Exposes the full membership of distribution lists.
668
+ # @see http://msdn.microsoft.com/en-us/library/aa494152.aspx ExpandDL
669
+ #
670
+ # @todo Fully support all of the ExpandDL operations. Today it just supports
671
+ # taking an e-mail address as an argument
672
+ # @param [Hash] opts
673
+ # @option opts [String] :email_address The e-mail address of the
674
+ # distribution to resolve
675
+ # @option opts [Hash] :item_id The ItemId of the private distribution to resolve.
676
+ # {:id => 'my id'}
677
+ def expand_dl(opts)
678
+ opts = opts.clone
679
+ req = build_soap! do |type, builder|
680
+ if(type == :header)
681
+ else
682
+ builder.nbuild.ExpandDL {|x|
683
+ x.parent.default_namespace = @default_ns
684
+ x.Mailbox {|mb|
685
+ key = :email_address
686
+ mb[NS_EWS_TYPES].EmailAddress(opts[key]) if opts[key]
687
+ builder.item_id! if opts[:item_id]
688
+ }
689
+ }
690
+ end
691
+ end
692
+ do_soap_request(req)
693
+ end
694
+
695
+ # Resolve ambiguous e-mail addresses and display names
696
+ # @see http://msdn.microsoft.com/en-us/library/aa565329.aspx ResolveNames
697
+ # @see http://msdn.microsoft.com/en-us/library/aa581054.aspx UnresolvedEntry
698
+ # @param [Hash] opts
699
+ # @option opts [String] :name the unresolved entry
700
+ # @option opts [Boolean] :full_contact_data (true) Whether or not to return
701
+ # the full contact details.
702
+ # @option opts [String] :search_scope where to seach for this entry, one of
703
+ # SOAP::Contacts, SOAP::ActiveDirectory, SOAP::ActiveDirectoryContacts
704
+ # (default), SOAP::ContactsActiveDirectory
705
+ # @option opts [String, FolderId] :parent_folder_id either the name of a
706
+ # folder or it's numerical ID.
707
+ # @see http://msdn.microsoft.com/en-us/library/aa565998.aspx
708
+ def resolve_names(opts)
709
+ opts = opts.clone
710
+ fcd = opts.has_key?(:full_contact_data) ? opts[:full_contact_data] : true
711
+ req = build_soap! do |type, builder|
712
+ if(type == :header)
713
+ else
714
+ builder.nbuild.ResolveNames {|x|
715
+ x.parent['ReturnFullContactData'] = fcd.to_s
716
+ x.parent['SearchScope'] = opts[:search_scope] if opts[:search_scope]
717
+ x.parent.default_namespace = @default_ns
718
+ # @todo builder.nbuild.ParentFolderIds
719
+ x.UnresolvedEntry(opts[:name])
720
+ }
721
+ end
722
+ end
723
+ do_soap_request(req)
724
+ end
725
+
726
+ # Converts item and folder identifiers between formats.
727
+ # @see http://msdn.microsoft.com/en-us/library/bb799665.aspx
728
+ # @todo Needs to be finished
729
+ def convert_id(opts)
730
+ opts = opts.clone
731
+ req = build_soap! do |type, builder|
732
+ if(type == :header)
733
+ else
734
+ builder.nbuild.ConvertId {|x|
735
+ }
736
+ end
737
+ end
738
+ do_soap_request(req)
739
+ end
740
+
741
+ end #ExchangeDataServices
742
+ end