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