viewpoint 0.1.26 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +203 -0
  3. data/lib/ews/calendar_accessors.rb +34 -0
  4. data/lib/ews/connection.rb +140 -0
  5. data/lib/ews/connection_helper.rb +35 -0
  6. data/lib/ews/convert_accessors.rb +56 -0
  7. data/lib/{exceptions/exceptions.rb → ews/errors.rb} +29 -19
  8. data/lib/ews/ews_client.rb +105 -0
  9. data/lib/ews/exceptions/exceptions.rb +61 -0
  10. data/lib/ews/folder_accessors.rb +264 -0
  11. data/lib/ews/impersonation.rb +30 -0
  12. data/lib/ews/item_accessors.rb +242 -0
  13. data/lib/ews/mailbox_accessors.rb +92 -0
  14. data/lib/ews/meeting_accessors.rb +39 -0
  15. data/lib/ews/message_accessors.rb +93 -0
  16. data/lib/ews/push_subscription_accessors.rb +33 -0
  17. data/lib/ews/room_accessors.rb +48 -0
  18. data/lib/ews/roomlist_accessors.rb +47 -0
  19. data/lib/ews/soap.rb +64 -0
  20. data/lib/ews/soap/builders/ews_builder.rb +1384 -0
  21. data/lib/ews/soap/ews_response.rb +84 -0
  22. data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
  23. data/lib/ews/soap/ews_soap_free_busy_response.rb +119 -0
  24. data/lib/ews/soap/ews_soap_response.rb +103 -0
  25. data/lib/ews/soap/ews_soap_room_response.rb +53 -0
  26. data/lib/ews/soap/ews_soap_roomlist_response.rb +54 -0
  27. data/lib/ews/soap/exchange_availability.rb +61 -0
  28. data/lib/ews/soap/exchange_data_services.rb +780 -0
  29. data/lib/ews/soap/exchange_notification.rb +146 -0
  30. data/lib/ews/soap/exchange_synchronization.rb +93 -0
  31. data/lib/ews/soap/exchange_time_zones.rb +56 -0
  32. data/lib/ews/soap/exchange_user_configuration.rb +33 -0
  33. data/lib/ews/soap/exchange_web_service.rb +264 -0
  34. data/lib/{model/item_attachment.rb → ews/soap/parsers/ews_parser.rb} +24 -14
  35. data/lib/ews/soap/parsers/ews_sax_document.rb +70 -0
  36. data/lib/ews/soap/response_message.rb +80 -0
  37. data/lib/ews/soap/responses/create_attachment_response_message.rb +47 -0
  38. data/lib/{model/meeting_message.rb → ews/soap/responses/create_item_response_message.rb} +7 -10
  39. data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
  40. data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
  41. data/lib/ews/soap/responses/send_notification_response_message.rb +59 -0
  42. data/lib/{model/attachment.rb → ews/soap/responses/subscribe_response_message.rb} +17 -13
  43. data/lib/{model/attendee.rb → ews/soap/responses/sync_folder_hierarchy_response_message.rb} +14 -15
  44. data/lib/ews/soap/responses/sync_folder_items_response_message.rb +36 -0
  45. data/lib/ews/templates/calendar_item.rb +79 -0
  46. data/lib/ews/templates/forward_item.rb +24 -0
  47. data/lib/ews/templates/message.rb +85 -0
  48. data/lib/ews/templates/reply_to_item.rb +25 -0
  49. data/lib/ews/templates/task.rb +74 -0
  50. data/lib/ews/types.rb +194 -0
  51. data/lib/ews/types/attachment.rb +77 -0
  52. data/lib/{model/meeting_cancellation.rb → ews/types/attendee.rb} +9 -8
  53. data/lib/ews/types/calendar_folder.rb +50 -0
  54. data/lib/ews/types/calendar_item.rb +130 -0
  55. data/lib/ews/types/contact.rb +7 -0
  56. data/lib/ews/types/contacts_folder.rb +8 -0
  57. data/lib/ews/types/copied_event.rb +51 -0
  58. data/lib/{soap/handsoap/builder.rb → ews/types/created_event.rb} +5 -2
  59. data/lib/ews/types/deleted_event.rb +24 -0
  60. data/lib/ews/types/distribution_list.rb +7 -0
  61. data/lib/ews/types/event.rb +62 -0
  62. data/lib/ews/types/export_items_response_message.rb +52 -0
  63. data/lib/ews/types/file_attachment.rb +65 -0
  64. data/lib/ews/types/folder.rb +60 -0
  65. data/lib/ews/types/free_busy_changed_event.rb +24 -0
  66. data/lib/ews/types/generic_folder.rb +418 -0
  67. data/lib/ews/types/item.rb +447 -0
  68. data/lib/ews/types/item_attachment.rb +84 -0
  69. data/lib/{model → ews/types}/item_field_uri_map.rb +2 -18
  70. data/lib/ews/types/mailbox_user.rb +156 -0
  71. data/lib/ews/types/meeting_cancellation.rb +7 -0
  72. data/lib/ews/types/meeting_message.rb +7 -0
  73. data/lib/ews/types/meeting_request.rb +7 -0
  74. data/lib/ews/types/meeting_response.rb +7 -0
  75. data/lib/ews/types/message.rb +7 -0
  76. data/lib/ews/types/modified_event.rb +48 -0
  77. data/lib/{extensions/string.rb → ews/types/moved_event.rb} +31 -15
  78. data/lib/ews/types/new_mail_event.rb +24 -0
  79. data/lib/ews/types/out_of_office.rb +147 -0
  80. data/lib/ews/types/post_item.rb +7 -0
  81. data/lib/ews/types/search_folder.rb +8 -0
  82. data/lib/ews/types/status_event.rb +39 -0
  83. data/lib/ews/types/task.rb +41 -0
  84. data/lib/ews/types/tasks_folder.rb +27 -0
  85. data/lib/viewpoint.rb +85 -108
  86. data/lib/{model/distribution_list.rb → viewpoint/logging.rb} +6 -3
  87. data/lib/{model/meeting_response.rb → viewpoint/logging/config.rb} +3 -3
  88. data/lib/viewpoint/string_utils.rb +76 -0
  89. metadata +156 -123
  90. data/README +0 -114
  91. data/lib/model/calendar_folder.rb +0 -67
  92. data/lib/model/calendar_item.rb +0 -267
  93. data/lib/model/contact.rb +0 -238
  94. data/lib/model/contacts_folder.rb +0 -46
  95. data/lib/model/event.rb +0 -116
  96. data/lib/model/file_attachment.rb +0 -53
  97. data/lib/model/folder.rb +0 -47
  98. data/lib/model/generic_folder.rb +0 -461
  99. data/lib/model/item.rb +0 -312
  100. data/lib/model/mailbox_user.rb +0 -146
  101. data/lib/model/meeting_request.rb +0 -39
  102. data/lib/model/message.rb +0 -142
  103. data/lib/model/model.rb +0 -269
  104. data/lib/model/search_folder.rb +0 -48
  105. data/lib/model/task.rb +0 -121
  106. data/lib/model/tasks_folder.rb +0 -44
  107. data/lib/soap/handsoap/builders/ews_build_helpers.rb +0 -383
  108. data/lib/soap/handsoap/builders/ews_builder.rb +0 -146
  109. data/lib/soap/handsoap/ews_service.rb +0 -790
  110. data/lib/soap/handsoap/parser.rb +0 -104
  111. data/lib/soap/handsoap/parsers/ews_parser.rb +0 -245
  112. data/lib/soap/soap_provider.rb +0 -64
