sfdcvp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/Changelog.txt +1004 -0
- data/README.md +201 -0
- data/TODO +17 -0
- data/lib/ews/calendar_accessors.rb +34 -0
- data/lib/ews/connection.rb +126 -0
- data/lib/ews/connection_helper.rb +35 -0
- data/lib/ews/convert_accessors.rb +56 -0
- data/lib/ews/errors.rb +56 -0
- data/lib/ews/ews_client.rb +101 -0
- data/lib/ews/exceptions/exceptions.rb +61 -0
- data/lib/ews/folder_accessors.rb +264 -0
- data/lib/ews/impersonation.rb +30 -0
- data/lib/ews/item_accessors.rb +231 -0
- data/lib/ews/mailbox_accessors.rb +92 -0
- data/lib/ews/message_accessors.rb +93 -0
- data/lib/ews/push_subscription_accessors.rb +33 -0
- data/lib/ews/room_accessors.rb +48 -0
- data/lib/ews/roomlist_accessors.rb +47 -0
- data/lib/ews/soap.rb +64 -0
- data/lib/ews/soap/builders/ews_builder.rb +1361 -0
- data/lib/ews/soap/ews_response.rb +84 -0
- data/lib/ews/soap/ews_soap_availability_response.rb +58 -0
- data/lib/ews/soap/ews_soap_free_busy_response.rb +119 -0
- data/lib/ews/soap/ews_soap_response.rb +103 -0
- data/lib/ews/soap/ews_soap_room_response.rb +53 -0
- data/lib/ews/soap/ews_soap_roomlist_response.rb +54 -0
- data/lib/ews/soap/exchange_availability.rb +61 -0
- data/lib/ews/soap/exchange_data_services.rb +780 -0
- data/lib/ews/soap/exchange_notification.rb +146 -0
- data/lib/ews/soap/exchange_synchronization.rb +93 -0
- data/lib/ews/soap/exchange_time_zones.rb +56 -0
- data/lib/ews/soap/exchange_user_configuration.rb +33 -0
- data/lib/ews/soap/exchange_web_service.rb +264 -0
- data/lib/ews/soap/parsers/ews_parser.rb +43 -0
- data/lib/ews/soap/parsers/ews_sax_document.rb +70 -0
- data/lib/ews/soap/response_message.rb +80 -0
- data/lib/ews/soap/responses/create_attachment_response_message.rb +47 -0
- data/lib/ews/soap/responses/create_item_response_message.rb +25 -0
- data/lib/ews/soap/responses/find_item_response_message.rb +80 -0
- data/lib/ews/soap/responses/get_events_response_message.rb +53 -0
- data/lib/ews/soap/responses/send_notification_response_message.rb +59 -0
- data/lib/ews/soap/responses/subscribe_response_message.rb +35 -0
- data/lib/ews/soap/responses/sync_folder_hierarchy_response_message.rb +36 -0
- data/lib/ews/soap/responses/sync_folder_items_response_message.rb +36 -0
- data/lib/ews/templates/calendar_item.rb +78 -0
- data/lib/ews/templates/forward_item.rb +24 -0
- data/lib/ews/templates/message.rb +73 -0
- data/lib/ews/templates/reply_to_item.rb +25 -0
- data/lib/ews/templates/task.rb +74 -0
- data/lib/ews/types.rb +194 -0
- data/lib/ews/types/attachment.rb +77 -0
- data/lib/ews/types/attendee.rb +27 -0
- data/lib/ews/types/calendar_folder.rb +50 -0
- data/lib/ews/types/calendar_item.rb +129 -0
- data/lib/ews/types/contact.rb +7 -0
- data/lib/ews/types/contacts_folder.rb +8 -0
- data/lib/ews/types/copied_event.rb +51 -0
- data/lib/ews/types/created_event.rb +24 -0
- data/lib/ews/types/deleted_event.rb +24 -0
- data/lib/ews/types/distribution_list.rb +7 -0
- data/lib/ews/types/event.rb +62 -0
- data/lib/ews/types/export_items_response_message.rb +52 -0
- data/lib/ews/types/file_attachment.rb +65 -0
- data/lib/ews/types/folder.rb +60 -0
- data/lib/ews/types/free_busy_changed_event.rb +24 -0
- data/lib/ews/types/generic_folder.rb +420 -0
- data/lib/ews/types/item.rb +442 -0
- data/lib/ews/types/item_attachment.rb +84 -0
- data/lib/ews/types/item_field_uri_map.rb +224 -0
- data/lib/ews/types/mailbox_user.rb +156 -0
- data/lib/ews/types/meeting_cancellation.rb +7 -0
- data/lib/ews/types/meeting_message.rb +7 -0
- data/lib/ews/types/meeting_request.rb +7 -0
- data/lib/ews/types/meeting_response.rb +7 -0
- data/lib/ews/types/message.rb +7 -0
- data/lib/ews/types/modified_event.rb +48 -0
- data/lib/ews/types/moved_event.rb +51 -0
- data/lib/ews/types/new_mail_event.rb +24 -0
- data/lib/ews/types/out_of_office.rb +147 -0
- data/lib/ews/types/search_folder.rb +8 -0
- data/lib/ews/types/status_event.rb +39 -0
- data/lib/ews/types/task.rb +37 -0
- data/lib/ews/types/tasks_folder.rb +27 -0
- data/lib/sfdcvp.rb +109 -0
- data/lib/viewpoint/logging.rb +27 -0
- data/lib/viewpoint/logging/config.rb +24 -0
- data/lib/viewpoint/string_utils.rb +76 -0
- metadata +190 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module Viewpoint::EWS::Types
|
2
|
+
|
3
|
+
class ExportItemsResponseMessage
|
4
|
+
include Viewpoint::EWS
|
5
|
+
include Viewpoint::EWS::Types
|
6
|
+
include Viewpoint::EWS::Types::Item
|
7
|
+
|
8
|
+
BULK_KEY_PATHS = {
|
9
|
+
:id => [:item_id, :attribs, :id],
|
10
|
+
:change_key => [:item_id, :attribs, :change_key],
|
11
|
+
:data => [:data, :text]
|
12
|
+
}
|
13
|
+
|
14
|
+
BULK_KEY_TYPES = { }
|
15
|
+
|
16
|
+
BULK_KEY_ALIAS = { }
|
17
|
+
|
18
|
+
def initialize(ews, bulk_item)
|
19
|
+
super(ews, bulk_item)
|
20
|
+
@item = bulk_item
|
21
|
+
@ews = ews
|
22
|
+
end
|
23
|
+
|
24
|
+
def id
|
25
|
+
@item[:item_id][:attribs][:id]
|
26
|
+
end
|
27
|
+
|
28
|
+
def change_key
|
29
|
+
@item[:item_id][:attribs][:change_key]
|
30
|
+
end
|
31
|
+
|
32
|
+
def data
|
33
|
+
@item[:data][:text]
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def key_paths
|
40
|
+
@key_paths ||= BULK_KEY_PATHS
|
41
|
+
end
|
42
|
+
|
43
|
+
def key_types
|
44
|
+
@key_types ||= BULK_KEY_TYPES
|
45
|
+
end
|
46
|
+
|
47
|
+
def key_alias
|
48
|
+
@key_alias ||= BULK_KEY_ALIAS
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
=begin
|
2
|
+
This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
|
3
|
+
|
4
|
+
Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
|
5
|
+
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
you may not use this file except in compliance with the License.
|
8
|
+
You may obtain a copy of the License at
|
9
|
+
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
See the License for the specific language governing permissions and
|
16
|
+
limitations under the License.
|
17
|
+
=end
|
18
|
+
|
19
|
+
module Viewpoint::EWS::Types
|
20
|
+
class FileAttachment < Attachment
|
21
|
+
|
22
|
+
FILE_ATTACH_KEY_PATHS = {
|
23
|
+
:is_contact_photo? => [:is_contact_photo, :text],
|
24
|
+
:content => [:content, :text],
|
25
|
+
}
|
26
|
+
|
27
|
+
FILE_ATTACH_KEY_TYPES = {
|
28
|
+
is_contact_photo?: ->(str){str.downcase == 'true'},
|
29
|
+
}
|
30
|
+
|
31
|
+
FILE_ATTACH_KEY_ALIAS = {
|
32
|
+
:file_name => :name,
|
33
|
+
}
|
34
|
+
|
35
|
+
def get_all_properties!
|
36
|
+
resp = ews.get_attachment attachment_ids: [self.id]
|
37
|
+
@ews_item.merge!(parse_response(resp))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
|
43
|
+
def key_paths
|
44
|
+
super.merge(FILE_ATTACH_KEY_PATHS)
|
45
|
+
end
|
46
|
+
|
47
|
+
def key_types
|
48
|
+
super.merge(FILE_ATTACH_KEY_TYPES)
|
49
|
+
end
|
50
|
+
|
51
|
+
def key_alias
|
52
|
+
super.merge(FILE_ATTACH_KEY_ALIAS)
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_response(resp)
|
56
|
+
if(resp.status == 'Success')
|
57
|
+
resp.response_message[:elems][:attachments][:elems][0][:file_attachment][:elems].inject(&:merge)
|
58
|
+
else
|
59
|
+
raise EwsError, "Could not retrieve #{self.class}. #{resp.code}: #{resp.message}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Viewpoint::EWS::Types
|
2
|
+
class Folder
|
3
|
+
include Viewpoint::EWS
|
4
|
+
include Viewpoint::EWS::Types
|
5
|
+
include Viewpoint::EWS::Types::GenericFolder
|
6
|
+
|
7
|
+
FOLDER_KEY_PATHS = {
|
8
|
+
:unread_count => [:unread_count, :text],
|
9
|
+
}
|
10
|
+
FOLDER_KEY_TYPES = {
|
11
|
+
:unread_count => ->(str){str.to_i},
|
12
|
+
}
|
13
|
+
FOLDER_KEY_ALIAS = {}
|
14
|
+
|
15
|
+
alias :messages :items
|
16
|
+
|
17
|
+
def unread_messages
|
18
|
+
self.items read_unread_restriction
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_messages
|
22
|
+
self.items read_unread_restriction(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
def messages_with_attachments
|
26
|
+
opts = {:restriction =>
|
27
|
+
{:is_equal_to => [
|
28
|
+
{:field_uRI => {:field_uRI=>'item:HasAttachments'}},
|
29
|
+
{:field_uRI_or_constant => {:constant => {:value=> true}}}
|
30
|
+
]}
|
31
|
+
}
|
32
|
+
self.items opts
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
|
38
|
+
def read_unread_restriction(read = false)
|
39
|
+
{:restriction =>
|
40
|
+
{:is_equal_to => [
|
41
|
+
{:field_uRI => {:field_uRI=>'message:IsRead'}},
|
42
|
+
{:field_uRI_or_constant => {:constant => {:value=> read}}}
|
43
|
+
]}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def key_paths
|
48
|
+
@key_paths ||= super.merge(FOLDER_KEY_PATHS)
|
49
|
+
end
|
50
|
+
|
51
|
+
def key_types
|
52
|
+
@key_types ||= super.merge(FOLDER_KEY_TYPES)
|
53
|
+
end
|
54
|
+
|
55
|
+
def key_alias
|
56
|
+
@key_alias ||= super.merge(FOLDER_KEY_ALIAS)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
=begin
|
2
|
+
This file is part of Viewpoint; the Ruby library for Microsoft Exchange Web Services.
|
3
|
+
|
4
|
+
Copyright © 2011 Dan Wanek <dan.wanek@gmail.com>
|
5
|
+
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
you may not use this file except in compliance with the License.
|
8
|
+
You may obtain a copy of the License at
|
9
|
+
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
See the License for the specific language governing permissions and
|
16
|
+
limitations under the License.
|
17
|
+
=end
|
18
|
+
|
19
|
+
module Viewpoint::EWS::Types
|
20
|
+
|
21
|
+
class FreeBusyChangedEvent < Event
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,420 @@
|
|
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
|
+
require 'ews/item_accessors'
|
20
|
+
|
21
|
+
module Viewpoint::EWS::Types
|
22
|
+
module GenericFolder
|
23
|
+
include Viewpoint::EWS
|
24
|
+
include Viewpoint::EWS::Types
|
25
|
+
include Viewpoint::EWS::ItemAccessors
|
26
|
+
include Viewpoint::StringUtils
|
27
|
+
|
28
|
+
GFOLDER_KEY_PATHS = {
|
29
|
+
:folder_id => [:folder_id, :attribs],
|
30
|
+
:id => [:folder_id, :attribs, :id],
|
31
|
+
:change_key => [:folder_id, :attribs, :change_key],
|
32
|
+
:parent_folder_id => [:parent_folder_id, :attribs, :id],
|
33
|
+
:parent_folder_change_key => [:parent_folder_id, :attribs, :change_key],
|
34
|
+
:folder_class => [:folder_class, :text],
|
35
|
+
:total_count => [:total_count, :text],
|
36
|
+
:child_folder_count => [:child_folder_count, :text],
|
37
|
+
:display_name => [:display_name, :text],
|
38
|
+
}
|
39
|
+
|
40
|
+
GFOLDER_KEY_TYPES = {
|
41
|
+
:total_count => ->(str){str.to_i},
|
42
|
+
:child_folder_count => ->(str){str.to_i},
|
43
|
+
}
|
44
|
+
|
45
|
+
GFOLDER_KEY_ALIAS = {
|
46
|
+
:name => :display_name,
|
47
|
+
:ckey => :change_key,
|
48
|
+
}
|
49
|
+
|
50
|
+
attr_accessor :subscription_id, :watermark, :sync_state
|
51
|
+
|
52
|
+
# @param [SOAP::ExchangeWebService] ews the EWS reference
|
53
|
+
# @param [Hash] ews_item the EWS parsed response document
|
54
|
+
def initialize(ews, ews_item)
|
55
|
+
super
|
56
|
+
simplify!
|
57
|
+
@sync_state = nil
|
58
|
+
@synced = false
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete!
|
62
|
+
opts = {
|
63
|
+
:folder_ids => [:id => id],
|
64
|
+
:delete_type => 'HardDelete'
|
65
|
+
}
|
66
|
+
resp = @ews.delete_folder(opts)
|
67
|
+
if resp.success?
|
68
|
+
true
|
69
|
+
else
|
70
|
+
raise EwsError, "Could not delete folder. #{resp.code}: #{resp.message}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def items(opts = {})
|
75
|
+
args = items_args(opts.clone)
|
76
|
+
obj = OpenStruct.new(opts: args, restriction: {})
|
77
|
+
yield obj if block_given?
|
78
|
+
merge_restrictions! obj
|
79
|
+
resp = ews.find_item(args)
|
80
|
+
items_parser resp
|
81
|
+
end
|
82
|
+
|
83
|
+
# Fetch items since a give DateTime
|
84
|
+
# @param [DateTime] date_time the time to fetch Items since.
|
85
|
+
def items_since(date_time, opts = {})
|
86
|
+
opts = opts.clone
|
87
|
+
unless date_time.kind_of?(Date)
|
88
|
+
raise EwsBadArgumentError, "First argument must be a Date or DateTime"
|
89
|
+
end
|
90
|
+
restr = {:restriction =>
|
91
|
+
{:is_greater_than_or_equal_to =>
|
92
|
+
[{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
|
93
|
+
{:field_uRI_or_constant =>{:constant => {:value=>date_time.to_datetime}}}]
|
94
|
+
}}
|
95
|
+
items(opts.merge(restr))
|
96
|
+
end
|
97
|
+
|
98
|
+
# Fetch only items from today (since midnight)
|
99
|
+
def todays_items(opts = {})
|
100
|
+
items_since(Date.today)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Fetch items between a given time period
|
104
|
+
# @param [DateTime] start_date the time to start fetching Items from
|
105
|
+
# @param [DateTime] end_date the time to stop fetching Items from
|
106
|
+
def items_between(start_date, end_date, opts={})
|
107
|
+
items do |obj|
|
108
|
+
obj.restriction = { :and =>
|
109
|
+
[
|
110
|
+
{:is_greater_than_or_equal_to =>
|
111
|
+
[
|
112
|
+
{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
|
113
|
+
{:field_uRI_or_constant=>{:constant => {:value =>start_date}}}
|
114
|
+
]
|
115
|
+
},
|
116
|
+
{:is_less_than_or_equal_to =>
|
117
|
+
[
|
118
|
+
{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}},
|
119
|
+
{:field_uRI_or_constant=>{:constant => {:value =>end_date}}}
|
120
|
+
]
|
121
|
+
}
|
122
|
+
]
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Search on the item subject
|
128
|
+
# @param [String] match_str A simple string paramater to match against the
|
129
|
+
# subject. The search ignores case and does not accept regexes... only strings.
|
130
|
+
# @param [String,nil] exclude_str A string to exclude from matches against
|
131
|
+
# the subject. This is optional.
|
132
|
+
def search_by_subject(match_str, exclude_str = nil)
|
133
|
+
items do |obj|
|
134
|
+
match = {:contains => {
|
135
|
+
:containment_mode => 'Substring',
|
136
|
+
:containment_comparison => 'IgnoreCase',
|
137
|
+
:field_uRI => {:field_uRI=>'item:Subject'},
|
138
|
+
:constant => {:value =>match_str}
|
139
|
+
}}
|
140
|
+
unless exclude_str.nil?
|
141
|
+
excl = {:not =>
|
142
|
+
{:contains => {
|
143
|
+
:containment_mode => 'Substring',
|
144
|
+
:containment_comparison => 'IgnoreCase',
|
145
|
+
:field_uRI => {:field_uRI=>'item:Subject'},
|
146
|
+
:constant => {:value =>exclude_str}
|
147
|
+
}}
|
148
|
+
}
|
149
|
+
|
150
|
+
match[:and] = [{:contains => match.delete(:contains)}, excl]
|
151
|
+
end
|
152
|
+
obj.restriction = match
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_all_properties!
|
157
|
+
@ews_item = get_folder(:base_shape => 'AllProperties')
|
158
|
+
simplify!
|
159
|
+
end
|
160
|
+
|
161
|
+
def available_categories
|
162
|
+
opts = {
|
163
|
+
user_config_name: {
|
164
|
+
name: 'CategoryList',
|
165
|
+
distinguished_folder_id: {id: :calendar}
|
166
|
+
},
|
167
|
+
user_config_props: 'XmlData'
|
168
|
+
}
|
169
|
+
resp = ews.get_user_configuration(opts)
|
170
|
+
#txt = resp.response_message[:elems][:get_user_configuration_response_message][:elems][1][:user_configuration][:elems][1][:xml_data][:text]
|
171
|
+
#Base64.decode64 txt
|
172
|
+
end
|
173
|
+
|
174
|
+
# Syncronize Items in this folder. If this method is issued multiple
|
175
|
+
# times it will continue where the last sync completed.
|
176
|
+
# @param [Integer] sync_amount The number of items to synchronize per sync
|
177
|
+
# @param [Boolean] sync_all Whether to sync all the data by looping through.
|
178
|
+
# The default is to just sync the first set. You can manually loop through
|
179
|
+
# with multiple calls to #sync_items!
|
180
|
+
# @return [Hash] Returns a hash with keys for each change type that ocurred.
|
181
|
+
# Possible key values are:
|
182
|
+
# (:create/:udpate/:delete/:read_flag_change).
|
183
|
+
# For :deleted and :read_flag_change items a simple hash with :id and
|
184
|
+
# :change_key is returned.
|
185
|
+
# See: http://msdn.microsoft.com/en-us/library/aa565609.aspx
|
186
|
+
def sync_items!(sync_state = nil, sync_amount = 256, sync_all = false, opts = {})
|
187
|
+
item_shape = opts.has_key?(:item_shape) ? opts.delete(:item_shape) : {:base_shape => :default}
|
188
|
+
sync_state ||= @sync_state
|
189
|
+
|
190
|
+
resp = ews.sync_folder_items item_shape: item_shape,
|
191
|
+
sync_folder_id: self.folder_id, max_changes_returned: sync_amount, sync_state: sync_state
|
192
|
+
rmsg = resp.response_messages[0]
|
193
|
+
|
194
|
+
if rmsg.success?
|
195
|
+
@synced = rmsg.includes_last_item_in_range?
|
196
|
+
@sync_state = rmsg.sync_state
|
197
|
+
rhash = {}
|
198
|
+
rmsg.changes.each do |c|
|
199
|
+
ctype = c.keys.first
|
200
|
+
rhash[ctype] = [] unless rhash.has_key?(ctype)
|
201
|
+
if ctype == :delete || ctype == :read_flag_change
|
202
|
+
rhash[ctype] << c[ctype][:elems][0][:item_id][:attribs]
|
203
|
+
else
|
204
|
+
type = c[ctype][:elems][0].keys.first
|
205
|
+
item = class_by_name(type).new(ews, c[ctype][:elems][0][type])
|
206
|
+
rhash[ctype] << item
|
207
|
+
end
|
208
|
+
end
|
209
|
+
rhash
|
210
|
+
else
|
211
|
+
raise EwsError, "Could not synchronize: #{rmsg.code}: #{rmsg.message_text}"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def synced?
|
216
|
+
@synced
|
217
|
+
end
|
218
|
+
|
219
|
+
# Subscribe this folder to events. This method initiates an Exchange pull
|
220
|
+
# type subscription.
|
221
|
+
#
|
222
|
+
# @param event_types [Array] Which event types to subscribe to. By default
|
223
|
+
# we subscribe to all Exchange event types: :all, :copied, :created,
|
224
|
+
# :deleted, :modified, :moved, :new_mail, :free_busy_changed
|
225
|
+
# @param watermark [String] pass a watermark if you wish to start the
|
226
|
+
# subscription at a specific point.
|
227
|
+
# @param timeout [Fixnum] the time in minutes that the subscription can
|
228
|
+
# remain idle between calls to #get_events. default: 240 minutes
|
229
|
+
# @return [Boolean] Did the subscription happen successfully?
|
230
|
+
def subscribe(evtypes = [:all], watermark = nil, timeout = 240)
|
231
|
+
# Refresh the subscription if already subscribed
|
232
|
+
unsubscribe if subscribed?
|
233
|
+
|
234
|
+
event_types = normalize_event_names(evtypes)
|
235
|
+
folder = {id: self.id, change_key: self.change_key}
|
236
|
+
resp = ews.pull_subscribe_folder(folder, event_types, timeout, watermark)
|
237
|
+
rmsg = resp.response_messages.first
|
238
|
+
if rmsg.success?
|
239
|
+
@subscription_id = rmsg.subscription_id
|
240
|
+
@watermark = rmsg.watermark
|
241
|
+
true
|
242
|
+
else
|
243
|
+
raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def push_subscribe(url, evtypes = [:all], watermark = nil, status_frequency = nil)
|
248
|
+
# Refresh the subscription if already subscribed
|
249
|
+
unsubscribe if subscribed?
|
250
|
+
|
251
|
+
event_types = normalize_event_names(evtypes)
|
252
|
+
folder = {id: self.id, change_key: self.change_key}
|
253
|
+
resp = ews.push_subscribe_folder(folder, event_types, url, status_frequency, watermark)
|
254
|
+
rmsg = resp.response_messages.first
|
255
|
+
if rmsg.success?
|
256
|
+
@subscription_id = rmsg.subscription_id
|
257
|
+
@watermark = rmsg.watermark
|
258
|
+
true
|
259
|
+
else
|
260
|
+
raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Check if there is a subscription for this folder.
|
265
|
+
# @return [Boolean] Are we subscribed to this folder?
|
266
|
+
def subscribed?
|
267
|
+
( @subscription_id.nil? or @watermark.nil? )? false : true
|
268
|
+
end
|
269
|
+
|
270
|
+
# Unsubscribe this folder from further Exchange events.
|
271
|
+
# @return [Boolean] Did we unsubscribe successfully?
|
272
|
+
def unsubscribe
|
273
|
+
return true if @subscription_id.nil?
|
274
|
+
|
275
|
+
resp = ews.unsubscribe(@subscription_id)
|
276
|
+
rmsg = resp.response_messages.first
|
277
|
+
if rmsg.success?
|
278
|
+
@subscription_id, @watermark = nil, nil
|
279
|
+
true
|
280
|
+
else
|
281
|
+
raise EwsSubscriptionError, "Could not unsubscribe: #{rmsg.code}: #{rmsg.message_text}"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Checks a subscribed folder for events
|
286
|
+
# @return [Array] An array of Event items
|
287
|
+
def get_events
|
288
|
+
begin
|
289
|
+
if subscribed?
|
290
|
+
resp = ews.get_events(@subscription_id, @watermark)
|
291
|
+
rmsg = resp.response_messages[0]
|
292
|
+
@watermark = rmsg.new_watermark
|
293
|
+
# @todo if parms[:more_events] # get more events
|
294
|
+
rmsg.events.collect{|ev|
|
295
|
+
type = ev.keys.first
|
296
|
+
class_by_name(type).new(ews, ev[type])
|
297
|
+
}
|
298
|
+
else
|
299
|
+
raise EwsSubscriptionError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
|
300
|
+
end
|
301
|
+
rescue EwsSubscriptionTimeout => e
|
302
|
+
@subscription_id, @watermark = nil, nil
|
303
|
+
raise e
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
private
|
309
|
+
|
310
|
+
|
311
|
+
def key_paths
|
312
|
+
@key_paths ||= super.merge(GFOLDER_KEY_PATHS)
|
313
|
+
end
|
314
|
+
|
315
|
+
def key_types
|
316
|
+
@key_types ||= super.merge(GFOLDER_KEY_TYPES)
|
317
|
+
end
|
318
|
+
|
319
|
+
def key_alias
|
320
|
+
@key_alias ||= super.merge(GFOLDER_KEY_ALIAS)
|
321
|
+
end
|
322
|
+
|
323
|
+
def simplify!
|
324
|
+
@ews_item = @ews_item[:elems].inject({}) do |o,i|
|
325
|
+
key = i.keys.first
|
326
|
+
if o.has_key?(key)
|
327
|
+
if o[key].is_a?(Array)
|
328
|
+
o[key] << i[key]
|
329
|
+
else
|
330
|
+
o[key] = [o.delete(key), i[key]]
|
331
|
+
end
|
332
|
+
else
|
333
|
+
o[key] = i[key]
|
334
|
+
end
|
335
|
+
o
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# Get a specific folder by its ID.
|
340
|
+
# @param [Hash] opts Misc options to control request
|
341
|
+
# @option opts [String] :base_shape IdOnly/Default/AllProperties
|
342
|
+
# @raise [EwsError] raised when the backend SOAP method returns an error.
|
343
|
+
def get_folder(opts = {})
|
344
|
+
args = get_folder_args(opts)
|
345
|
+
resp = ews.get_folder(args)
|
346
|
+
get_folder_parser(resp)
|
347
|
+
end
|
348
|
+
|
349
|
+
# Build up the arguements for #get_folder
|
350
|
+
# @todo: should we really pass the ChangeKey or do we want the freshest obj?
|
351
|
+
def get_folder_args(opts)
|
352
|
+
opts[:base_shape] ||= 'Default'
|
353
|
+
default_args = {
|
354
|
+
:folder_ids => [{:id => self.id, :change_key => self.change_key}],
|
355
|
+
:folder_shape => {:base_shape => opts[:base_shape]}
|
356
|
+
}
|
357
|
+
default_args.merge(opts)
|
358
|
+
end
|
359
|
+
|
360
|
+
def get_folder_parser(resp)
|
361
|
+
if(resp.status == 'Success')
|
362
|
+
f = resp.response_message[:elems][:folders][:elems][0]
|
363
|
+
f.values.first
|
364
|
+
else
|
365
|
+
raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def items_args(opts)
|
370
|
+
default_args = {
|
371
|
+
:parent_folder_ids => [{:id => self.id}],
|
372
|
+
:traversal => 'Shallow',
|
373
|
+
:item_shape => {:base_shape => 'Default'}
|
374
|
+
}.merge(opts)
|
375
|
+
end
|
376
|
+
|
377
|
+
def items_parser(resp)
|
378
|
+
rm = resp.response_messages[0]
|
379
|
+
if(rm.status == 'Success')
|
380
|
+
items = []
|
381
|
+
rm.root_folder.items.each do |i|
|
382
|
+
type = i.keys.first
|
383
|
+
items << class_by_name(type).new(ews, i[type], self)
|
384
|
+
end
|
385
|
+
items
|
386
|
+
else
|
387
|
+
raise EwsError, "Could not retrieve folder. #{rm.code}: #{rm.message_text}"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def merge_restrictions!(obj, merge_type = :and)
|
392
|
+
if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty?
|
393
|
+
obj.opts[:restriction] = {
|
394
|
+
merge_type => [
|
395
|
+
obj.opts.delete(:restriction),
|
396
|
+
obj.restriction
|
397
|
+
]
|
398
|
+
}
|
399
|
+
elsif !obj.restriction.empty?
|
400
|
+
obj.opts[:restriction] = obj.restriction
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def normalize_event_names(events)
|
405
|
+
if events.include?(:all)
|
406
|
+
events = [:copied, :created, :deleted, :modified, :moved, :new_mail, :free_busy_changed]
|
407
|
+
end
|
408
|
+
|
409
|
+
events.collect do |ev|
|
410
|
+
nev = ruby_case(ev)
|
411
|
+
if nev.end_with?('_event')
|
412
|
+
nev.to_sym
|
413
|
+
else
|
414
|
+
"#{nev}_event".to_sym
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
end
|
420
|
+
end
|