viewpoint2 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +216 -0
- data/lib/ews/calendar_accessors.rb +34 -0
- data/lib/ews/connection.rb +130 -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 +103 -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 +99 -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 +1351 -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 +79 -0
- data/lib/ews/templates/forward_item.rb +24 -0
- data/lib/ews/templates/message.rb +76 -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 +41 -0
- data/lib/ews/types/calendar_folder.rb +50 -0
- data/lib/ews/types/calendar_item.rb +133 -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 +418 -0
- data/lib/ews/types/item.rb +450 -0
- data/lib/ews/types/item_attachment.rb +84 -0
- data/lib/ews/types/item_field_uri_map.rb +208 -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/post_item.rb +7 -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 +104 -0
- data/lib/ews/types/tasks_folder.rb +27 -0
- data/lib/viewpoint/logging.rb +27 -0
- data/lib/viewpoint/logging/config.rb +24 -0
- data/lib/viewpoint/string_utils.rb +76 -0
- data/lib/viewpoint2.rb +111 -0
- metadata +191 -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,418 @@
|
|
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
|
+
|
249
|
+
event_types = normalize_event_names(evtypes)
|
250
|
+
folder = {id: self.id, change_key: self.change_key}
|
251
|
+
resp = ews.push_subscribe_folder(folder, event_types, url, status_frequency, watermark)
|
252
|
+
rmsg = resp.response_messages.first
|
253
|
+
if rmsg.success?
|
254
|
+
@subscription_id = rmsg.subscription_id
|
255
|
+
@watermark = rmsg.watermark
|
256
|
+
true
|
257
|
+
else
|
258
|
+
raise EwsSubscriptionError, "Could not subscribe: #{rmsg.code}: #{rmsg.message_text}"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Check if there is a subscription for this folder.
|
263
|
+
# @return [Boolean] Are we subscribed to this folder?
|
264
|
+
def subscribed?
|
265
|
+
( @subscription_id.nil? or @watermark.nil? )? false : true
|
266
|
+
end
|
267
|
+
|
268
|
+
# Unsubscribe this folder from further Exchange events.
|
269
|
+
# @return [Boolean] Did we unsubscribe successfully?
|
270
|
+
def unsubscribe
|
271
|
+
return true if @subscription_id.nil?
|
272
|
+
|
273
|
+
resp = ews.unsubscribe(@subscription_id)
|
274
|
+
rmsg = resp.response_messages.first
|
275
|
+
if rmsg.success?
|
276
|
+
@subscription_id, @watermark = nil, nil
|
277
|
+
true
|
278
|
+
else
|
279
|
+
raise EwsSubscriptionError, "Could not unsubscribe: #{rmsg.code}: #{rmsg.message_text}"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Checks a subscribed folder for events
|
284
|
+
# @return [Array] An array of Event items
|
285
|
+
def get_events
|
286
|
+
begin
|
287
|
+
if subscribed?
|
288
|
+
resp = ews.get_events(@subscription_id, @watermark)
|
289
|
+
rmsg = resp.response_messages[0]
|
290
|
+
@watermark = rmsg.new_watermark
|
291
|
+
# @todo if parms[:more_events] # get more events
|
292
|
+
rmsg.events.collect{|ev|
|
293
|
+
type = ev.keys.first
|
294
|
+
class_by_name(type).new(ews, ev[type])
|
295
|
+
}
|
296
|
+
else
|
297
|
+
raise EwsSubscriptionError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
|
298
|
+
end
|
299
|
+
rescue EwsSubscriptionTimeout => e
|
300
|
+
@subscription_id, @watermark = nil, nil
|
301
|
+
raise e
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
private
|
307
|
+
|
308
|
+
|
309
|
+
def key_paths
|
310
|
+
@key_paths ||= super.merge(GFOLDER_KEY_PATHS)
|
311
|
+
end
|
312
|
+
|
313
|
+
def key_types
|
314
|
+
@key_types ||= super.merge(GFOLDER_KEY_TYPES)
|
315
|
+
end
|
316
|
+
|
317
|
+
def key_alias
|
318
|
+
@key_alias ||= super.merge(GFOLDER_KEY_ALIAS)
|
319
|
+
end
|
320
|
+
|
321
|
+
def simplify!
|
322
|
+
@ews_item = @ews_item[:elems].inject({}) do |o,i|
|
323
|
+
key = i.keys.first
|
324
|
+
if o.has_key?(key)
|
325
|
+
if o[key].is_a?(Array)
|
326
|
+
o[key] << i[key]
|
327
|
+
else
|
328
|
+
o[key] = [o.delete(key), i[key]]
|
329
|
+
end
|
330
|
+
else
|
331
|
+
o[key] = i[key]
|
332
|
+
end
|
333
|
+
o
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# Get a specific folder by its ID.
|
338
|
+
# @param [Hash] opts Misc options to control request
|
339
|
+
# @option opts [String] :base_shape IdOnly/Default/AllProperties
|
340
|
+
# @raise [EwsError] raised when the backend SOAP method returns an error.
|
341
|
+
def get_folder(opts = {})
|
342
|
+
args = get_folder_args(opts)
|
343
|
+
resp = ews.get_folder(args)
|
344
|
+
get_folder_parser(resp)
|
345
|
+
end
|
346
|
+
|
347
|
+
# Build up the arguements for #get_folder
|
348
|
+
# @todo: should we really pass the ChangeKey or do we want the freshest obj?
|
349
|
+
def get_folder_args(opts)
|
350
|
+
opts[:base_shape] ||= 'Default'
|
351
|
+
default_args = {
|
352
|
+
:folder_ids => [{:id => self.id, :change_key => self.change_key}],
|
353
|
+
:folder_shape => {:base_shape => opts[:base_shape]}
|
354
|
+
}
|
355
|
+
default_args.merge(opts)
|
356
|
+
end
|
357
|
+
|
358
|
+
def get_folder_parser(resp)
|
359
|
+
if(resp.status == 'Success')
|
360
|
+
f = resp.response_message[:elems][:folders][:elems][0]
|
361
|
+
f.values.first
|
362
|
+
else
|
363
|
+
raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def items_args(opts)
|
368
|
+
default_args = {
|
369
|
+
:parent_folder_ids => [{:id => self.id}],
|
370
|
+
:traversal => 'Shallow',
|
371
|
+
:item_shape => {:base_shape => 'Default'}
|
372
|
+
}.merge(opts)
|
373
|
+
end
|
374
|
+
|
375
|
+
def items_parser(resp)
|
376
|
+
rm = resp.response_messages[0]
|
377
|
+
if(rm.status == 'Success')
|
378
|
+
items = []
|
379
|
+
rm.root_folder.items.each do |i|
|
380
|
+
type = i.keys.first
|
381
|
+
items << class_by_name(type).new(ews, i[type], self)
|
382
|
+
end
|
383
|
+
items
|
384
|
+
else
|
385
|
+
raise EwsError, "Could not retrieve folder. #{rm.code}: #{rm.message_text}"
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def merge_restrictions!(obj, merge_type = :and)
|
390
|
+
if obj.opts[:restriction] && !obj.opts[:restriction].empty? && !obj.restriction.empty?
|
391
|
+
obj.opts[:restriction] = {
|
392
|
+
merge_type => [
|
393
|
+
obj.opts.delete(:restriction),
|
394
|
+
obj.restriction
|
395
|
+
]
|
396
|
+
}
|
397
|
+
elsif !obj.restriction.empty?
|
398
|
+
obj.opts[:restriction] = obj.restriction
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def normalize_event_names(events)
|
403
|
+
if events.include?(:all)
|
404
|
+
events = [:copied, :created, :deleted, :modified, :moved, :new_mail, :free_busy_changed]
|
405
|
+
end
|
406
|
+
|
407
|
+
events.collect do |ev|
|
408
|
+
nev = ruby_case(ev)
|
409
|
+
if nev.end_with?('_event')
|
410
|
+
nev.to_sym
|
411
|
+
else
|
412
|
+
"#{nev}_event".to_sym
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
418
|
+
end
|