viewpoint 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +674 -0
- data/README +60 -0
- data/Rakefile +39 -0
- data/examples/cal2ical.rb +29 -0
- data/examples/ews_fusefs.rb +364 -0
- data/examples/webclient/.gems +2 -0
- data/examples/webclient/README +1 -0
- data/examples/webclient/config.ru +26 -0
- data/examples/webclient/ews_access_handler.rb +42 -0
- data/examples/webclient/public/css/mail.css +33 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/examples/webclient/public/css/smoothness/jquery-ui-1.7.2.custom.css +406 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/examples/webclient/public/css/ui-lightness/jquery-ui-1.7.2.custom.css +406 -0
- data/examples/webclient/public/js/jquery-1.3.2.min.js +19 -0
- data/examples/webclient/public/js/jquery-ui-1.7.2.custom.min.js +145 -0
- data/examples/webclient/viewpoint_web.rb +295 -0
- data/examples/webclient/views/_footer.haml +1 -0
- data/examples/webclient/views/_header.haml +11 -0
- data/examples/webclient/views/_tagline.haml +1 -0
- data/examples/webclient/views/index.haml +20 -0
- data/examples/webclient/views/layout.haml +42 -0
- data/examples/webclient/views/mail.haml +45 -0
- data/examples/webclient/views/welcome.haml +0 -0
- data/lib/calendar.rb +121 -0
- data/lib/calendar_item.rb +110 -0
- data/lib/event.rb +0 -0
- data/lib/exchange_headers.rb +50 -0
- data/lib/exchwebserv.rb +228 -0
- data/lib/folder.rb +269 -0
- data/lib/item.rb +56 -0
- data/lib/mail.rb +118 -0
- data/lib/message.rb +134 -0
- data/lib/soap/viewpoint.conf +3 -0
- data/lib/task.rb +0 -0
- data/lib/tasks.rb +0 -0
- data/lib/viewpoint.rb +2 -0
- data/lib/wsdl/defaultMappingRegistry.rb +10680 -0
- data/lib/wsdl/exchangeServiceBinding.rb +349 -0
- data/lib/wsdl/exchangeServiceTypes.rb +11013 -0
- data/preamble +19 -0
- data/test/spec/authtest_spec.rb +12 -0
- data/test/spec/findfolders_spec.rb +14 -0
- data/test/test_client.rb +12 -0
- data/test/testrestrict.rb +75 -0
- metadata +130 -0
data/lib/folder.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 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
|
+
require 'rubygems'
|
21
|
+
require 'viewpoint'
|
22
|
+
|
23
|
+
# This class is inherited by all folder subtypes such as Mail, Calendar,
|
24
|
+
# Tasks and Search. It will serve as the brain for all of the methods that
|
25
|
+
# each of these folder types have in common.
|
26
|
+
class Viewpoint::Folder
|
27
|
+
include Viewpoint
|
28
|
+
|
29
|
+
attr_accessor :folder_id, :parent_id, :display_name
|
30
|
+
def initialize(folder)
|
31
|
+
@folder_id = folder.folderId.xmlattr_Id
|
32
|
+
@parent_id = folder.parentFolderId.xmlattr_Id unless folder.parentFolderId == nil
|
33
|
+
@display_name = folder.displayName
|
34
|
+
@sync_state = nil
|
35
|
+
@subscription_id = nil
|
36
|
+
@watermark = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# Subscribe to folder and save the subscription_id into the database. Subsequent calls
|
40
|
+
# to check_subscription will use that id.
|
41
|
+
# Returns true if the operation is successful, false otherwise
|
42
|
+
def subscribe
|
43
|
+
subscribe = SubscribeType.new
|
44
|
+
pull = PullSubscriptionRequestType.new
|
45
|
+
|
46
|
+
# Set-up folder Id
|
47
|
+
dist_fid = DistinguishedFolderIdType.new
|
48
|
+
dist_fid.xmlattr_Id = DistinguishedFolderIdNameType::Calendar
|
49
|
+
f_ids = NonEmptyArrayOfBaseFolderIdsType.new()
|
50
|
+
f_ids.distinguishedFolderId = dist_fid
|
51
|
+
pull.folderIds = f_ids
|
52
|
+
|
53
|
+
# Set-up event types
|
54
|
+
event_types = NonEmptyArrayOfNotificationEventTypesType.new
|
55
|
+
#event_types.push(NotificationEventTypeType::NewMailEvent)
|
56
|
+
event_types.push(NotificationEventTypeType::CreatedEvent)
|
57
|
+
event_types.push(NotificationEventTypeType::DeletedEvent)
|
58
|
+
#event_types.push(NotificationEventTypeType::ModifiedEvent)
|
59
|
+
event_types.push(NotificationEventTypeType::MovedEvent)
|
60
|
+
pull.eventTypes = event_types
|
61
|
+
|
62
|
+
pull.timeout = 10
|
63
|
+
|
64
|
+
subscribe.pullSubscriptionRequest = pull
|
65
|
+
|
66
|
+
resp = ExchWebServ.instance.ews.subscribe(subscribe).responseMessages.subscribeResponseMessage[0]
|
67
|
+
@subscription_id = resp.subscriptionId
|
68
|
+
@watermark = resp.watermark
|
69
|
+
|
70
|
+
return (resp.responseCode == "NoError")? true: false
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Fetch events with the subscription_id. If one does not exists or is expired,
|
75
|
+
# call subscribe.
|
76
|
+
def check_subscription
|
77
|
+
begin
|
78
|
+
if( @subscription_id == nil or @watermark == nil) then
|
79
|
+
self.subscribe
|
80
|
+
end
|
81
|
+
ge = GetEventsType.new(@subscription_id, @watermark)
|
82
|
+
|
83
|
+
resp = ExchWebServ.instance.ews.getEvents(ge).responseMessages.getEventsResponseMessage[0]
|
84
|
+
|
85
|
+
#TODO: Add more event processing
|
86
|
+
|
87
|
+
|
88
|
+
notifications = resp.notification
|
89
|
+
|
90
|
+
# Process Notifications
|
91
|
+
if( notifications.createdEvent != nil)
|
92
|
+
notifications.createdEvent.each do |note|
|
93
|
+
@watermark = note.watermark
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
if( notifications.deletedEvent != nil)
|
98
|
+
notifications.deletedEvent.each do |note|
|
99
|
+
@watermark = note.watermark
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if( notifications.movedEvent != nil)
|
104
|
+
notifications.movedEvent.each do |note|
|
105
|
+
@watermark = note.watermark
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if( notifications.statusEvent != nil)
|
110
|
+
notifications.statusEvent.each do |note|
|
111
|
+
@watermark = note.watermark
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
return resp
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
# This is a proxy for the SyncFolderItems operation detailed here: http://msdn.microsoft.com/en-us/library/aa563967.aspx
|
122
|
+
# It returns a SyncFolderItemsResponseType object
|
123
|
+
def sync_folder(max_items = 256)
|
124
|
+
begin
|
125
|
+
# ItemResponseShapeType
|
126
|
+
itemshapeT = ItemResponseShapeType.new(DefaultShapeNamesType::IdOnly, false)
|
127
|
+
|
128
|
+
# TargetFolderIdType
|
129
|
+
tfolderidT = TargetFolderIdType.new
|
130
|
+
folderidT = FolderIdType.new
|
131
|
+
folderidT.xmlattr_Id = self.folder_id
|
132
|
+
tfolderidT.folderId = folderidT
|
133
|
+
|
134
|
+
# SyncFolderItemsType
|
135
|
+
syncitemsT = SyncFolderItemsType.new(itemshapeT,tfolderidT,self.sync_state,nil,max_items)
|
136
|
+
|
137
|
+
# Call Sync => returns SyncFolderItemsResponseType
|
138
|
+
resp = ExchWebServ.instance.ews.syncFolderItems(syncitemsT).responseMessages.syncFolderItemsResponseMessage[0]
|
139
|
+
@sync_state = resp.syncState
|
140
|
+
return resp
|
141
|
+
rescue
|
142
|
+
puts "** Something happened during synchronizing folder => #{self.display_name}"
|
143
|
+
raise
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# Wrapper around EWS's FindItem method: http://msdn.microsoft.com/en-us/library/aa566107.aspx
|
149
|
+
# The specifics of this method should be set up in the child classes and then this method should
|
150
|
+
# be called with a parameter of FindItemType: http://msdn.microsoft.com/en-us/library/aa566370.aspx
|
151
|
+
# This allows for a central place of error handling. See Calendar::get_events for an example
|
152
|
+
# of how this works.
|
153
|
+
def find_items(find_item_t)
|
154
|
+
# FindItemResponseMessageType: http://msdn.microsoft.com/en-us/library/aa566424.aspx
|
155
|
+
resp = ExchWebServ.instance.ews.findItem(find_item_t).responseMessages.findItemResponseMessage[0]
|
156
|
+
|
157
|
+
#TODO: Error handling
|
158
|
+
if resp.xmlattr_ResponseClass == "Success"
|
159
|
+
return resp
|
160
|
+
else
|
161
|
+
return nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# Fetch item by item_id
|
167
|
+
# Params: item_id: ItemIdType
|
168
|
+
# item_type: String (message, calendarItem)
|
169
|
+
# all_props: boolean; default is to get just the Default props
|
170
|
+
# Returns: a Item type of some sort ( depends on 'item_type' parameter )
|
171
|
+
def get_item(item_id, item_type = nil, all_props = false)
|
172
|
+
get_item = GetItemType.new
|
173
|
+
|
174
|
+
if all_props
|
175
|
+
shape_name = DefaultShapeNamesType::AllProperties
|
176
|
+
else
|
177
|
+
shape_name = DefaultShapeNamesType::Default
|
178
|
+
end
|
179
|
+
|
180
|
+
item_shape = ItemResponseShapeType.new( shape_name, false, BodyTypeResponseType::Text )
|
181
|
+
|
182
|
+
#additional_props = NonEmptyArrayOfPathsToElementType.new
|
183
|
+
#prop_a = PathToUnindexedFieldType.new
|
184
|
+
#prop_b = PathToUnindexedFieldType.new
|
185
|
+
#prop_c = PathToUnindexedFieldType.new
|
186
|
+
#prop_d = PathToUnindexedFieldType.new
|
187
|
+
#prop_a.xmlattr_FieldURI = UnindexedFieldURIType::CalendarMeetingTimeZone
|
188
|
+
#prop_b.xmlattr_FieldURI = UnindexedFieldURIType.new("calendar:EndTimeZone")
|
189
|
+
#prop_c.xmlattr_FieldURI = UnindexedFieldURIType::ItemInternetMessageHeaders
|
190
|
+
#prop_d.xmlattr_FieldURI = UnindexedFieldURIType::MessageFrom
|
191
|
+
#additional_props.upath << prop_a
|
192
|
+
#additional_props.upath << prop_b
|
193
|
+
#additional_props.upath << prop_c
|
194
|
+
#additional_props << prop_d
|
195
|
+
#item_shape.additionalProperties = additional_props
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
item_id_t = ItemIdType.new
|
200
|
+
item_id_t.xmlattr_Id = item_id
|
201
|
+
item_ids = NonEmptyArrayOfBaseItemIdsType.new([item_id_t])
|
202
|
+
|
203
|
+
get_item.itemShape = item_shape
|
204
|
+
get_item.itemIds= item_ids
|
205
|
+
|
206
|
+
# ItemInfoResponseMessageType: http://msdn.microsoft.com/en-us/library/aa565417.aspx
|
207
|
+
resp = ExchWebServ.instance.ews.getItem(get_item).responseMessages.getItemResponseMessage[0]
|
208
|
+
|
209
|
+
#TODO: Error handling
|
210
|
+
if resp.xmlattr_ResponseClass == "Success"
|
211
|
+
item = resp.items.send(item_type)
|
212
|
+
if( item.length > 1 )
|
213
|
+
puts "ERROR: Item Id should only resolve to a single item!"
|
214
|
+
end
|
215
|
+
return item[0]
|
216
|
+
else
|
217
|
+
return nil
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
# More info: http://msdn.microsoft.com/en-us/library/aa565781.aspx
|
223
|
+
def move_item(item_id, new_folder)
|
224
|
+
return false unless new_folder.kind_of?(Viewpoint::Folder)
|
225
|
+
|
226
|
+
folder_id_t = FolderIdType.new
|
227
|
+
folder_id_t.xmlattr_Id = new_folder.folder_id
|
228
|
+
target_folder_t = TargetFolderIdType.new(folder_id_t)
|
229
|
+
|
230
|
+
item_ids = NonEmptyArrayOfBaseItemIdsType.new
|
231
|
+
item_t = ItemIdType.new
|
232
|
+
item_t.xmlattr_Id = item_id
|
233
|
+
item_ids.itemId << item_t
|
234
|
+
|
235
|
+
move_t = MoveItemType.new(target_folder_t, item_ids)
|
236
|
+
resp = ExchWebServ.instance.ews.moveItem(move_t).responseMessages.moveItemResponseMessage.first
|
237
|
+
#TODO: Error handling
|
238
|
+
if resp.xmlattr_ResponseClass == "Success"
|
239
|
+
return true
|
240
|
+
else
|
241
|
+
return false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Delete item by item_id
|
246
|
+
# More info: http://msdn.microsoft.com/en-us/library/aa580484.aspx
|
247
|
+
def delete_item(item_id, delete_type=DisposalType::HardDelete)
|
248
|
+
item_ids = NonEmptyArrayOfBaseItemIdsType.new
|
249
|
+
item = ItemIdType.new
|
250
|
+
item.xmlattr_Id = item_id
|
251
|
+
item_ids.itemId << item
|
252
|
+
|
253
|
+
delete = DeleteItemType.new(item_ids)
|
254
|
+
delete.xmlattr_DeleteType = delete_type
|
255
|
+
resp = ExchWebServ.instance.ews.deleteItem(delete).responseMessages.deleteItemResponseMessage.first
|
256
|
+
|
257
|
+
#TODO: Error handling
|
258
|
+
if resp.xmlattr_ResponseClass == "Success"
|
259
|
+
return true
|
260
|
+
else
|
261
|
+
return false
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Move item to Deleted Items folder instead of deleting it
|
266
|
+
def recycle_item(item_id)
|
267
|
+
delete_item(item_id, DisposalType::MoveToDeletedItems)
|
268
|
+
end
|
269
|
+
end
|
data/lib/item.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 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
|
+
require 'viewpoint'
|
21
|
+
|
22
|
+
|
23
|
+
# This class is inherited by all Item subtypes such as Message, Event,
|
24
|
+
# and Task. It will serve as the brain for all of the methods that
|
25
|
+
# each of these Item types have in common.
|
26
|
+
class Viewpoint::Item
|
27
|
+
include Viewpoint
|
28
|
+
|
29
|
+
attr_accessor :item_id
|
30
|
+
|
31
|
+
# Initialize an Exchange Web Services item
|
32
|
+
def initialize(ews_item, parent_folder)
|
33
|
+
@item_id = ews_item.itemId.xmlattr_Id
|
34
|
+
@parent_folder = parent_folder
|
35
|
+
end
|
36
|
+
|
37
|
+
# Takes an object of type Viewpoint::Folder as an argument
|
38
|
+
# Returns a boolean value, true if the move ocurred, false otherwise.
|
39
|
+
def move_to!(new_folder)
|
40
|
+
retval = @parent_folder.move_item(@item_id, new_folder)
|
41
|
+
@parent_folder = new_folder if retval
|
42
|
+
|
43
|
+
return retval
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Returns a boolean value, true if the delete ocurred, false otherwise.
|
48
|
+
def delete!
|
49
|
+
@parent_folder.delete_item(@item_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns a boolean value, true if the recycle ocurred, false otherwise.
|
53
|
+
def recycle!
|
54
|
+
@parent_folder.recycle_item(@item_id)
|
55
|
+
end
|
56
|
+
end
|
data/lib/mail.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 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
|
+
$:.unshift(File.dirname(__FILE__))
|
21
|
+
require 'rubygems'
|
22
|
+
require 'wsdl/exchangeServiceBinding'
|
23
|
+
# --- Folder Types ---
|
24
|
+
require 'folder'
|
25
|
+
# --- Item Types ---
|
26
|
+
require 'message'
|
27
|
+
|
28
|
+
require 'viewpoint'
|
29
|
+
|
30
|
+
|
31
|
+
class Viewpoint::MailFolder < Viewpoint::Folder
|
32
|
+
include Viewpoint
|
33
|
+
|
34
|
+
# initialize with an item of MailFolderType
|
35
|
+
def initialize(folder)
|
36
|
+
super(folder)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_todays_messages
|
40
|
+
get_messages( DateTime.parse(Date.today.to_s).to_s )
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get messages between a certain time period. Defaults to "today"
|
44
|
+
# Input: DateTime of start, DateTime of end
|
45
|
+
# This method will return an Array of Message
|
46
|
+
def get_messages(since = (DateTime.parse(Date.today.to_s)) )
|
47
|
+
# Set-up FindItemType
|
48
|
+
find_item_t = FindItemType.new
|
49
|
+
find_item_t.xmlattr_Traversal = ItemQueryTraversalType::Shallow
|
50
|
+
item_shape = ItemResponseShapeType.new(DefaultShapeNamesType::IdOnly, false)
|
51
|
+
|
52
|
+
additional_props = NonEmptyArrayOfPathsToElementType.new
|
53
|
+
prop_a = PathToUnindexedFieldType.new
|
54
|
+
prop_b = PathToUnindexedFieldType.new
|
55
|
+
prop_c = PathToUnindexedFieldType.new
|
56
|
+
prop_d = PathToUnindexedFieldType.new
|
57
|
+
prop_e = PathToUnindexedFieldType.new
|
58
|
+
prop_f = PathToUnindexedFieldType.new
|
59
|
+
prop_a.xmlattr_FieldURI = UnindexedFieldURIType::ItemSubject
|
60
|
+
prop_b.xmlattr_FieldURI = UnindexedFieldURIType::ItemDateTimeReceived
|
61
|
+
prop_c.xmlattr_FieldURI = UnindexedFieldURIType::MessageSender
|
62
|
+
prop_d.xmlattr_FieldURI = UnindexedFieldURIType::MessageFrom
|
63
|
+
prop_e.xmlattr_FieldURI = UnindexedFieldURIType::MessageIsRead
|
64
|
+
prop_f.xmlattr_FieldURI = UnindexedFieldURIType::MessageInternetMessageId
|
65
|
+
additional_props.upath << prop_a
|
66
|
+
additional_props.upath << prop_b
|
67
|
+
additional_props.upath << prop_c
|
68
|
+
additional_props.upath << prop_d
|
69
|
+
additional_props.upath << prop_e
|
70
|
+
additional_props.upath << prop_f
|
71
|
+
item_shape.additionalProperties = additional_props
|
72
|
+
find_item_t.itemShape = item_shape
|
73
|
+
|
74
|
+
|
75
|
+
# Set-up folder Ids to search in
|
76
|
+
folder_ids = NonEmptyArrayOfBaseFolderIdsType.new()
|
77
|
+
dist_folder = DistinguishedFolderIdType.new
|
78
|
+
dist_folder.xmlattr_Id = DistinguishedFolderIdNameType.new(@display_name.downcase)
|
79
|
+
folder_ids.distinguishedFolderId = dist_folder
|
80
|
+
find_item_t.parentFolderIds = folder_ids
|
81
|
+
|
82
|
+
|
83
|
+
# Set-up date-based restriction.
|
84
|
+
restriction = RestrictionType.new
|
85
|
+
search_type = IsGreaterThanOrEqualToType.new
|
86
|
+
fielduri = PathToUnindexedFieldType.new
|
87
|
+
fielduri.xmlattr_FieldURI = UnindexedFieldURIType::ItemDateTimeReceived
|
88
|
+
const = FieldURIOrConstantType.new
|
89
|
+
c = ConstantValueType.new
|
90
|
+
c.xmlattr_Value = (DateTime.now - 2).new_offset(0).to_s
|
91
|
+
const.constant = c
|
92
|
+
search_type.path = fielduri
|
93
|
+
search_type.fieldURIOrConstant = const
|
94
|
+
restriction.isGreaterThanOrEqualTo = search_type
|
95
|
+
|
96
|
+
find_item_t.restriction = restriction
|
97
|
+
|
98
|
+
resp = find_items(find_item_t)
|
99
|
+
|
100
|
+
if resp != nil
|
101
|
+
messages = []
|
102
|
+
resp.rootFolder.items.message.each do |msg|
|
103
|
+
messages << Message.new(msg, self)
|
104
|
+
end
|
105
|
+
|
106
|
+
return messages
|
107
|
+
else
|
108
|
+
return resp
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
# See docs for Folder::get_item
|
115
|
+
def get_item(item_id)
|
116
|
+
msg = super(item_id, "message", true)
|
117
|
+
end
|
118
|
+
end
|
data/lib/message.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# Copyright © 2009 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
|
+
$:.unshift(File.dirname(__FILE__))
|
21
|
+
require 'item'
|
22
|
+
require 'viewpoint'
|
23
|
+
|
24
|
+
class Viewpoint::Message < Viewpoint::Item
|
25
|
+
include Viewpoint
|
26
|
+
|
27
|
+
attr_reader :subject, :parent_folder, :sender, :date_time_recieved
|
28
|
+
attr_reader :ews_item if $DEBUG
|
29
|
+
|
30
|
+
# Initialize an Exchange Web Services item of MessageType
|
31
|
+
def initialize(ews_item, parent_folder)
|
32
|
+
# keep this now for debuging
|
33
|
+
@ews_item = ews_item if $DEBUG
|
34
|
+
@subject = ews_item.subject # String
|
35
|
+
@sender = ews_item.sender.mailbox.name if ews_item.sender # String
|
36
|
+
@recipients =
|
37
|
+
@is_read = ews_item.isRead # boolean
|
38
|
+
@date_time_recieved = ews_item.dateTimeReceived # DateTime
|
39
|
+
|
40
|
+
# This is where the entire message 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
|
+
def body
|
49
|
+
get_message if @message == nil
|
50
|
+
return @message.body
|
51
|
+
end
|
52
|
+
|
53
|
+
def recipients
|
54
|
+
get_message if @message == nil
|
55
|
+
to_recipients = ''
|
56
|
+
@message.toRecipients.each do |r|
|
57
|
+
to_recipients += ', ' if to_recipients != ''
|
58
|
+
to_recipients += "#{r.name} <#{r.emailAddress}>"
|
59
|
+
end
|
60
|
+
|
61
|
+
return to_recipients
|
62
|
+
end
|
63
|
+
|
64
|
+
def cc_recipients
|
65
|
+
get_message if @message == nil
|
66
|
+
if( @message.ccRecipients != nil)
|
67
|
+
cc = ''
|
68
|
+
@message.ccRecipients.each do |r|
|
69
|
+
cc += ', ' if cc != ''
|
70
|
+
cc += "#{r.name} <#{r.emailAddress}>"
|
71
|
+
end
|
72
|
+
return cc
|
73
|
+
end
|
74
|
+
return nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def bcc_recipients
|
78
|
+
get_message if @message == nil
|
79
|
+
if( @message.bccRecipients != nil)
|
80
|
+
bcc = ''
|
81
|
+
@message.bccRecipients.each do |r|
|
82
|
+
bcc += ', ' if bcc != ''
|
83
|
+
bcc += "#{r.name} <#{r.emailAddress}>"
|
84
|
+
end
|
85
|
+
return bcc
|
86
|
+
end
|
87
|
+
return nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_message
|
91
|
+
@message = @parent_folder.get_item(@item_id)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Output the message in RFC 822 format: http://www.ietf.org/rfc/rfc0822.txt
|
95
|
+
def to_rfc822
|
96
|
+
get_message if @message == nil
|
97
|
+
rfc822 = []
|
98
|
+
rfc822.push 'Return-Path' => @message.sender.mailbox.emailAddress
|
99
|
+
rfc822.push 'Delivered-To' => @message.receivedBy.mailbox.emailAddress
|
100
|
+
@message.internetMessageHeaders.each do |hdr|
|
101
|
+
# TODO: Quick Fix... needs more research
|
102
|
+
if( hdr.xmlattr_HeaderName == 'Content-Type' && hdr =~ /tnef/ )
|
103
|
+
rfc822.push hdr.xmlattr_HeaderName => 'multipart/alternative'
|
104
|
+
else
|
105
|
+
rfc822.push hdr.xmlattr_HeaderName => hdr
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# From
|
110
|
+
rfc822.push 'From' => "#{@message.sender.mailbox.name} <#{@message.sender.mailbox.emailAddress}>"
|
111
|
+
|
112
|
+
# To
|
113
|
+
rfc822.push 'To' => self.recipients
|
114
|
+
|
115
|
+
# CC
|
116
|
+
if( ( cc = self.cc_recipients) != nil)
|
117
|
+
rfc822.push 'Cc' => cc
|
118
|
+
end
|
119
|
+
|
120
|
+
# BCC
|
121
|
+
if( ( bcc = self.bcc_recipients) != nil)
|
122
|
+
rfc822.push 'Bcc' => bcc
|
123
|
+
end
|
124
|
+
|
125
|
+
rfc822_msg = ""
|
126
|
+
rfc822.each do |line|
|
127
|
+
line.each_pair do |key,val|
|
128
|
+
rfc822_msg += "#{key}: #{val}\n"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
rfc822_msg += "\n\n#{@message.body}"
|
133
|
+
end
|
134
|
+
end
|