viewpoint 0.0.5 → 0.1.0
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.
- data/README +84 -45
- data/Rakefile +7 -5
- data/TODO +6 -0
- data/VERSION +1 -1
- data/lib/exceptions/exceptions.rb +34 -0
- data/lib/extensions/string.rb +37 -0
- data/lib/model/calendar_folder.rb +45 -0
- data/lib/model/calendar_item.rb +145 -0
- data/lib/model/contact.rb +58 -0
- data/lib/model/contacts_folder.rb +35 -0
- data/lib/model/distribution_list.rb +26 -0
- data/lib/model/event.rb +118 -0
- data/lib/model/folder.rb +36 -0
- data/lib/model/generic_folder.rb +302 -0
- data/lib/model/item.rb +126 -0
- data/lib/model/mailbox_user.rb +107 -0
- data/lib/model/meeting_cancellation.rb +28 -0
- data/lib/{viewpoint/errors.rb → model/meeting_message.rb} +10 -14
- data/lib/model/meeting_request.rb +26 -0
- data/lib/model/meeting_response.rb +26 -0
- data/lib/model/message.rb +73 -0
- data/lib/model/model.rb +161 -0
- data/lib/model/search_folder.rb +36 -0
- data/lib/model/task.rb +62 -0
- data/lib/model/task_list.rb +19 -0
- data/lib/model/tasks_folder.rb +33 -0
- data/lib/soap/handsoap/builder.rb +22 -0
- data/lib/soap/handsoap/builders/ews_build_helpers.rb +317 -0
- data/lib/soap/handsoap/builders/ews_builder.rb +86 -0
- data/lib/soap/handsoap/ews_service.rb +646 -0
- data/lib/soap/handsoap/parser.rb +106 -0
- data/lib/soap/handsoap/parsers/ews_parser.rb +165 -0
- data/lib/soap/soap_provider.rb +75 -0
- data/lib/viewpoint.rb +98 -3
- data/preamble +1 -1
- data/test/spec/basic_functions.spec +51 -0
- data/test/spec/folder_subscriptions.spec +35 -0
- data/test/spec/folder_synchronization.spec +28 -0
- data/utils/ewsWSDL2rb.rb +29 -0
- metadata +101 -43
- data/lib/exchwebserv.rb +0 -6
- data/lib/soap/viewpoint.conf +0 -3
- data/lib/viewpoint/calendar.rb +0 -128
- data/lib/viewpoint/calendar_item.rb +0 -118
- data/lib/viewpoint/event.rb +0 -0
- data/lib/viewpoint/exchange_headers.rb +0 -49
- data/lib/viewpoint/exchwebserv.rb +0 -236
- data/lib/viewpoint/folder.rb +0 -358
- data/lib/viewpoint/item.rb +0 -101
- data/lib/viewpoint/mail.rb +0 -117
- data/lib/viewpoint/message.rb +0 -132
- data/lib/viewpoint/task.rb +0 -0
- data/lib/viewpoint/tasks.rb +0 -0
- data/lib/wsdl/defaultMappingRegistry.rb +0 -10680
- data/lib/wsdl/exchangeServiceBinding.rb +0 -349
- data/lib/wsdl/exchangeServiceTypes.rb +0 -11013
- data/test/spec/basic_features_spec.rb +0 -37
- data/test/test_client.rb +0 -13
- data/test/testrestrict.rb +0 -75
@@ -0,0 +1,58 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
class Contact < Item
|
24
|
+
|
25
|
+
# Create a Contact in the Exchange Data Store
|
26
|
+
#
|
27
|
+
# @param [String] subject The task subject
|
28
|
+
# @param [String] body The task body
|
29
|
+
def self.add_contact()
|
30
|
+
item = {}
|
31
|
+
|
32
|
+
conn = Viewpoint::EWS::EWS.instance
|
33
|
+
resp = conn.ews.create_contact_item()
|
34
|
+
|
35
|
+
if(resp.status == 'Success')
|
36
|
+
resp = resp.items.shift
|
37
|
+
self.new(resp[resp.keys.first])
|
38
|
+
else
|
39
|
+
raise EwsError, "Could not add contact. #{resp.code}: #{resp.message}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
# Initialize an Exchange Web Services item of type Contact
|
46
|
+
def initialize(ews_item)
|
47
|
+
super(ews_item)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def init_methods
|
53
|
+
super()
|
54
|
+
end
|
55
|
+
|
56
|
+
end # Contact
|
57
|
+
end # EWS
|
58
|
+
end # Viewpoint
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
class ContactsFolder < GenericFolder
|
24
|
+
|
25
|
+
# initialize with an item of CalendarFolderType
|
26
|
+
def initialize(folder)
|
27
|
+
super(folder)
|
28
|
+
|
29
|
+
# @todo Handle:
|
30
|
+
# <SharingEffectiveRights/>
|
31
|
+
end
|
32
|
+
|
33
|
+
end # ContactsFolder
|
34
|
+
end # EWS
|
35
|
+
end # Viewpoint
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
class DistributionList < Item
|
24
|
+
end # DistributionList
|
25
|
+
end # EWS
|
26
|
+
end # Viewpoint
|
data/lib/model/event.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
class Event < Item
|
24
|
+
|
25
|
+
attr_reader :subject, :organizer, :location, :start, :end, :cal_item_type
|
26
|
+
|
27
|
+
# Initialize an Exchange Web Services item
|
28
|
+
def initialize(ews_item, parent_folder)
|
29
|
+
raise InvalidEWSItemError if ews_item.nil?
|
30
|
+
|
31
|
+
@subject = ews_item.subject # String
|
32
|
+
@location = ews_item.location if ews_item.location
|
33
|
+
@cal_item_type = ews_item.calendarItemType
|
34
|
+
@organizer = ews_item.organizer.mailbox.name if ews_item.organizer and ews_item.organizer.mailbox # String
|
35
|
+
@start = ews_item.start if ews_item.start # DateTime
|
36
|
+
@end = ews_item.v_end if ews_item.v_end # DateTime
|
37
|
+
@busy_status = ews_item.legacyFreeBusyStatus if ews_item.legacyFreeBusyStatus # String
|
38
|
+
@date_time_recieved = ews_item.dateTimeReceived if ews_item.dateTimeReceived # DateTime
|
39
|
+
|
40
|
+
# This is where the event object gets loaded if it
|
41
|
+
# is requested. Think of it like IMAP downloading the
|
42
|
+
# body when the message is viewed.
|
43
|
+
@message = nil
|
44
|
+
|
45
|
+
super(ews_item, parent_folder)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
def body
|
51
|
+
get_calitem if @message == nil
|
52
|
+
@message.body
|
53
|
+
end
|
54
|
+
|
55
|
+
def sender
|
56
|
+
@organizer
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Convert item to iCal format: http://www.ietf.org/rfc/rfc2445.txt
|
61
|
+
# Returns Icalendar::Event object
|
62
|
+
def to_ical_event
|
63
|
+
get_calitem if @message == nil
|
64
|
+
iev = Icalendar::Event.new
|
65
|
+
iev.uid = @message.uID
|
66
|
+
unless(@message.organizer == nil)
|
67
|
+
iev.organizer = "CN=\"#{@message.organizer.mailbox.name}\"" if @message.organizer.mailbox.name
|
68
|
+
iev.organizer += ":MAILTO:#{@message.organizer.mailbox.emailAddress}" if @message.organizer.mailbox.emailAddress
|
69
|
+
end
|
70
|
+
# TODO: Handle EWS Timezones better. TZ_HASH in viewpoint.rb is the start of this
|
71
|
+
require 'time'
|
72
|
+
#tzoffset = @message.timeZone.sub(/^\(GMT([^\)]+)\).*$/,'\1')
|
73
|
+
dtstart = Time.at(@message.start.strftime('%s').to_i)
|
74
|
+
dtend = Time.at(@message.v_end.strftime('%s').to_i)
|
75
|
+
dtstamp = Time.at(@message.dateTimeStamp.strftime('%s').to_i)
|
76
|
+
last_modified = Time.at(@message.lastModifiedTime.strftime('%s').to_i)
|
77
|
+
timestr = "%Y%m%dT%H%M%S"
|
78
|
+
iev.dtstart = dtstart.strftime(timestr)
|
79
|
+
iev.dtend = dtend.strftime(timestr)
|
80
|
+
iev.tzid = dtstart.strftime('%Z')
|
81
|
+
iev.dtstamp = dtstamp.strftime(timestr)
|
82
|
+
iev.last_modified = last_modified.strftime(timestr)
|
83
|
+
iev.location = @message.location if @message.location
|
84
|
+
iev.klass = @message.sensitivity if @message.sensitivity
|
85
|
+
iev.summary = @message.subject if @message.subject
|
86
|
+
iev.description = @message.body if @message.body
|
87
|
+
iev.transp = @message.legacyFreeBusyStatus if @message.legacyFreeBusyStatus
|
88
|
+
iev.duration = @message.duration if @message.duration
|
89
|
+
iev.sequence = @message.appointmentSequenceNumber if @message.appointmentSequenceNumber
|
90
|
+
iev.status = @message.myResponseType if @message.myResponseType
|
91
|
+
#iev.attach @message.attachments if @message.hasAttachments
|
92
|
+
@message.requiredAttendees.each do |pers|
|
93
|
+
output = "ROLE=REQ-PARTICIPANT;CN=\"#{pers.mailbox.name}\"" if pers.mailbox.respond_to?(:name)
|
94
|
+
output += ":MAILTO:#{pers.mailbox.emailAddress}" if pers.mailbox.respond_to?(:emailAddress)
|
95
|
+
iev.attendees << output if output
|
96
|
+
end if @message.requiredAttendees
|
97
|
+
@message.optionalAttendees.each do |pers|
|
98
|
+
output = "ROLE=OPT-PARTICIPANT;CN=\"#{pers.mailbox.name}\"" if pers.mailbox.respond_to?(:name)
|
99
|
+
output += ":MAILTO:#{pers.mailbox.emailAddress}" if pers.mailbox.respond_to?(:emailAddress)
|
100
|
+
iev.attendees << output if output
|
101
|
+
end if @message.optionalAttendees
|
102
|
+
|
103
|
+
#iev.categories = @message.categories if @message.categories
|
104
|
+
#iev.resources = @message.resources if @message.resources
|
105
|
+
return iev
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# These methods are marked 'private' because they return EWS Types and I am trying to
|
110
|
+
# hide those because they are not elegant and a bit too tedious for the public interface.
|
111
|
+
private
|
112
|
+
|
113
|
+
def get_calitem
|
114
|
+
@message = @parent_folder.get_item(@item_id)
|
115
|
+
end
|
116
|
+
end # Event
|
117
|
+
end # EWS
|
118
|
+
end # Viewpoint
|
data/lib/model/folder.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
module Viewpoint
|
22
|
+
module EWS
|
23
|
+
# This class represents a FolderType object in the Exchange Data store.
|
24
|
+
# This is the type of folder that mail messages will be found in.
|
25
|
+
class Folder < GenericFolder
|
26
|
+
|
27
|
+
# Initialize with an item of FolderType. This is typically the folder
|
28
|
+
# used to house mail messages.
|
29
|
+
def initialize(folder)
|
30
|
+
super(folder)
|
31
|
+
define_int_var :unread_count
|
32
|
+
end
|
33
|
+
|
34
|
+
end # Folder
|
35
|
+
end # EWS
|
36
|
+
end # Viewpoint
|
@@ -0,0 +1,302 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2010 Dan Wanek <dan.wanek@gmail.com>
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# This file is part of Viewpoint.
|
6
|
+
#
|
7
|
+
# Viewpoint is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or (at
|
10
|
+
# your option) any later version.
|
11
|
+
#
|
12
|
+
# Viewpoint is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
15
|
+
# Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along
|
18
|
+
# with Viewpoint. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#############################################################################
|
20
|
+
|
21
|
+
# This class is inherited by all folder subtypes such as Mail, Calendar,
|
22
|
+
# Tasks and Search. It will serve as the brain for all of the methods that
|
23
|
+
# each of these folder types have in common.
|
24
|
+
module Viewpoint
|
25
|
+
module EWS
|
26
|
+
# This class is a generic folder that should typically not be instantiated
|
27
|
+
# on it's own. It represents all the commonalities among folders found
|
28
|
+
# in the Exchange Data Store of which there are many.
|
29
|
+
# @see http://msdn.microsoft.com/en-us/library/aa564009.aspx
|
30
|
+
class GenericFolder
|
31
|
+
include Viewpoint
|
32
|
+
include Model
|
33
|
+
|
34
|
+
@@distinguished_folder_ids = %w{calendar contacts deleteditems drafts inbox journal
|
35
|
+
notes outbox sentitems tasks msgfolderroot root junkemail searchfolders voicemail
|
36
|
+
recoverableitemsroot recoverableitemsdeletions recoverableitemsversions
|
37
|
+
recoverableitemspurges archiveroot archivemsgfolderroot archivedeleteditems
|
38
|
+
archiverecoverableitemsroot archiverecoverableitemsdeletions
|
39
|
+
archiverecoverableitemsversions archiverecoverableitemspurges}
|
40
|
+
|
41
|
+
@@event_types = %w{CopiedEvent CreatedEvent DeletedEvent ModifiedEvent MovedEvent NewMailEvent}
|
42
|
+
|
43
|
+
def self.get_folder(folder_id, act_as = nil, folder_shape = {:base_shape => 'Default'})
|
44
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.get_folder( [normalize_id(folder_id)], folder_shape, act_as )
|
45
|
+
if(resp.status == 'Success')
|
46
|
+
folder = resp.items.first
|
47
|
+
f_type = folder.keys.first.to_s.camel_case
|
48
|
+
return(eval "#{f_type}.new(folder[folder.keys.first])")
|
49
|
+
else
|
50
|
+
raise EwsError, "Could not retrieve folder. #{resp.code}: #{resp.message}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Find subfolders of the passed root folder. If no parameters are passed
|
55
|
+
# this method will search from the Root folder.
|
56
|
+
# @param [Array] root An folder id, either a DistinguishedFolderId (must me a Symbol)
|
57
|
+
# or a FolderId (String)
|
58
|
+
# @param [String] traversal Shallow/Deep/SoftDeleted
|
59
|
+
# @return [Array] Returns an Array of Folder or subclasses of Folder
|
60
|
+
def self.find_folders(root = :root, traversal = 'Shallow')
|
61
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_folder( [normalize_id(root)], traversal )
|
62
|
+
if(resp.status == 'Success')
|
63
|
+
folders = []
|
64
|
+
resp.items.each do |f|
|
65
|
+
f_type = f.keys.first.to_s.camel_case
|
66
|
+
folders << (eval "#{f_type}.new(f[f.keys.first])")
|
67
|
+
end
|
68
|
+
return folders
|
69
|
+
else
|
70
|
+
raise EwsError, "Could not retrieve folders. #{resp.code}: #{resp.message}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_accessor :folder_id, :change_key, :parent_id
|
75
|
+
attr_reader :subscription_id, :watermark, :sync_state
|
76
|
+
alias :id :folder_id
|
77
|
+
|
78
|
+
def initialize(ews_item)
|
79
|
+
super() # Calls initialize in Model (creates @ews_methods Array)
|
80
|
+
@ews_item = ews_item
|
81
|
+
@folder_id = ews_item[:folder_id][:id]
|
82
|
+
@ews_methods << :folder_id
|
83
|
+
@ews_methods << :id
|
84
|
+
@change_key = ews_item[:folder_id][:change_key]
|
85
|
+
@ews_methods << :change_key
|
86
|
+
unless ews_item[:parent_folder_id].nil?
|
87
|
+
@parent_id = ews_item[:parent_folder_id]
|
88
|
+
@ews_methods << :parent_id
|
89
|
+
end
|
90
|
+
define_str_var :display_name, :folder_class
|
91
|
+
define_int_var :child_folder_count, :total_count
|
92
|
+
# @todo Handle:
|
93
|
+
# <EffectiveRights/>, <ExtendedProperty/>, <ManagedFolderInformation/>, <PermissionSet/>
|
94
|
+
|
95
|
+
@sync_state = nil # Base-64 encoded sync data
|
96
|
+
@synced = false # Whether or not the synchronization process is complete
|
97
|
+
@subscription_id = nil
|
98
|
+
@watermark = nil
|
99
|
+
@shallow = true
|
100
|
+
end
|
101
|
+
|
102
|
+
# Subscribe this folder to events. This method initiates an Exchange pull
|
103
|
+
# type subscription.
|
104
|
+
#
|
105
|
+
# @param [Array] event_types Which event types to subscribe to. By default
|
106
|
+
# we subscribe to all Exchange event types: CopiedEvent, CreatedEvent,
|
107
|
+
# DeletedEvent, ModifiedEvent, MovedEvent, NewMailEvent, FreeBusyChangedEvent
|
108
|
+
# @return [Boolean] Did the subscription happen successfully?
|
109
|
+
# @todo Add custom Exception for EWS
|
110
|
+
def subscribe(event_types = @@event_types)
|
111
|
+
# Refresh the subscription if already subscribed
|
112
|
+
unsubscribe if subscribed?
|
113
|
+
|
114
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.subscribe([folder_id],event_types)
|
115
|
+
if(resp.status == 'Success')
|
116
|
+
@subscription_id = resp.items.first[:subscription_id][:text]
|
117
|
+
@watermark = resp.items.first[:watermark][:text]
|
118
|
+
return true
|
119
|
+
else
|
120
|
+
raise StandardError, "Error: #{resp.message}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Check if there is a subscription for this folder.
|
125
|
+
# @return [Boolean] Are we subscribed to this folder?
|
126
|
+
def subscribed?
|
127
|
+
( @subscription_id.nil? or @watermark.nil? )? false : true
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Unsubscribe this folder from further Exchange events.
|
132
|
+
# @return [Boolean] Did we unsubscribe successfully?
|
133
|
+
# @todo Add custom Exception for EWS
|
134
|
+
def unsubscribe
|
135
|
+
return true if @subscription_id.nil?
|
136
|
+
|
137
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.unsubscribe(@subscription_id)
|
138
|
+
if(resp.status == 'Success')
|
139
|
+
@subscription_id, @watermark = nil, nil
|
140
|
+
return true
|
141
|
+
else
|
142
|
+
raise StandardError, "Error: #{resp.message}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Checks a subscribed folder for events
|
147
|
+
# @returns [Array] An array of Event items
|
148
|
+
# @todo check for subscription expiry
|
149
|
+
def get_events
|
150
|
+
begin
|
151
|
+
if(subscribed?)
|
152
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.get_events(@subscription_id, @watermark)
|
153
|
+
parms = resp.items.shift
|
154
|
+
@watermark = parms[:watermark]
|
155
|
+
# @todo if parms[:more_events] # get more events
|
156
|
+
return resp.items
|
157
|
+
else
|
158
|
+
raise StandardError, "Folder <#{self.display_name}> not subscribed to. Issue a Folder#subscribe before checking events."
|
159
|
+
end
|
160
|
+
rescue EwsSubscriptionTimeout => e
|
161
|
+
@subscription_id, @watermark = nil, nil
|
162
|
+
raise e
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Find Items
|
167
|
+
def find_items(opts = {})
|
168
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.find_item([@folder_id], 'Shallow', {:base_shape => 'Default'}, opts)
|
169
|
+
if(resp.status == 'Success')
|
170
|
+
parms = resp.items.shift
|
171
|
+
items = []
|
172
|
+
resp.items.each do |i|
|
173
|
+
i_type = i.keys.first
|
174
|
+
items << (eval "#{i_type.to_s.camel_case}.new(i[i_type])")
|
175
|
+
end
|
176
|
+
return items
|
177
|
+
else
|
178
|
+
raise EwsError, "Could not find items. #{resp.code}: #{resp.message}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def todays_items
|
183
|
+
#opts = {:query_string => ["Received:today"]}
|
184
|
+
items_since(Date.today.to_datetime)
|
185
|
+
end
|
186
|
+
|
187
|
+
def items_since(date_time)
|
188
|
+
restr = {:restriction =>
|
189
|
+
{:is_greater_than_or_equal_to =>
|
190
|
+
{:field_uRI => {:field_uRI=>'item:DateTimeReceived'}, :field_uRI_or_constant =>{:constant => {:value=>date_time}}}}}
|
191
|
+
find_items(restr)
|
192
|
+
end
|
193
|
+
|
194
|
+
def items_between(start_date, end_date)
|
195
|
+
restr = {:restriction => {:and => [
|
196
|
+
{:is_greater_than_or_equal_to => {:field_uRI => {:field_uRI=>'item:DateTimeReceived'},:field_uRI_or_constant=>{:constant => {:value =>start_date}}}},
|
197
|
+
{:is_less_than_or_equal_to => {:field_uRI => {:field_uRI=>'item:DateTimeReceived'},:field_uRI_or_constant=>{:constant => {:value =>end_date}}}}
|
198
|
+
]}}
|
199
|
+
find_items(restr)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Search on the item subject
|
203
|
+
# @param [String] match_str A simple string paramater to match against the subject. The search ignores
|
204
|
+
# case and does not accept regexes... only strings.
|
205
|
+
# @param [String,nil] exclude_str A string to exclude from matches against the subject. This is optional.
|
206
|
+
def search_by_subject(match_str, exclude_str = nil)
|
207
|
+
match = {:contains =>
|
208
|
+
{
|
209
|
+
:containment_mode => 'Substring',
|
210
|
+
:containment_comparison => 'IgnoreCase',
|
211
|
+
:field_uRI => {:field_uRI=>'item:Subject'},
|
212
|
+
:constant => {:value =>match_str}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
unless exclude_str.nil?
|
216
|
+
excl = {:not =>
|
217
|
+
{:contains =>
|
218
|
+
{
|
219
|
+
:containment_mode => 'Substring',
|
220
|
+
:containment_comparison => 'IgnoreCase',
|
221
|
+
:field_uRI => {:field_uRI=>'item:Subject'},
|
222
|
+
:constant => {:value =>exclude_str}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
match[:and] = [{:contains => match.delete(:contains)}, excl]
|
228
|
+
end
|
229
|
+
|
230
|
+
find_items({:restriction => match})
|
231
|
+
end
|
232
|
+
|
233
|
+
# Get Item
|
234
|
+
def get_item(item_id, change_key = nil)
|
235
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.get_item([item_id])
|
236
|
+
if(resp.status == 'Success')
|
237
|
+
item = resp.items.shift
|
238
|
+
type = item.keys.first
|
239
|
+
return eval "#{type.to_s.camel_case}.new(item[type])"
|
240
|
+
else
|
241
|
+
raise EwsError, "Could not retrieve item. #{resp.code}: #{resp.message}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Syncronize Items in this folder. If this method is issued multiple
|
246
|
+
# times it will continue where the last sync completed.
|
247
|
+
# @param [Integer] sync_amount The number of items to synchronize per sync
|
248
|
+
# @param [Boolean] sync_all Whether to sync all the data by looping through.
|
249
|
+
# The default is to just sync the first set. You can manually loop through
|
250
|
+
# with multiple calls to #sync_items!
|
251
|
+
# @return [Hash] Returns a hash with keys for each change type that ocurred.
|
252
|
+
# Possible key values are (:create/:udpate/:delete). For create and update
|
253
|
+
# changes the values are Arrays of Item or a subclass of Item. For deletes
|
254
|
+
# an array of ItemIds are returned wich is a Hash in the form:
|
255
|
+
# {:id=>"item id", :change_key=>"change key"}
|
256
|
+
# See: http://msdn.microsoft.com/en-us/library/aa565609.aspx
|
257
|
+
def sync_items!(sync_amount = 256, sync_all = false)
|
258
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.sync_folder_items(@folder_id, @sync_state, sync_amount)
|
259
|
+
parms = resp.items.shift
|
260
|
+
@sync_state = parms[:sync_state]
|
261
|
+
@synced = parms[:includes_last_item_in_range]
|
262
|
+
items = {}
|
263
|
+
resp.items.each do |i|
|
264
|
+
key = i.keys.first
|
265
|
+
items[key] = [] unless items[key].is_a?(Array)
|
266
|
+
if(key == :delete || key == :read_flag_change)
|
267
|
+
items[key] << i[key][:item_id]
|
268
|
+
else
|
269
|
+
i_type = i[key].keys.first
|
270
|
+
items[key] << (eval "#{i_type.to_s.camel_case}.new(i[key][i_type])")
|
271
|
+
end
|
272
|
+
end
|
273
|
+
items
|
274
|
+
end
|
275
|
+
|
276
|
+
# Create a subfolder of this folder
|
277
|
+
#
|
278
|
+
# @param [String] name The name of the new folder
|
279
|
+
def add_subfolder(name)
|
280
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.create_folder(@folder_id, name)
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
# Deletes this folder from the Exchange Data Store
|
285
|
+
def delete!
|
286
|
+
resp = (Viewpoint::EWS::EWS.instance).ews.delete_folder(@folder_id)
|
287
|
+
end
|
288
|
+
|
289
|
+
private
|
290
|
+
|
291
|
+
# Return the appropriate id based on whether it is a DistinguishedFolderId or
|
292
|
+
# simply just a FolderId
|
293
|
+
def self.normalize_id(folder_id)
|
294
|
+
tfolder_id = folder_id.to_s.downcase
|
295
|
+
# If the folder_id is a DistinguishedFolderId change it to a symbol so our SOAP
|
296
|
+
# method does the right thing.
|
297
|
+
@@distinguished_folder_ids.find_index(tfolder_id) ? tfolder_id.to_sym : folder_id
|
298
|
+
end
|
299
|
+
|
300
|
+
end # GenericFolder
|
301
|
+
end # EWS
|
302
|
+
end # Viewpoint
|