viewpoint 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/COPYING.txt +674 -0
  2. data/README +60 -0
  3. data/Rakefile +39 -0
  4. data/examples/cal2ical.rb +29 -0
  5. data/examples/ews_fusefs.rb +364 -0
  6. data/examples/webclient/.gems +2 -0
  7. data/examples/webclient/README +1 -0
  8. data/examples/webclient/config.ru +26 -0
  9. data/examples/webclient/ews_access_handler.rb +42 -0
  10. data/examples/webclient/public/css/mail.css +33 -0
  11. data/examples/webclient/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  12. data/examples/webclient/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  13. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  14. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  15. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  16. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  17. data/examples/webclient/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  18. data/examples/webclient/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  19. data/examples/webclient/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  20. data/examples/webclient/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  21. data/examples/webclient/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  22. data/examples/webclient/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  23. data/examples/webclient/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  24. data/examples/webclient/public/css/smoothness/jquery-ui-1.7.2.custom.css +406 -0
  25. data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  26. data/examples/webclient/public/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  27. data/examples/webclient/public/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  28. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  29. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  30. data/examples/webclient/public/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  31. data/examples/webclient/public/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  32. data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  33. data/examples/webclient/public/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  34. data/examples/webclient/public/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  35. data/examples/webclient/public/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  36. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  37. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  38. data/examples/webclient/public/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  39. data/examples/webclient/public/css/ui-lightness/jquery-ui-1.7.2.custom.css +406 -0
  40. data/examples/webclient/public/js/jquery-1.3.2.min.js +19 -0
  41. data/examples/webclient/public/js/jquery-ui-1.7.2.custom.min.js +145 -0
  42. data/examples/webclient/viewpoint_web.rb +295 -0
  43. data/examples/webclient/views/_footer.haml +1 -0
  44. data/examples/webclient/views/_header.haml +11 -0
  45. data/examples/webclient/views/_tagline.haml +1 -0
  46. data/examples/webclient/views/index.haml +20 -0
  47. data/examples/webclient/views/layout.haml +42 -0
  48. data/examples/webclient/views/mail.haml +45 -0
  49. data/examples/webclient/views/welcome.haml +0 -0
  50. data/lib/calendar.rb +121 -0
  51. data/lib/calendar_item.rb +110 -0
  52. data/lib/event.rb +0 -0
  53. data/lib/exchange_headers.rb +50 -0
  54. data/lib/exchwebserv.rb +228 -0
  55. data/lib/folder.rb +269 -0
  56. data/lib/item.rb +56 -0
  57. data/lib/mail.rb +118 -0
  58. data/lib/message.rb +134 -0
  59. data/lib/soap/viewpoint.conf +3 -0
  60. data/lib/task.rb +0 -0
  61. data/lib/tasks.rb +0 -0
  62. data/lib/viewpoint.rb +2 -0
  63. data/lib/wsdl/defaultMappingRegistry.rb +10680 -0
  64. data/lib/wsdl/exchangeServiceBinding.rb +349 -0
  65. data/lib/wsdl/exchangeServiceTypes.rb +11013 -0
  66. data/preamble +19 -0
  67. data/test/spec/authtest_spec.rb +12 -0
  68. data/test/spec/findfolders_spec.rb +14 -0
  69. data/test/test_client.rb +12 -0
  70. data/test/testrestrict.rb +75 -0
  71. metadata +130 -0
@@ -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
@@ -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
@@ -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
@@ -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