viewpoint 0.1.27 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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