@@ -0,0 +1,33 @@
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::PushSubscriptionAccessors
20
+ include Viewpoint::EWS
21
+
22
+ def parse_send_notification(msg)
23
+ parser = Viewpoint::EWS::SOAP::EwsParser.new(msg)
24
+ resp = parser.parse response_class: Viewpoint::EWS::SOAP::EwsResponse
25
+ rmsg = resp.response_messages[0]
26
+ if rmsg.success?
27
+ rmsg
28
+ else
29
+ raise EwsSubscriptionError, "#{rmsg.code}: #{rmsg.message_text}"
30
+ end
31
+ end
32
+
33
+ end # Viewpoint::EWS::PushSubscriptionAccessors
@@ -0,0 +1,48 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2013 Camille Baldock <viewpoint@camillebaldock.co.uk>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::EWS::RoomAccessors
20
+ include Viewpoint::EWS
21
+
22
+ # Gets the rooms that are available within the specified room distribution list
23
+ # @see http://msdn.microsoft.com/en-us/library/dd899415.aspx
24
+ # @param [String] roomDistributionList
25
+ def get_rooms(roomDistributionList)
26
+ resp = ews.get_rooms(roomDistributionList)
27
+ get_rooms_parser(resp)
28
+ end
29
+
30
+ def room_name( room )
31
+ room[:room][:elems][:id][:elems][0][:name][:text]
32
+ end
33
+
34
+ def room_email( room )
35
+ room[:room][:elems][:id][:elems][1][:email_address][:text]
36
+ end
37
+
38
+ private
39
+
40
+ def get_rooms_parser(resp)
41
+ if resp.success?
42
+ resp
43
+ else
44
+ raise EwsError, "GetRooms produced an error: #{resp.code}: #{resp.message}"
45
+ end
46
+ end
47
+
48
+ end # Viewpoint::EWS::RoomAccessors
@@ -0,0 +1,47 @@
1
+ =begin
2
+ This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
3
+
4
+ Copyright © 2013 Camille Baldock <viewpoint@camillebaldock.co.uk>
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ module Viewpoint::EWS::RoomlistAccessors
20
+ include Viewpoint::EWS
21
+
22
+ # Gets the room lists that are available within the Exchange organization.
23
+ # @see http://msdn.microsoft.com/en-us/library/dd899416.aspx
24
+ def get_room_lists
25
+ resp = ews.get_room_lists
26
+ get_room_lists_parser(resp)
27
+ end
28
+
29
+ def roomlist_name( roomlist )
30
+ roomlist[:address][:elems][:name][:text]
31
+ end
32
+
33
+ def roomlist_email( roomlist )
34
+ roomlist[:address][:elems][:email_address][:text]
35
+ end
36
+
37
+ private
38
+
39
+ def get_room_lists_parser(resp)
40
+ if resp.success?
41
+ resp
42
+ else
43
+ raise EwsError, "GetRoomLists produced an error: #{resp.code}: #{resp.message}"
44
+ end
45
+ end
46
+
47
+ end # Viewpoint::EWS::RoomlistAccessors
data/lib/ews/soap.rb ADDED
@@ -0,0 +1,64 @@
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
+ # This module defines some constants and other niceties to make available to
20
+ # the underlying SOAP classes and modules that do the actual work.
21
+ module Viewpoint
22
+ module EWS
23
+ module SOAP
24
+
25
+ # CONSTANTS
26
+
27
+ NS_SOAP = 'soap'.freeze
28
+ NS_EWS_TYPES = 't'.freeze
29
+ NS_EWS_MESSAGES = 'm'.freeze
30
+ NAMESPACES = {
31
+ "xmlns:#{NS_SOAP}" => 'http://schemas.xmlsoap.org/soap/envelope/',
32
+ "xmlns:#{NS_EWS_TYPES}" => 'http://schemas.microsoft.com/exchange/services/2006/types',
33
+ "xmlns:#{NS_EWS_MESSAGES}" => 'http://schemas.microsoft.com/exchange/services/2006/messages',
34
+ }.freeze
35
+
36
+ # used in ResolveNames to determine where names are resolved
37
+ ActiveDirectory = 'ActiveDirectory'
38
+ ActiveDirectoryContacts = 'ActiveDirectoryContacts'
39
+ Contacts = 'Contacts'
40
+ ContactsActiveDirectory = 'ContactsActiveDirectory'
41
+
42
+ # Target specific Exchange Server versions
43
+ # @see http://msdn.microsoft.com/en-us/library/bb891876(v=exchg.140).aspx
44
+ VERSION_2007 = 'Exchange2007'
45
+ VERSION_2007_SP1 = 'Exchange2007_SP1'
46
+ VERSION_2010 = 'Exchange2010'
47
+ VERSION_2010_SP1 = 'Exchange2010_SP1'
48
+ VERSION_2010_SP2 = 'Exchange2010_SP2'
49
+ VERSION_2013 = 'Exchange2013'
50
+ VERSION_2013_SP1 = 'Exchange2013_SP1'
51
+ VERSION_NONE = 'none'
52
+
53
+ HARD_DELETE = 'HardDelete'
54
+ SOFT_DELETE = 'SoftDelete'
55
+ MOVE_TO_DELETED_ITEMS = 'MoveToDeletedItems'
56
+
57
+ def initialize
58
+ @log = Logging.logger[self.class.name.to_s.to_sym]
59
+ @default_ns = NAMESPACES["xmlns:#{NS_EWS_MESSAGES}"]
60
+ end
61
+
62
+ end # SOAP
63
+ end # EWS
64
+ end # Viewpoint
@@ -0,0 +1,1384 @@
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
+ module Viewpoint::EWS::SOAP
19
+
20
+ # This class includes the element builders. The idea is that each element should
21
+ # know how to build themselves so each parent element can delegate creation of
22
+ # subelements to a method of the same name with a '!' after it.
23
+ class EwsBuilder
24
+ include Viewpoint::EWS
25
+ include Viewpoint::StringUtils
26
+
27
+ attr_reader :nbuild
28
+ def initialize
29
+ @nbuild = Nokogiri::XML::Builder.new
30
+ end
31
+
32
+ # Build the SOAP envelope and yield this object so subelements can be built. Once
33
+ # you have the EwsBuilder object you can use the nbuild object like shown in the
34
+ # example for the Header section. The nbuild object is the underlying
35
+ # Nokogiri::XML::Builder object.
36
+ # @param [Hash] opts
37
+ # @option opts [String] :server_version The version string that should get
38
+ # set in the Header. See ExchangeWebService#initialize
39
+ # @option opts [Hash] :time_zone_context TimeZoneDefinition. Format: !{id: time_zone_identifier}
40
+ # @example
41
+ # xb = EwsBuilder.new
42
+ # xb.build! do |part, b|
43
+ # if(part == :header)
44
+ # b.nbuild.MyVar('blablabla')
45
+ # else
46
+ # b.folder_shape!({:base_shape => 'Default'})
47
+ # end
48
+ # end
49
+ def build!(opts = {}, &block)
50
+ @nbuild.Envelope(NAMESPACES) do |node|
51
+ node.parent.namespace = parent_namespace(node)
52
+ node.Header {
53
+ set_version_header! opts[:server_version]
54
+ set_impersonation! opts[:impersonation_type], opts[:impersonation_mail]
55
+ set_time_zone_context_header! opts[:time_zone_context]
56
+ yield(:header, self) if block_given?
57
+ }
58
+ node.Body {
59
+ yield(:body, self) if block_given?
60
+ }
61
+ end
62
+ @nbuild.doc
63
+ end
64
+
65
+ # Build XML from a passed in Hash or Array in a specified format.
66
+ # @param [Array,Hash] elems The elements to add to the Builder. They must
67
+ # be specified like so:
68
+ #
69
+ # !{:top =>
70
+ # { :xmlns => 'http://stonesthrow/soap',
71
+ # :sub_elements => [
72
+ # {:elem1 => {:text => 'inside'}},
73
+ # {:elem2 => {:text => 'inside2'}}
74
+ # ],
75
+ # :id => '3232', :tx_dd => 23, :asdf => 'turkey'
76
+ # }
77
+ # }
78
+ # or
79
+ # [ {:first => {:text => 'hello'}},
80
+ # {:second => {:text => 'world'}}
81
+ # ]
82
+ #
83
+ # NOTE: there are specialized keys for text (:text), child elements
84
+ # (:sub_elements) and namespaces (:xmlns).
85
+ def build_xml!(elems)
86
+ case elems.class.name
87
+ when 'Hash'
88
+ keys = elems.keys
89
+ vals = elems.values
90
+ if(keys.length > 1 && !vals.is_a?(Hash))
91
+ raise "invalid input: #{elems}"
92
+ end
93
+ vals = vals.first.clone
94
+ se = vals.delete(:sub_elements)
95
+ txt = vals.delete(:text)
96
+ xmlns_attribute = vals.delete(:xmlns_attribute)
97
+
98
+ node = @nbuild.send(camel_case(keys.first), txt, vals) {|x|
99
+ build_xml!(se) if se
100
+ }
101
+
102
+ # Set node level namespace
103
+ node.xmlns = NAMESPACES["xmlns:#{xmlns_attribute}"] if xmlns_attribute
104
+ when 'Array'
105
+ elems.each do |e|
106
+ build_xml!(e)
107
+ end
108
+ else
109
+ raise "Unsupported type: #{elems.class.name}"
110
+ end
111
+ end
112
+
113
+ # Build the FolderShape element
114
+ # @see http://msdn.microsoft.com/en-us/library/aa494311.aspx
115
+ # @param [Hash] folder_shape The folder shape structure to build from
116
+ # @todo need fully support all options
117
+ def folder_shape!(folder_shape)
118
+ @nbuild.FolderShape {
119
+ @nbuild.parent.default_namespace = @default_ns
120
+ base_shape!(folder_shape[:base_shape])
121
+ if(folder_shape[:additional_properties])
122
+ additional_properties!(folder_shape[:additional_properties])
123
+ end
124
+ }
125
+ end
126
+
127
+ # Build the ItemShape element
128
+ # @see http://msdn.microsoft.com/en-us/library/aa565261.aspx
129
+ # @param [Hash] item_shape The item shape structure to build from
130
+ # @todo need fully support all options
131
+ def item_shape!(item_shape)
132
+ @nbuild[NS_EWS_MESSAGES].ItemShape {
133
+ @nbuild.parent.default_namespace = @default_ns
134
+ base_shape!(item_shape[:base_shape])
135
+ include_mime_content!(item_shape[:include_mime_content]) if item_shape.has_key?(:include_mime_content)
136
+ body_type!(item_shape[:body_type]) if item_shape[:body_type]
137
+ if(item_shape[:additional_properties])
138
+ additional_properties!(item_shape[:additional_properties])
139
+ end
140
+ }
141
+ end
142
+
143
+ # Build the IndexedPageItemView element
144
+ # @see http://msdn.microsoft.com/en-us/library/exchange/aa563549(v=exchg.150).aspx
145
+ # @todo needs peer check
146
+ def indexed_page_item_view!(indexed_page_item_view)
147
+ attribs = {}
148
+ indexed_page_item_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
149
+ @nbuild[NS_EWS_MESSAGES].IndexedPageItemView(attribs)
150
+ end
151
+
152
+ # Build the BaseShape element
153
+ # @see http://msdn.microsoft.com/en-us/library/aa580545.aspx
154
+ def base_shape!(base_shape)
155
+ @nbuild[NS_EWS_TYPES].BaseShape(camel_case(base_shape))
156
+ end
157
+
158
+ def include_mime_content!(include_mime_content)
159
+ @nbuild[NS_EWS_TYPES].IncludeMimeContent(include_mime_content.to_s.downcase)
160
+ end
161
+
162
+ def body_type!(body_type)
163
+ body_type = body_type.to_s
164
+ if body_type =~ /html/i
165
+ body_type = body_type.upcase
166
+ else
167
+ body_type = body_type.downcase.capitalize
168
+ end
169
+ nbuild[NS_EWS_TYPES].BodyType(body_type)
170
+ end
171
+
172
+ # Build the ParentFolderIds element
173
+ # @see http://msdn.microsoft.com/en-us/library/aa565998.aspx
174
+ def parent_folder_ids!(pfids)
175
+ @nbuild[NS_EWS_MESSAGES].ParentFolderIds {
176
+ pfids.each do |pfid|
177
+ dispatch_folder_id!(pfid)
178
+ end
179
+ }
180
+ end
181
+
182
+ # Build the ParentFolderId element
183
+ # @see http://msdn.microsoft.com/en-us/library/aa563268.aspx
184
+ def parent_folder_id!(pfid)
185
+ @nbuild.ParentFolderId {
186
+ dispatch_folder_id!(pfid)
187
+ }
188
+ end
189
+
190
+ # Build the FolderIds element
191
+ # @see http://msdn.microsoft.com/en-us/library/aa580509.aspx
192
+ def folder_ids!(fids, act_as=nil)
193
+ ns = @nbuild.parent.name.match(/subscription/i) ? NS_EWS_TYPES : NS_EWS_MESSAGES
194
+ @nbuild[ns].FolderIds {
195
+ fids.each do |fid|
196
+ fid[:act_as] = act_as if act_as != nil
197
+ dispatch_folder_id!(fid)
198
+ end
199
+ }
200
+ end
201
+
202
+ # Build the SyncFolderId element
203
+ # @see http://msdn.microsoft.com/en-us/library/aa580296.aspx
204
+ def sync_folder_id!(fid)
205
+ @nbuild.SyncFolderId {
206
+ dispatch_folder_id!(fid)
207
+ }
208
+ end
209
+
210
+ # Build the DistinguishedFolderId element
211
+ # @see http://msdn.microsoft.com/en-us/library/aa580808.aspx
212
+ # @todo add support for the Mailbox child object
213
+ def distinguished_folder_id!(dfid, change_key = nil, act_as = nil)
214
+ attribs = {'Id' => dfid.to_s}
215
+ attribs['ChangeKey'] = change_key if change_key
216
+ @nbuild[NS_EWS_TYPES].DistinguishedFolderId(attribs) {
217
+ if ! act_as.nil?
218
+ mailbox!({:email_address => act_as})
219
+ end
220
+ }
221
+ end
222
+
223
+ # Build the FolderId element
224
+ # @see http://msdn.microsoft.com/en-us/library/aa579461.aspx
225
+ def folder_id!(fid, change_key = nil)
226
+ attribs = {'Id' => fid}
227
+ attribs['ChangeKey'] = change_key if change_key
228
+ @nbuild[NS_EWS_TYPES].FolderId(attribs)
229
+ end
230
+
231
+ # @see http://msdn.microsoft.com/en-us/library/aa563525(v=EXCHG.140).aspx
232
+ def item_ids!(item_ids)
233
+ @nbuild.ItemIds {
234
+ item_ids.each do |iid|
235
+ dispatch_item_id!(iid)
236
+ end
237
+ }
238
+ end
239
+
240
+ def parent_item_id!(id)
241
+ nbuild.ParentItemId {|x|
242
+ x.parent['Id'] = id[:id]
243
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
244
+ }
245
+ end
246
+
247
+ # @see http://msdn.microsoft.com/en-us/library/aa580234(v=EXCHG.140).aspx
248
+ def item_id!(id)
249
+ nbuild[NS_EWS_TYPES].ItemId {|x|
250
+ x.parent['Id'] = id[:id]
251
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
252
+ }
253
+ end
254
+
255
+ # @see http://msdn.microsoft.com/en-us/library/ff709503(v=exchg.140).aspx
256
+ def export_item_ids!(item_ids)
257
+ ns = @nbuild.parent.name.match(/subscription/i) ? NS_EWS_TYPES : NS_EWS_MESSAGES
258
+ @nbuild[ns].ExportItems{
259
+ @nbuild.ItemIds {
260
+ item_ids.each do |iid|
261
+ dispatch_item_id!(iid)
262
+ end
263
+ }
264
+ }
265
+ end
266
+
267
+ # @see http://msdn.microsoft.com/en-us/library/aa580744(v=EXCHG.140).aspx
268
+ def occurrence_item_id!(id)
269
+ @nbuild[NS_EWS_TYPES].OccurrenceItemId {|x|
270
+ x.parent['RecurringMasterId'] = id[:recurring_master_id]
271
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
272
+ x.parent['InstanceIndex'] = id[:instance_index]
273
+ }
274
+ end
275
+
276
+ # @see http://msdn.microsoft.com/en-us/library/aa581019(v=EXCHG.140).aspx
277
+ def recurring_master_item_id!(id)
278
+ @nbuild[NS_EWS_TYPES].RecurringMasterItemId {|x|
279
+ x.parent['OccurrenceId'] = id[:occurrence_id]
280
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
281
+ }
282
+ end
283
+
284
+ # @see http://msdn.microsoft.com/en-us/library/aa565020(v=EXCHG.140).aspx
285
+ def to_folder_id!(to_fid)
286
+ @nbuild[NS_EWS_MESSAGES].ToFolderId {
287
+ dispatch_folder_id!(to_fid)
288
+ }
289
+ end
290
+
291
+ # @see http://msdn.microsoft.com/en-us/library/aa564009.aspx
292
+ def folders!(folders)
293
+ @nbuild.Folders {|x|
294
+ folders.each do |fold|
295
+ fold.each_pair do |ftype, vars| # convenience, should only be one pair
296
+ ftype = "#{ftype}!".to_sym
297
+ if self.respond_to? ftype
298
+ self.send ftype, vars
299
+ else
300
+ raise Viewpoint::EWS::EwsNotImplemented,
301
+ "#{ftype} not implemented as a builder."
302
+ end
303
+ end
304
+ end
305
+ }
306
+ end
307
+
308
+ def folder!(folder, type = :Folder)
309
+ nbuild[NS_EWS_TYPES].send(type) {|x|
310
+ folder.each_pair do |e,v|
311
+ ftype = "#{e}!".to_sym
312
+ if e == :folder_id
313
+ dispatch_folder_id!(v)
314
+ elsif self.respond_to?(ftype)
315
+ self.send ftype, v
316
+ else
317
+ raise Viewpoint::EWS::EwsNotImplemented,
318
+ "#{ftype} not implemented as a builder."
319
+ end
320
+ end
321
+ }
322
+ end
323
+
324
+ def calendar_folder!(folder)
325
+ folder! folder, :CalendarFolder
326
+ end
327
+
328
+ def contacts_folder!(folder)
329
+ folder! folder, :ContactsFolder
330
+ end
331
+
332
+ def search_folder!(folder)
333
+ folder! folder, :SearchFolder
334
+ end
335
+
336
+ def tasks_folder!(folder)
337
+ folder! folder, :TasksFolder
338
+ end
339
+
340
+ def display_name!(name)
341
+ nbuild[NS_EWS_TYPES].DisplayName(name)
342
+ end
343
+
344
+ # Build the AdditionalProperties element
345
+ # @see http://msdn.microsoft.com/en-us/library/aa563810.aspx
346
+ def additional_properties!(addprops)
347
+ @nbuild[NS_EWS_TYPES].AdditionalProperties {
348
+ addprops.each_pair {|k,v|
349
+ dispatch_field_uri!({k => v}, NS_EWS_TYPES)
350
+ }
351
+ }
352
+ end
353
+
354
+ # Build the Mailbox element.
355
+ # This element is commonly used for delegation. Typically passing an
356
+ # email_address is sufficient
357
+ # @see http://msdn.microsoft.com/en-us/library/aa565036.aspx
358
+ # @param [Hash] mailbox A well-formated hash
359
+ def mailbox!(mbox)
360
+ nbuild[NS_EWS_TYPES].Mailbox {
361
+ name!(mbox[:name]) if mbox[:name]
362
+ email_address!(mbox[:email_address]) if mbox[:email_address]
363
+ address!(mbox[:address]) if mbox[:address] # for Availability query
364
+ routing_type!(mbox[:routing_type]) if mbox[:routing_type]
365
+ mailbox_type!(mbox[:mailbox_type]) if mbox[:mailbox_type]
366
+ item_id!(mbox[:item_id]) if mbox[:item_id]
367
+ }
368
+ end
369
+
370
+ def name!(name)
371
+ nbuild[NS_EWS_TYPES].Name(name)
372
+ end
373
+
374
+ def email_address!(email)
375
+ nbuild[NS_EWS_TYPES].EmailAddress(email)
376
+ end
377
+
378
+ def address!(email)
379
+ nbuild[NS_EWS_TYPES].Address(email)
380
+ end
381
+
382
+ # This is stupid. The only valid value is "SMTP"
383
+ def routing_type!(type)
384
+ nbuild[NS_EWS_TYPES].RoutingType(type)
385
+ end
386
+
387
+ def mailbox_type!(type)Standard
388
+ nbuild[NS_EWS_TYPES].MailboxType(type)
389
+ end
390
+
391
+ def user_oof_settings!(opts)
392
+ nbuild[NS_EWS_TYPES].UserOofSettings {
393
+ nbuild.OofState(camel_case(opts[:oof_state]))
394
+ nbuild.ExternalAudience(camel_case(opts[:external_audience])) if opts[:external_audience]
395
+ duration!(opts[:duration]) if opts[:duration]
396
+ nbuild.InternalReply {
397
+ nbuild.Message(opts[:internal_reply])
398
+ } if opts[:external_reply]
399
+ nbuild.ExternalReply {
400
+ nbuild.Message(opts[:external_reply])
401
+ } if opts[:external_reply]
402
+ }
403
+ end
404
+
405
+ def duration!(opts)
406
+ nbuild.Duration {
407
+ nbuild.StartTime(format_time opts[:start_time])
408
+ nbuild.EndTime(format_time opts[:end_time])
409
+ }
410
+ end
411
+
412
+ def mailbox_data!(md)
413
+ nbuild[NS_EWS_TYPES].MailboxData {
414
+ nbuild[NS_EWS_TYPES].Email {
415
+ mbox = md[:email]
416
+ name!(mbox[:name]) if mbox[:name]
417
+ address!(mbox[:address]) if mbox[:address] # for Availability query
418
+ routing_type!(mbox[:routing_type]) if mbox[:routing_type]
419
+ }
420
+ nbuild[NS_EWS_TYPES].AttendeeType 'Required'
421
+ }
422
+ end
423
+
424
+ def free_busy_view_options!(opts)
425
+ nbuild[NS_EWS_TYPES].FreeBusyViewOptions {
426
+ nbuild[NS_EWS_TYPES].TimeWindow {
427
+ nbuild[NS_EWS_TYPES].StartTime(format_time opts[:time_window][:start_time])
428
+ nbuild[NS_EWS_TYPES].EndTime(format_time opts[:time_window][:end_time])
429
+ }
430
+ nbuild[NS_EWS_TYPES].RequestedView(camel_case(opts[:requested_view][:requested_free_busy_view]))
431
+ }
432
+ end
433
+
434
+ def suggestions_view_options!(opts)
435
+ end
436
+
437
+ def time_zone!(zone)
438
+ zone ||= {}
439
+ zone = {
440
+ bias: zone[:bias] || 480,
441
+ standard_time: {
442
+ bias: 0,
443
+ time: "02:00:00",
444
+ day_order: 5,
445
+ month: 10,
446
+ day_of_week: 'Sunday'
447
+ }.merge(zone[:standard_time] || {}),
448
+ daylight_time: {
449
+ bias: -60,
450
+ time: "02:00:00",
451
+ day_order: 1,
452
+ month: 4,
453
+ day_of_week: 'Sunday'
454
+ }.merge(zone[:daylight_time] || {})
455
+ }
456
+
457
+ nbuild[NS_EWS_TYPES].TimeZone {
458
+ nbuild[NS_EWS_TYPES].Bias(zone[:bias])
459
+ nbuild[NS_EWS_TYPES].StandardTime {
460
+ nbuild[NS_EWS_TYPES].Bias(zone[:standard_time][:bias])
461
+ nbuild[NS_EWS_TYPES].Time(zone[:standard_time][:time])
462
+ nbuild[NS_EWS_TYPES].DayOrder(zone[:standard_time][:day_order])
463
+ nbuild[NS_EWS_TYPES].Month(zone[:standard_time][:month])
464
+ nbuild[NS_EWS_TYPES].DayOfWeek(zone[:standard_time][:day_of_week])
465
+ }
466
+ nbuild[NS_EWS_TYPES].DaylightTime {
467
+ nbuild[NS_EWS_TYPES].Bias(zone[:daylight_time][:bias])
468
+ nbuild[NS_EWS_TYPES].Time(zone[:daylight_time][:time])
469
+ nbuild[NS_EWS_TYPES].DayOrder(zone[:daylight_time][:day_order])
470
+ nbuild[NS_EWS_TYPES].Month(zone[:daylight_time][:month])
471
+ nbuild[NS_EWS_TYPES].DayOfWeek(zone[:daylight_time][:day_of_week])
472
+ }
473
+ }
474
+ end
475
+
476
+ # Request all known time_zones from server
477
+ def get_server_time_zones!(get_time_zone_options)
478
+ nbuild[NS_EWS_MESSAGES].GetServerTimeZones('ReturnFullTimeZoneData' => get_time_zone_options[:full]) do
479
+ if get_time_zone_options[:ids] && get_time_zone_options[:ids].any?
480
+ nbuild[NS_EWS_MESSAGES].Ids do
481
+ get_time_zone_options[:ids].each do |id|
482
+ nbuild[NS_EWS_TYPES].Id id
483
+ end
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+ # Specifies an optional time zone for the start time
490
+ # @param [Hash] attributes
491
+ # @option attributes :id [String] ID of the Microsoft well known time zone
492
+ # @option attributes :name [String] Optional name of the time zone
493
+ # @todo Implement sub elements Periods, TransitionsGroups and Transitions to override zone
494
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899524.aspx
495
+ def start_time_zone!(zone)
496
+ attributes = {}
497
+ attributes['Id'] = zone[:id] if zone[:id]
498
+ attributes['Name'] = zone[:name] if zone[:name]
499
+ nbuild[NS_EWS_TYPES].StartTimeZone(attributes)
500
+ end
501
+
502
+ # Specifies an optional time zone for the end time
503
+ # @param [Hash] attributes
504
+ # @option attributes :id [String] ID of the Microsoft well known time zone
505
+ # @option attributes :name [String] Optional name of the time zone
506
+ # @todo Implement sub elements Periods, TransitionsGroups and Transitions to override zone
507
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899434.aspx
508
+ def end_time_zone!(zone)
509
+ attributes = {}
510
+ attributes['Id'] = zone[:id] if zone[:id]
511
+ attributes['Name'] = zone[:name] if zone[:name]
512
+ nbuild[NS_EWS_TYPES].EndTimeZone(attributes)
513
+ end
514
+
515
+ # Specify a time zone
516
+ # @todo Implement subelements Periods, TransitionsGroups and Transitions to override zone
517
+ # @see http://msdn.microsoft.com/en-us/library/exchange/dd899488.aspx
518
+ def time_zone_definition!(zone)
519
+ attributes = {'Id' => zone[:id]}
520
+ attributes['Name'] = zone[:name] if zone[:name]
521
+ nbuild[NS_EWS_TYPES].TimeZoneDefinition(attributes)
522
+ end
523
+
524
+ # Build the Restriction element
525
+ # @see http://msdn.microsoft.com/en-us/library/aa563791.aspx
526
+ # @param [Hash] restriction a well-formatted Hash that can be fed to #build_xml!
527
+ def restriction!(restriction)
528
+ @nbuild[NS_EWS_MESSAGES].Restriction {
529
+ restriction.each_pair do |k,v|
530
+ self.send normalize_type(k), v
531
+ end
532
+ }
533
+ end
534
+
535
+ def and_r(expr)
536
+ and_or('And', expr)
537
+ end
538
+
539
+ def or_r(expr)
540
+ and_or('Or', expr)
541
+ end
542
+
543
+ def and_or(type, expr)
544
+ @nbuild[NS_EWS_TYPES].send(type) {
545
+ expr.each do |e|
546
+ type = e.keys.first
547
+ self.send normalize_type(type), e[type]
548
+ end
549
+ }
550
+ end
551
+
552
+ def not_r(expr)
553
+ @nbuild[NS_EWS_TYPES].Not {
554
+ type = expr.keys.first
555
+ self.send(type, expr[type])
556
+ }
557
+ end
558
+
559
+ def contains(expr)
560
+ @nbuild[NS_EWS_TYPES].Contains(
561
+ 'ContainmentMode' => expr.delete(:containment_mode),
562
+ 'ContainmentComparison' => expr.delete(:containment_comparison)) {
563
+ c = expr.delete(:constant) # remove constant 1st for ordering
564
+ type = expr.keys.first
565
+ self.send(type, expr[type])
566
+ constant(c)
567
+ }
568
+ end
569
+
570
+ def excludes(expr)
571
+ @nbuild[NS_EWS_TYPES].Excludes {
572
+ b = expr.delete(:bitmask) # remove bitmask 1st for ordering
573
+ type = expr.keys.first
574
+ self.send(type, expr[type])
575
+ bitmask(b)
576
+ }
577
+ end
578
+
579
+ def exists(expr)
580
+ @nbuild[NS_EWS_TYPES].Exists {
581
+ type = expr.keys.first
582
+ self.send(type, expr[type])
583
+ }
584
+ end
585
+
586
+ def bitmask(expr)
587
+ @nbuild[NS_EWS_TYPES].Bitmask('Value' => expr[:value])
588
+ end
589
+
590
+ def is_equal_to(expr)
591
+ restriction_compare('IsEqualTo',expr)
592
+ end
593
+
594
+ def is_greater_than(expr)
595
+ restriction_compare('IsGreaterThan',expr)
596
+ end
597
+
598
+ def is_greater_than_or_equal_to(expr)
599
+ restriction_compare('IsGreaterThanOrEqualTo',expr)
600
+ end
601
+
602
+ def is_less_than(expr)
603
+ restriction_compare('IsLessThan',expr)
604
+ end
605
+
606
+ def is_less_than_or_equal_to(expr)
607
+ restriction_compare('IsLessThanOrEqualTo',expr)
608
+ end
609
+
610
+ def is_not_equal_to(expr)
611
+ restriction_compare('IsNotEqualTo',expr)
612
+ end
613
+
614
+ def restriction_compare(type,expr)
615
+ nbuild[NS_EWS_TYPES].send(type) {
616
+ expr.each do |e|
617
+ e.each_pair do |k,v|
618
+ self.send(k, v)
619
+ end
620
+ end
621
+ }
622
+ end
623
+
624
+ def ews_types_builder
625
+ nbuild[NS_EWS_TYPES]
626
+ end
627
+
628
+ def field_uRI(expr)
629
+ value = expr.is_a?(Hash) ? (expr[:field_uRI] || expr[:field_uri]) : expr
630
+ ews_types_builder.FieldURI('FieldURI' => value)
631
+ end
632
+
633
+ alias_method :field_uri, :field_uRI
634
+
635
+ def indexed_field_uRI(expr)
636
+ nbuild[NS_EWS_TYPES].IndexedFieldURI(
637
+ 'FieldURI' => (expr[:field_uRI] || expr[:field_uri]),
638
+ 'FieldIndex' => expr[:field_index]
639
+ )
640
+ end
641
+
642
+ alias_method :indexed_field_uri, :indexed_field_uRI
643
+
644
+ def extended_field_uRI(expr)
645
+ nbuild[NS_EWS_TYPES].ExtendedFieldURI {
646
+ nbuild.parent['DistinguishedPropertySetId'] = expr[:distinguished_property_set_id] if expr[:distinguished_property_set_id]
647
+ nbuild.parent['PropertySetId'] = expr[:property_set_id] if expr[:property_set_id]
648
+ nbuild.parent['PropertyTag'] = expr[:property_tag] if expr[:property_tag]
649
+ nbuild.parent['PropertyName'] = expr[:property_name] if expr[:property_name]
650
+ nbuild.parent['PropertyId'] = expr[:property_id] if expr[:property_id]
651
+ nbuild.parent['PropertyType'] = expr[:property_type] if expr[:property_type]
652
+ }
653
+ end
654
+
655
+ alias_method :extended_field_uri, :extended_field_uRI
656
+
657
+ def extended_properties!(eprops)
658
+ eprops.each {|ep| extended_property!(ep)}
659
+ end
660
+
661
+ def extended_property!(eprop)
662
+ nbuild[NS_EWS_TYPES].ExtendedProperty {
663
+ key = eprop.keys.grep(/extended/i).first
664
+ dispatch_field_uri!({key => eprop[key]}, NS_EWS_TYPES)
665
+ if eprop[:values]
666
+ nbuild.Values {
667
+ eprop[:values].each do |v|
668
+ value! v
669
+ end
670
+ }
671
+ elsif eprop[:value]
672
+ value! eprop[:value]
673
+ end
674
+ }
675
+ end
676
+
677
+ def value!(val)
678
+ nbuild[NS_EWS_TYPES].Value(val)
679
+ end
680
+
681
+ def field_uRI_or_constant(expr)
682
+ nbuild[NS_EWS_TYPES].FieldURIOrConstant {
683
+ type = expr.keys.first
684
+ self.send(type, expr[type])
685
+ }
686
+ end
687
+
688
+ alias_method :field_uri_or_constant, :field_uRI_or_constant
689
+
690
+ def constant(expr)
691
+ nbuild[NS_EWS_TYPES].Constant('Value' => expr[:value])
692
+ end
693
+
694
+ # Build the CalendarView element
695
+ def calendar_view!(cal_view)
696
+ attribs = {}
697
+ cal_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
698
+ @nbuild[NS_EWS_MESSAGES].CalendarView(attribs)
699
+ end
700
+
701
+ # Build the ContactsView element
702
+ def contacts_view!(con_view)
703
+ attribs = {}
704
+ con_view.each_pair {|k,v| attribs[camel_case(k)] = v.to_s}
705
+ @nbuild[NS_EWS_MESSAGES].ContactsView(attribs)
706
+ end
707
+
708
+ # @see http://msdn.microsoft.com/en-us/library/aa579678(v=EXCHG.140).aspx
709
+ def event_types!(evtypes)
710
+ @nbuild[NS_EWS_TYPES].EventTypes {
711
+ evtypes.each do |et|
712
+ @nbuild[NS_EWS_TYPES].EventType(camel_case(et))
713
+ end
714
+ }
715
+ end
716
+
717
+ # @see http://msdn.microsoft.com/en-us/library/aa565886(v=EXCHG.140).aspx
718
+ def watermark!(wmark, ns = NS_EWS_TYPES)
719
+ @nbuild[ns].Watermark(wmark)
720
+ end
721
+
722
+ # @see http://msdn.microsoft.com/en-us/library/aa565201(v=EXCHG.140).aspx
723
+ def timeout!(tout)
724
+ @nbuild[NS_EWS_TYPES].Timeout(tout)
725
+ end
726
+
727
+ # @see http://msdn.microsoft.com/en-us/library/aa564048(v=EXCHG.140).aspx
728
+ def status_frequency!(freq)
729
+ @nbuild[NS_EWS_TYPES].StatusFrequency(freq)
730
+ end
731
+
732
+ # @see http://msdn.microsoft.com/en-us/library/aa566309(v=EXCHG.140).aspx
733
+ def uRL!(url)
734
+ @nbuild[NS_EWS_TYPES].URL(url)
735
+ end
736
+
737
+ # @see http://msdn.microsoft.com/en-us/library/aa563790(v=EXCHG.140).aspx
738
+ def subscription_id!(subid)
739
+ @nbuild.SubscriptionId(subid)
740
+ end
741
+
742
+ # @see http://msdn.microsoft.com/en-us/library/aa563455(v=EXCHG.140).aspx
743
+ def pull_subscription_request(subopts)
744
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
745
+ @nbuild.PullSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
746
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
747
+ event_types!(subopts[:event_types]) if subopts[:event_types]
748
+ watermark!(subopts[:watermark]) if subopts[:watermark]
749
+ timeout!(subopts[:timeout]) if subopts[:timeout]
750
+ }
751
+ end
752
+
753
+ # @see http://msdn.microsoft.com/en-us/library/aa563599(v=EXCHG.140).aspx
754
+ def push_subscription_request(subopts)
755
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
756
+ @nbuild.PushSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
757
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
758
+ event_types!(subopts[:event_types]) if subopts[:event_types]
759
+ watermark!(subopts[:watermark]) if subopts[:watermark]
760
+ status_frequency!(subopts[:status_frequency]) if subopts[:status_frequency]
761
+ uRL!(subopts[:uRL]) if subopts[:uRL]
762
+ }
763
+ end
764
+
765
+ # @see http://msdn.microsoft.com/en-us/library/ff406182(v=EXCHG.140).aspx
766
+ def streaming_subscription_request(subopts)
767
+ subscribe_all = subopts[:subscribe_to_all_folders] ? 'true' : 'false'
768
+ @nbuild.StreamingSubscriptionRequest('SubscribeToAllFolders' => subscribe_all) {
769
+ folder_ids!(subopts[:folder_ids]) if subopts[:folder_ids]
770
+ event_types!(subopts[:event_types]) if subopts[:event_types]
771
+ }
772
+ end
773
+
774
+ # @see http://msdn.microsoft.com/en-us/library/aa565970(v=EXCHG.140).aspx
775
+ def sync_state!(syncstate)
776
+ @nbuild.SyncState(syncstate)
777
+ end
778
+
779
+ # @see http://msdn.microsoft.com/en-us/library/aa563785(v=EXCHG.140).aspx
780
+ def ignore!(item_ids)
781
+ @nbuild.Ignore {
782
+ item_ids.each do |iid|
783
+ item_id!(iid)
784
+ end
785
+ }
786
+ end
787
+
788
+ # @see http://msdn.microsoft.com/en-us/library/aa566325(v=EXCHG.140).aspx
789
+ def max_changes_returned!(cnum)
790
+ @nbuild[NS_EWS_MESSAGES].MaxChangesReturned(cnum)
791
+ end
792
+
793
+ # @see http://msdn.microsoft.com/en-us/library/dd899531(v=EXCHG.140).aspx
794
+ def sync_scope!(scope)
795
+ @nbuild.SyncScope(scope)
796
+ end
797
+
798
+ # @see http://msdn.microsoft.com/en-us/library/aa580758(v=EXCHG.140).aspx
799
+ def saved_item_folder_id!(fid)
800
+ @nbuild.SavedItemFolderId {
801
+ dispatch_folder_id!(fid)
802
+ }
803
+ end
804
+
805
+ # @see http://msdn.microsoft.com/en-us/library/aa565652(v=exchg.140).aspx
806
+ def item!(item)
807
+ nbuild.Item {
808
+ item.each_pair {|k,v|
809
+ self.send("#{k}!", v)
810
+ }
811
+ }
812
+ end
813
+
814
+ def message!(item)
815
+ nbuild[NS_EWS_TYPES].Message {
816
+ if item[:extended_properties]
817
+ extended_properties! item.delete(:extended_properties)
818
+ end
819
+ item.each_pair {|k,v|
820
+ self.send("#{k}!", v)
821
+ }
822
+ }
823
+ end
824
+
825
+ def categories!(categories)
826
+ nbuild[NS_EWS_TYPES].Categories {
827
+ categories.each do |c|
828
+ nbuild[NS_EWS_TYPES].String(c)
829
+ end
830
+ }
831
+ end
832
+
833
+ def is_from_me!(ans)
834
+ return unless ans
835
+
836
+ nbuild[NS_EWS_TYPES].IsFromMe
837
+ end
838
+
839
+ def mime_content!(mime_content)
840
+ @nbuild[NS_EWS_TYPES].MimeContent(mime_content)
841
+ end
842
+
843
+ def is_read!(read)
844
+ nbuild[NS_EWS_TYPES].IsRead(read)
845
+ end
846
+
847
+ def calendar_item!(item)
848
+ nbuild[NS_EWS_TYPES].CalendarItem {
849
+ item.each_pair {|k,v|
850
+ self.send("#{k}!", v)
851
+ }
852
+ }
853
+ end
854
+
855
+ def calendar_item_type!(type)
856
+ nbuild[NS_EWS_TYPES].CalendarItemType(type)
857
+ end
858
+
859
+ def recurrence!(item)
860
+ nbuild[NS_EWS_TYPES].Recurrence {
861
+ item.each_pair { |k, v|
862
+ self.send("#{k}!", v)
863
+ }
864
+ }
865
+ end
866
+
867
+ def daily_recurrence!(item)
868
+ nbuild[NS_EWS_TYPES].DailyRecurrence {
869
+ item.each_pair { |k, v|
870
+ self.send("#{k}!", v)
871
+ }
872
+ }
873
+ end
874
+
875
+ def weekly_recurrence!(item)
876
+ nbuild[NS_EWS_TYPES].WeeklyRecurrence {
877
+ item.each_pair { |k, v|
878
+ self.send("#{k}!", v)
879
+ }
880
+ }
881
+ end
882
+
883
+ def interval!(num)
884
+ nbuild[NS_EWS_TYPES].Interval(num)
885
+ end
886
+
887
+ def no_end_recurrence!(item)
888
+ nbuild[NS_EWS_TYPES].NoEndRecurrence {
889
+ item.each_pair { |k, v|
890
+ self.send("#{k}!", v)
891
+ }
892
+ }
893
+ end
894
+
895
+ def numbered_recurrence!(item)
896
+ nbuild[NS_EWS_TYPES].NumberedRecurrence {
897
+ item.each_pair { |k, v|
898
+ self.send("#{k}!", v)
899
+ }
900
+ }
901
+ end
902
+
903
+ def number_of_occurrences!(count)
904
+ nbuild[NS_EWS_TYPES].NumberOfOccurrences(count)
905
+ end
906
+
907
+
908
+ def task!(item)
909
+ nbuild[NS_EWS_TYPES].Task {
910
+ item.each_pair {|k, v|
911
+ self.send("#{k}!", v)
912
+ }
913
+ }
914
+ end
915
+
916
+ def forward_item!(item)
917
+ nbuild[NS_EWS_TYPES].ForwardItem {
918
+ item.each_pair {|k,v|
919
+ self.send("#{k}!", v)
920
+ }
921
+ }
922
+ end
923
+
924
+ def reply_to_item!(item)
925
+ nbuild[NS_EWS_TYPES].ReplyToItem {
926
+ item.each_pair {|k,v|
927
+ self.send("#{k}!", v)
928
+ }
929
+ }
930
+ end
931
+
932
+ def reply_all_to_item!(item)
933
+ nbuild[NS_EWS_TYPES].ReplyAllToItem {
934
+ item.each_pair {|k,v|
935
+ self.send("#{k}!", v)
936
+ }
937
+ }
938
+ end
939
+
940
+ def reference_item_id!(id)
941
+ nbuild[NS_EWS_TYPES].ReferenceItemId {|x|
942
+ x.parent['Id'] = id[:id]
943
+ x.parent['ChangeKey'] = id[:change_key] if id[:change_key]
944
+ }
945
+ end
946
+
947
+ def subject!(sub)
948
+ nbuild[NS_EWS_TYPES].Subject(sub)
949
+ end
950
+
951
+ def importance!(sub)
952
+ nbuild[NS_EWS_TYPES].Importance(sub)
953
+ end
954
+
955
+ def body!(b)
956
+ nbuild[NS_EWS_TYPES].Body(b[:text]) {|x|
957
+ x.parent['BodyType'] = b[:body_type] if b[:body_type]
958
+ }
959
+ end
960
+
961
+ def new_body_content!(b)
962
+ nbuild[NS_EWS_TYPES].NewBodyContent(b[:text]) {|x|
963
+ x.parent['BodyType'] = b[:body_type] if b[:body_type]
964
+ }
965
+ end
966
+
967
+ # @see http://msdn.microsoft.com/en-us/library/aa563719(v=exchg.140).aspx
968
+ # @param [Array] r An array of Mailbox type hashes to send to #mailbox!
969
+ def to_recipients!(r)
970
+ nbuild[NS_EWS_TYPES].ToRecipients {
971
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
972
+ }
973
+ end
974
+
975
+ def cc_recipients!(r)
976
+ nbuild[NS_EWS_TYPES].CcRecipients {
977
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
978
+ }
979
+ end
980
+
981
+ def bcc_recipients!(r)
982
+ nbuild[NS_EWS_TYPES].BccRecipients {
983
+ r.each {|mbox| mailbox!(mbox[:mailbox]) }
984
+ }
985
+ end
986
+
987
+ def from!(f)
988
+ nbuild[NS_EWS_TYPES].From {
989
+ mailbox! f[:mailbox]
990
+ }
991
+ end
992
+
993
+ def sender!(f)
994
+ nbuild[NS_EWS_TYPES].Sender {
995
+ mailbox! f[:mailbox]
996
+ }
997
+ end
998
+
999
+ def required_attendees!(attendees)
1000
+ nbuild[NS_EWS_TYPES].RequiredAttendees {
1001
+ attendees.each {|a| attendee!(a[:attendee])}
1002
+ }
1003
+ end
1004
+
1005
+ def optional_attendees!(attendees)
1006
+ nbuild[NS_EWS_TYPES].OptionalAttendees {
1007
+ attendees.each {|a| attendee!(a[:attendee])}
1008
+ }
1009
+ end
1010
+
1011
+ def resources!(attendees)
1012
+ nbuild[NS_EWS_TYPES].Resources {
1013
+ attendees.each {|a| attendee!(a[:attendee])}
1014
+ }
1015
+ end
1016
+
1017
+ # @todo support ResponseType, LastResponseTime: http://msdn.microsoft.com/en-us/library/aa580339.aspx
1018
+ def attendee!(a)
1019
+ nbuild[NS_EWS_TYPES].Attendee {
1020
+ mailbox!(a[:mailbox])
1021
+ }
1022
+ end
1023
+
1024
+ def start!(st)
1025
+ nbuild[NS_EWS_TYPES].Start(st[:text])
1026
+ end
1027
+
1028
+ def end!(et)
1029
+ nbuild[NS_EWS_TYPES].End(et[:text])
1030
+ end
1031
+
1032
+ def start_date!(sd)
1033
+ nbuild[NS_EWS_TYPES].StartDate sd[:text]
1034
+ end
1035
+
1036
+ def due_date!(dd)
1037
+ nbuild[NS_EWS_TYPES].DueDate format_time(dd[:text])
1038
+ end
1039
+
1040
+ def location!(loc)
1041
+ nbuild[NS_EWS_TYPES].Location(loc)
1042
+ end
1043
+
1044
+ def is_all_day_event!(all_day)
1045
+ nbuild[NS_EWS_TYPES].IsAllDayEvent(all_day)
1046
+ end
1047
+
1048
+ def is_response_requested!(response_requested)
1049
+ nbuild[NS_EWS_TYPES].IsResponseRequested(response_requested)
1050
+ end
1051
+
1052
+ def reminder_is_set!(reminder)
1053
+ nbuild[NS_EWS_TYPES].ReminderIsSet reminder
1054
+ end
1055
+
1056
+ def reminder_due_by!(date)
1057
+ nbuild[NS_EWS_TYPES].ReminderDueBy format_time(date)
1058
+ end
1059
+
1060
+ def reminder_minutes_before_start!(minutes)
1061
+ nbuild[NS_EWS_TYPES].ReminderMinutesBeforeStart minutes
1062
+ end
1063
+
1064
+ # @see http://msdn.microsoft.com/en-us/library/aa566143(v=exchg.150).aspx
1065
+ # possible values Exchange Server 2010 = [Free, Tentative, Busy, OOF, NoData]
1066
+ # Exchange Server 2013 = [Free, Tentative, Busy, OOF, WorkingElsewhere, NoData]
1067
+ def legacy_free_busy_status!(state)
1068
+ nbuild[NS_EWS_TYPES].LegacyFreeBusyStatus(state)
1069
+ end
1070
+
1071
+ # @see http://msdn.microsoft.com/en-us/library/aa565428(v=exchg.140).aspx
1072
+ def item_changes!(changes)
1073
+ nbuild.ItemChanges {
1074
+ changes.each do |chg|
1075
+ item_change!(chg)
1076
+ end
1077
+ }
1078
+ end
1079
+
1080
+ # @see http://msdn.microsoft.com/en-us/library/aa581081(v=exchg.140).aspx
1081
+ def item_change!(change)
1082
+ @nbuild[NS_EWS_TYPES].ItemChange {
1083
+ updates = change.delete(:updates) # Remove updates so dispatch_item_id works correctly
1084
+ dispatch_item_id!(change)
1085
+ updates!(updates)
1086
+ }
1087
+ end
1088
+
1089
+ # @see http://msdn.microsoft.com/en-us/library/aa581074(v=exchg.140).aspx
1090
+ def updates!(updates)
1091
+ @nbuild[NS_EWS_TYPES].Updates {
1092
+ updates.each do |update|
1093
+ dispatch_update_type!(update)
1094
+ end
1095
+ }
1096
+ end
1097
+
1098
+ # @see http://msdn.microsoft.com/en-us/library/aa581317(v=exchg.140).aspx
1099
+ def append_to_item_field!(upd)
1100
+ uri = upd.select {|k,v| k =~ /_uri/i}
1101
+ raise EwsBadArgumentError, "Bad argument given for AppendToItemField." if uri.keys.length != 1
1102
+ upd.delete(uri.keys.first)
1103
+ @nbuild.AppendToItemField {
1104
+ dispatch_field_uri!(uri)
1105
+ dispatch_field_item!(upd)
1106
+ }
1107
+ end
1108
+
1109
+ # @see http://msdn.microsoft.com/en-us/library/aa581487(v=exchg.140).aspx
1110
+ def set_item_field!(upd)
1111
+ uri = upd.select {|k,v| k =~ /_uri/i}
1112
+ raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
1113
+ upd.delete(uri.keys.first)
1114
+ @nbuild[NS_EWS_TYPES].SetItemField {
1115
+ dispatch_field_uri!(uri, NS_EWS_TYPES)
1116
+ dispatch_field_item!(upd, NS_EWS_TYPES)
1117
+ }
1118
+ end
1119
+
1120
+ # @see http://msdn.microsoft.com/en-us/library/aa580330(v=exchg.140).aspx
1121
+ def delete_item_field!(upd)
1122
+ uri = upd.select {|k,v| k =~ /_uri/i}
1123
+ raise EwsBadArgumentError, "Bad argument given for SetItemField." if uri.keys.length != 1
1124
+ @nbuild[NS_EWS_TYPES].DeleteItemField {
1125
+ dispatch_field_uri!(uri, NS_EWS_TYPES)
1126
+ }
1127
+ end
1128
+
1129
+ # @see http://msdn.microsoft.com/en-us/library/ff709497(v=exchg.140).aspx
1130
+ def return_new_item_ids!(retval)
1131
+ @nbuild.ReturnNewItemIds(retval)
1132
+ end
1133
+
1134
+ def inline_attachment!(fa)
1135
+ @nbuild[NS_EWS_TYPES].FileAttachment {
1136
+ @nbuild[NS_EWS_TYPES].Name(fa.name)
1137
+ @nbuild[NS_EWS_TYPES].ContentId(fa.name)
1138
+ @nbuild[NS_EWS_TYPES].IsInline(true)
1139
+ @nbuild[NS_EWS_TYPES].Content(fa.content)
1140
+ }
1141
+ end
1142
+
1143
+ def file_attachment!(fa)
1144
+ @nbuild[NS_EWS_TYPES].FileAttachment {
1145
+ @nbuild[NS_EWS_TYPES].Name(fa.name)
1146
+ @nbuild[NS_EWS_TYPES].Content(fa.content)
1147
+ }
1148
+ end
1149
+
1150
+ def item_attachment!(ia)
1151
+ @nbuild[NS_EWS_TYPES].ItemAttachment {
1152
+ @nbuild[NS_EWS_TYPES].Name(ia.name)
1153
+ @nbuild[NS_EWS_TYPES].Item {
1154
+ item_id!(ia.item)
1155
+ }
1156
+ }
1157
+ end
1158
+
1159
+ # Build the AttachmentIds element
1160
+ # @see http://msdn.microsoft.com/en-us/library/aa580686.aspx
1161
+ def attachment_ids!(aids)
1162
+ @nbuild.AttachmentIds {
1163
+ @nbuild.parent.default_namespace = @default_ns
1164
+ aids.each do |aid|
1165
+ attachment_id!(aid)
1166
+ end
1167
+ }
1168
+ end
1169
+
1170
+ # Build the AttachmentId element
1171
+ # @see http://msdn.microsoft.com/en-us/library/aa580764.aspx
1172
+ def attachment_id!(aid)
1173
+ attribs = {'Id' => aid}
1174
+ @nbuild[NS_EWS_TYPES].AttachmentId(attribs)
1175
+ end
1176
+
1177
+ def user_configuration_name!(cfg_name)
1178
+ attribs = {'Name' => cfg_name.delete(:name)}
1179
+ @nbuild[NS_EWS_MESSAGES].UserConfigurationName(attribs) {
1180
+ fid = cfg_name.keys.first
1181
+ self.send "#{fid}!", cfg_name[fid][:id], cfg_name[fid][:change_key]
1182
+ }
1183
+ end
1184
+
1185
+ def user_configuration_properties!(cfg_prop)
1186
+ @nbuild[NS_EWS_MESSAGES].UserConfigurationProperties(cfg_prop)
1187
+ end
1188
+
1189
+ # ---------------------- Helpers -------------------- #
1190
+
1191
+ # A helper method to dispatch to a FolderId or DistinguishedFolderId correctly
1192
+ # @param [Hash] fid A folder_id
1193
+ # Ex: {:id => myid, :change_key => ck}
1194
+ def dispatch_folder_id!(fid)
1195
+ if(fid[:id].is_a?(String))
1196
+ folder_id!(fid[:id], fid[:change_key])
1197
+ elsif(fid[:id].is_a?(Symbol))
1198
+ distinguished_folder_id!(fid[:id], fid[:change_key], fid[:act_as])
1199
+ else
1200
+ raise EwsBadArgumentError, "Bad argument given for a FolderId. #{fid[:id].class}"
1201
+ end
1202
+ end
1203
+
1204
+ # A helper method to dispatch to an ItemId, OccurrenceItemId, or a RecurringMasterItemId
1205
+ # @param [Hash] iid The item id of some type
1206
+ def dispatch_item_id!(iid)
1207
+ type = iid.keys.first
1208
+ item = iid[type]
1209
+ case type
1210
+ when :item_id
1211
+ item_id!(item)
1212
+ when :occurrence_item_id
1213
+ occurrence_item_id!(item)
1214
+ when :recurring_master_item_id
1215
+ recurring_master_item_id!(item)
1216
+ else
1217
+ raise EwsBadArgumentError, "Bad ItemId type. #{type}"
1218
+ end
1219
+ end
1220
+
1221
+ # A helper method to dispatch to a AppendToItemField, SetItemField, or
1222
+ # DeleteItemField
1223
+ # @param [Hash] update An update of some type
1224
+ def dispatch_update_type!(update)
1225
+ type = update.keys.first
1226
+ upd = update[type]
1227
+ case type
1228
+ when :append_to_item_field
1229
+ append_to_item_field!(upd)
1230
+ when :set_item_field
1231
+ set_item_field!(upd)
1232
+ when :delete_item_field
1233
+ delete_item_field!(upd)
1234
+ else
1235
+ raise EwsBadArgumentError, "Bad Update type. #{type}"
1236
+ end
1237
+ end
1238
+
1239
+ # A helper to dispatch to a FieldURI, IndexedFieldURI, or an ExtendedFieldURI
1240
+ # @todo Implement ExtendedFieldURI
1241
+ def dispatch_field_uri!(uri, ns=NS_EWS_MESSAGES)
1242
+ type = uri.keys.first
1243
+ vals = uri[type].is_a?(Array) ? uri[type] : [uri[type]]
1244
+ case type
1245
+ when :field_uRI, :field_uri
1246
+ vals.each do |val|
1247
+ value = val.is_a?(Hash) ? val[type] : val
1248
+ nbuild[ns].FieldURI('FieldURI' => value)
1249
+ end
1250
+ when :indexed_field_uRI, :indexed_field_uri
1251
+ vals.each do |val|
1252
+ nbuild[ns].IndexedFieldURI(
1253
+ 'FieldURI' => (val[:field_uRI] || val[:field_uri]),
1254
+ 'FieldIndex' => val[:field_index]
1255
+ )
1256
+ end
1257
+ when :extended_field_uRI, :extended_field_uri
1258
+ vals.each do |val|
1259
+ nbuild[ns].ExtendedFieldURI {
1260
+ nbuild.parent['DistinguishedPropertySetId'] = val[:distinguished_property_set_id] if val[:distinguished_property_set_id]
1261
+ nbuild.parent['PropertySetId'] = val[:property_set_id] if val[:property_set_id]
1262
+ nbuild.parent['PropertyTag'] = val[:property_tag] if val[:property_tag]
1263
+ nbuild.parent['PropertyName'] = val[:property_name] if val[:property_name]
1264
+ nbuild.parent['PropertyId'] = val[:property_id] if val[:property_id]
1265
+ nbuild.parent['PropertyType'] = val[:property_type] if val[:property_type]
1266
+ }
1267
+ end
1268
+ else
1269
+ raise EwsBadArgumentError, "Bad URI type. #{type}"
1270
+ end
1271
+ end
1272
+
1273
+ # Insert item, enforce xmlns attribute if prefix is present
1274
+ def dispatch_field_item!(item, ns_prefix = nil)
1275
+ item.values.first[:xmlns_attribute] = ns_prefix if ns_prefix
1276
+ build_xml!(item)
1277
+ end
1278
+
1279
+ def room_list!(cfg_prop)
1280
+ @nbuild[NS_EWS_MESSAGES].RoomList {
1281
+ email_address!(cfg_prop)
1282
+ }
1283
+ end
1284
+
1285
+ def room_lists!
1286
+ @nbuild[NS_EWS_MESSAGES].GetRoomLists
1287
+ end
1288
+
1289
+ def accept_item!(opts)
1290
+ @nbuild[NS_EWS_TYPES].AcceptItem {
1291
+ sensitivity!(opts)
1292
+ body!(opts) if opts[:text]
1293
+ reference_item_id!(opts)
1294
+ }
1295
+ end
1296
+
1297
+ def tentatively_accept_item!(opts)
1298
+ @nbuild[NS_EWS_TYPES].TentativelyAcceptItem {
1299
+ sensitivity!(opts)
1300
+ body!(opts) if opts[:text]
1301
+ reference_item_id!(opts)
1302
+ }
1303
+ end
1304
+
1305
+ def decline_item!(opts)
1306
+ @nbuild[NS_EWS_TYPES].DeclineItem {
1307
+ sensitivity!(opts)
1308
+ body!(opts) if opts[:text]
1309
+ reference_item_id!(opts)
1310
+ }
1311
+ end
1312
+
1313
+ def sensitivity!(value)
1314
+ nbuild[NS_EWS_TYPES].Sensitivity(value[:sensitivity])
1315
+ end
1316
+
1317
+ private
1318
+
1319
+ def parent_namespace(node)
1320
+ node.parent.namespace_definitions.find {|ns| ns.prefix == NS_SOAP}
1321
+ end
1322
+
1323
+ def set_version_header!(version)
1324
+ if version && !(version == 'none')
1325
+ nbuild[NS_EWS_TYPES].RequestServerVersion {|x|
1326
+ x.parent['Version'] = version
1327
+ }
1328
+ end
1329
+ end
1330
+
1331
+ def set_impersonation!(type, address)
1332
+ if type && type != ""
1333
+ nbuild[NS_EWS_TYPES].ExchangeImpersonation {
1334
+ nbuild[NS_EWS_TYPES].ConnectingSID {
1335
+ nbuild[NS_EWS_TYPES].method_missing type, address
1336
+ }
1337
+ }
1338
+ end
1339
+ end
1340
+
1341
+ # Set TimeZoneContext Header
1342
+ # @param time_zone_def [Hash] !{id: time_zone_identifier, name: time_zone_name}
1343
+ def set_time_zone_context_header!(time_zone_def)
1344
+ if time_zone_def
1345
+ nbuild[NS_EWS_TYPES].TimeZoneContext do
1346
+ time_zone_definition! time_zone_def
1347
+ end
1348
+ end
1349
+ end
1350
+
1351
+ def meeting_time_zone!(mtz)
1352
+ nbuild[NS_EWS_TYPES].MeetingTimeZone do |x|
1353
+ x.parent['TimeZoneName'] = mtz[:time_zone_name] if mtz[:time_zone_name]
1354
+ nbuild[NS_EWS_TYPES].BaseOffset(mtz[:base_offset][:text]) if mtz[:base_offset]
1355
+ end
1356
+ end
1357
+
1358
+ # some methods need special naming so they use the '_r' suffix like 'and'
1359
+ def normalize_type(type)
1360
+ case type
1361
+ when :and, :or, :not
1362
+ "#{type}_r".to_sym
1363
+ else
1364
+ type
1365
+ end
1366
+ end
1367
+
1368
+ def format_time(time)
1369
+ case time
1370
+ when Time, Date, DateTime
1371
+ time.to_datetime.new_offset(0).iso8601
1372
+ when String
1373
+ begin
1374
+ DateTime.parse(time).new_offset(0).iso8601
1375
+ rescue ArgumentError
1376
+ raise EwsBadArgumentError, "Invalid Time argument (#{time})"
1377
+ end
1378
+ else
1379
+ raise EwsBadArgumentError, "Invalid Time argument (#{time})"
1380
+ end
1381
+ end
1382
+
1383
+ end # EwsBuilder
1384
+ end # Viewpoint::EWS::SOAP