sonar_rexchange 0.3.7
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/.gitignore +22 -0
- data/LICENSE +20 -0
- data/RAKEFILE +50 -0
- data/README +89 -0
- data/REXCHANGE-CHANGELOG +52 -0
- data/REXCHANGE-MIT-LICENSE +22 -0
- data/VERSION +1 -0
- data/lib/r_exchange.rb +2 -0
- data/lib/rexchange.rb +33 -0
- data/lib/rexchange/appointment.rb +38 -0
- data/lib/rexchange/contact.rb +29 -0
- data/lib/rexchange/credentials.rb +38 -0
- data/lib/rexchange/dav_delete_request.rb +30 -0
- data/lib/rexchange/dav_get_request.rb +28 -0
- data/lib/rexchange/dav_mkcol_request.rb +27 -0
- data/lib/rexchange/dav_move_request.rb +30 -0
- data/lib/rexchange/dav_proppatch_request.rb +49 -0
- data/lib/rexchange/dav_search_request.rb +8 -0
- data/lib/rexchange/exchange_request.rb +86 -0
- data/lib/rexchange/folder.rb +108 -0
- data/lib/rexchange/generic_item.rb +124 -0
- data/lib/rexchange/message.rb +88 -0
- data/lib/rexchange/message_href.rb +107 -0
- data/lib/rexchange/note.rb +16 -0
- data/lib/rexchange/r_exception.rb +25 -0
- data/lib/rexchange/session.rb +28 -0
- data/lib/rexchange/task.rb +26 -0
- data/test/functional.rb +23 -0
- metadata +92 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rexchange/generic_item'
|
2
|
+
require 'rexchange/dav_proppatch_request'
|
3
|
+
|
4
|
+
module RExchange
|
5
|
+
class Message < GenericItem
|
6
|
+
|
7
|
+
set_folder_type 'mail'
|
8
|
+
|
9
|
+
attribute_mappings :from => 'urn:schemas:httpmail:from',
|
10
|
+
:to => 'urn:schemas:httpmail:to',
|
11
|
+
:message_id => 'urn:schemas:mailheader:message-id',
|
12
|
+
:subject => 'urn:schemas:httpmail:subject',
|
13
|
+
:recieved_on => 'urn:schemas:httpmail:date',
|
14
|
+
:importance => 'urn:schemas:httpmail:importance',
|
15
|
+
:has_attachments? => 'urn:schemas:httpmail:hasattachment',
|
16
|
+
:body => 'urn:schemas:httpmail:textdescription',
|
17
|
+
:html => 'urn:schemas:httpmail:htmldescription'
|
18
|
+
|
19
|
+
|
20
|
+
# Move this message to the specified folder.
|
21
|
+
# The folder can be a string such as 'inbox/archive' or a RExchange::Folder.
|
22
|
+
# === Example
|
23
|
+
# mailbox.inbox.each do |message|
|
24
|
+
# message.move_to mailbox.inbox.archive
|
25
|
+
# end
|
26
|
+
def move_to(folder)
|
27
|
+
destination =
|
28
|
+
if folder.is_a?(RExchange::Folder)
|
29
|
+
folder.to_s.ensure_ends_with('/') + self.href.split('/').last
|
30
|
+
else
|
31
|
+
@session.uri.path.ensure_ends_with('/') + folder.to_s.ensure_ends_with('/') + self.href.split('/').last
|
32
|
+
end
|
33
|
+
|
34
|
+
DavMoveRequest.execute(@session, self.href, destination)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Delete this message.
|
38
|
+
# === Example
|
39
|
+
# mailbox.inbox.each do |message|
|
40
|
+
# message.delete!
|
41
|
+
# end
|
42
|
+
def delete!
|
43
|
+
response = DavDeleteRequest.execute(@session, self.href)
|
44
|
+
case response.code
|
45
|
+
when 204 then
|
46
|
+
# Standard success response. ( http://msdn.microsoft.com/en-us/library/aa142839(EXCHG.65).aspx )
|
47
|
+
true
|
48
|
+
when 423 then
|
49
|
+
# The destination resource is locked.
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"To: #{to}, From: #{from}, Subject: #{subject}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def raw
|
60
|
+
fetch(href, limit = 10)
|
61
|
+
end
|
62
|
+
|
63
|
+
def fetch(uri_str, limit = 10)
|
64
|
+
# You should choose better exception.
|
65
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
66
|
+
response = DavGetRequest.execute(@session, uri_str)
|
67
|
+
case response
|
68
|
+
when Net::HTTPSuccess then
|
69
|
+
response.body
|
70
|
+
when Net::HTTPRedirection then
|
71
|
+
fetch(response['location'], limit - 1)
|
72
|
+
else
|
73
|
+
response.error!
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def mark_as_read
|
78
|
+
response = DavProppatchRequest.execute(@session, self.href, RExchange::PR_HTTPMAIL_READ, RExchange::NS_HTTPMAIL, 1)
|
79
|
+
case response
|
80
|
+
when Net::HTTPSuccess then
|
81
|
+
true
|
82
|
+
else
|
83
|
+
false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'rexchange/dav_delete_request'
|
2
|
+
require 'rexchange/dav_proppatch_request'
|
3
|
+
|
4
|
+
module RExchange
|
5
|
+
class MessageHref
|
6
|
+
|
7
|
+
def initialize(session, href)
|
8
|
+
@href = href
|
9
|
+
@session = session
|
10
|
+
end
|
11
|
+
|
12
|
+
# Move this message to the specified folder.
|
13
|
+
# The folder can be a string such as 'inbox/archive' or a RExchange::Folder.
|
14
|
+
# === Example
|
15
|
+
# mailbox.inbox.each do |message|
|
16
|
+
# message.move_to mailbox.inbox.archive
|
17
|
+
# end
|
18
|
+
def move_to(folder)
|
19
|
+
|
20
|
+
destination =
|
21
|
+
if folder.is_a?(RExchange::Folder)
|
22
|
+
folder.to_s.ensure_ends_with('/') + @href.split('/').last
|
23
|
+
else
|
24
|
+
@session.uri.path.ensure_ends_with('/') + folder.to_s.ensure_ends_with('/') + @href.split('/').last
|
25
|
+
end
|
26
|
+
|
27
|
+
DavMoveRequest.execute(@session, @href, destination)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Delete this message.
|
31
|
+
# === Example
|
32
|
+
# mailbox.inbox.each do |message|
|
33
|
+
# message.delete!
|
34
|
+
# end
|
35
|
+
def delete!
|
36
|
+
uri_str = @href
|
37
|
+
response = DavDeleteRequest.execute(@session, @href)
|
38
|
+
case response.code
|
39
|
+
when 204 then
|
40
|
+
# Standard success response. ( http://msdn.microsoft.com/en-us/library/aa142839(EXCHG.65).aspx )
|
41
|
+
true
|
42
|
+
when 423 then
|
43
|
+
# The destination resource is locked.
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
"Href: #{@href}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def raw
|
53
|
+
# memoization of the raw contents
|
54
|
+
@raw ||= fetch(@href, limit = 10)
|
55
|
+
end
|
56
|
+
|
57
|
+
def fetch(uri_str, limit = 10)
|
58
|
+
# You should choose better exception.
|
59
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
60
|
+
response = DavGetRequest.execute(@session, uri_str)
|
61
|
+
case response
|
62
|
+
when Net::HTTPSuccess then
|
63
|
+
response.body
|
64
|
+
when Net::HTTPRedirection then
|
65
|
+
fetch(response['location'], limit - 1)
|
66
|
+
else
|
67
|
+
puts "URI #{@href}"
|
68
|
+
response.error!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def mark_as_read
|
73
|
+
DavProppatchRequest.execute(@session, @href, RExchange::PR_HTTPMAIL_READ, RExchange::NS_HTTPMAIL, 1)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.query(path)
|
77
|
+
<<-QBODY
|
78
|
+
SELECT
|
79
|
+
"DAV:href"
|
80
|
+
FROM SCOPE('shallow traversal of "#{path}"')
|
81
|
+
WHERE "DAV:ishidden" = false
|
82
|
+
AND "DAV:isfolder" = false
|
83
|
+
|
84
|
+
QBODY
|
85
|
+
# AND "DAV:contentclass" = 'urn:content-classes:message'
|
86
|
+
end
|
87
|
+
|
88
|
+
# Retrieve an Array of hrefs to items (such as Contact, Message, etc)
|
89
|
+
def self.find_message_hrefs(href_regex, credentials, path, conditions = nil)
|
90
|
+
qbody = <<-QBODY
|
91
|
+
<D:searchrequest xmlns:D = "DAV:">
|
92
|
+
<D:sql>
|
93
|
+
#{query(path)}
|
94
|
+
</D:sql>
|
95
|
+
</D:searchrequest>
|
96
|
+
QBODY
|
97
|
+
items = []
|
98
|
+
DavSearchRequest.execute(credentials, :body => qbody) do |response|
|
99
|
+
response.body.scan(href_regex){|m|
|
100
|
+
items << self.new(credentials, m[0]) if m[0]
|
101
|
+
}
|
102
|
+
end
|
103
|
+
items
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rexchange/generic_item'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
class Note < GenericItem
|
5
|
+
|
6
|
+
set_folder_type 'note'
|
7
|
+
|
8
|
+
attribute_mappings :displayname => 'DAV:displayname',
|
9
|
+
:created_at => 'DAV:creationdate',
|
10
|
+
:subject =>'urn:schemas:httpmail:subject',
|
11
|
+
:body => 'urn:schemas:httpmail:textdescription'
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module RExchange
|
3
|
+
class RException < Exception
|
4
|
+
|
5
|
+
attr_reader :req, :res
|
6
|
+
|
7
|
+
def initialize(req, res, oryg)
|
8
|
+
super(oryg.to_s)
|
9
|
+
set_backtrace oryg.backtrace
|
10
|
+
@oryg = oryg
|
11
|
+
@req = req
|
12
|
+
@res = res
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
inspect
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#{super.inspect} req:#{@req.inspect} body:[#{@req.body}] headers:[#{@req.to_hash}] href:[#{@req.path}] res:#{@res.inspect} oryginal message:#{@oryg.message} ."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rexchange/folder'
|
3
|
+
require 'rexchange/credentials'
|
4
|
+
|
5
|
+
module RExchange
|
6
|
+
|
7
|
+
class Session < Folder
|
8
|
+
|
9
|
+
# Creates a Credentials instance to pass to subfolders
|
10
|
+
# === Example
|
11
|
+
# RExchange::Session.new('https://mydomain.com/exchange/demo', 'https://mydomain.com/owa/auth/owaauth.dll', 'mydomain\\bob', 'secret') do |mailbox|
|
12
|
+
# mailbox.test.each do |message|
|
13
|
+
# puts message.subject
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
def initialize(dav_uri, owa_uri, username = nil, password = nil)
|
17
|
+
|
18
|
+
@credentials = Credentials.new(dav_uri, owa_uri, username, password)
|
19
|
+
@parent = @credentials.dav_uri.path
|
20
|
+
@folder = ''
|
21
|
+
@href = @credentials.dav_uri.to_s
|
22
|
+
|
23
|
+
yield(self) if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rexchange/generic_item'
|
2
|
+
|
3
|
+
module RExchange
|
4
|
+
class Task < GenericItem
|
5
|
+
|
6
|
+
set_folder_type 'task'
|
7
|
+
|
8
|
+
attribute_mappings :displayname => 'DAV:displayname',
|
9
|
+
:created_at => 'DAV:creationdate',
|
10
|
+
:subject =>'urn:schemas:httpmail:subject',
|
11
|
+
:body => 'urn:schemas:httpmail:textdescription',
|
12
|
+
:percent_complete =>'http://schemas.microsoft.com/exchange/tasks/percentcomplete',
|
13
|
+
:owner =>'http://schemas.microsoft.com/exchange/tasks/owner',
|
14
|
+
:is_complete =>'http://schemas.microsoft.com/exchange/tasks/is_complete',
|
15
|
+
:date_start =>'http://schemas.microsoft.com/exchange/tasks/dtstart',
|
16
|
+
:date_due =>'http://schemas.microsoft.com/exchange/tasks/dtdue',
|
17
|
+
:actual_effort =>'http://schemas.microsoft.com/exchange/tasks/actualeffort',
|
18
|
+
:estimated_effort =>'http://schemas.microsoft.com/exchange/tasks/estimatedeffort',
|
19
|
+
:priority =>'http://schemas.microsoft.com/mapi/priority',
|
20
|
+
:status =>'http://schemas.microsoft.com/exchange/tasks/status',
|
21
|
+
:state =>'http://schemas.microsoft.com/exchange/tasks/state'
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
end
|
data/test/functional.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rexchange'
|
3
|
+
|
4
|
+
class FunctionalTests < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@mailbox = RExchange::Session.new 'url', 'username', 'password'
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@mailbox = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# Ok, so it's not a real test, but I needed to get started,
|
15
|
+
# and get rid of console scripts.
|
16
|
+
def test_no_exceptions
|
17
|
+
|
18
|
+
@mailbox.inbox.search(:from => 'scott').each do |m|
|
19
|
+
puts m.subject
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sonar_rexchange
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 3
|
8
|
+
- 7
|
9
|
+
version: 0.3.7
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter MacRobert
|
13
|
+
- Daniel Kwiecinski
|
14
|
+
- Craig McMillan
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-07-28 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: The sonar_rexchange gem imports and fixes bugs in the rexchange gem.
|
24
|
+
email: hello@empire42.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files:
|
30
|
+
- LICENSE
|
31
|
+
- README
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- LICENSE
|
35
|
+
- RAKEFILE
|
36
|
+
- README
|
37
|
+
- REXCHANGE-CHANGELOG
|
38
|
+
- REXCHANGE-MIT-LICENSE
|
39
|
+
- VERSION
|
40
|
+
- lib/r_exchange.rb
|
41
|
+
- lib/rexchange.rb
|
42
|
+
- lib/rexchange/appointment.rb
|
43
|
+
- lib/rexchange/contact.rb
|
44
|
+
- lib/rexchange/credentials.rb
|
45
|
+
- lib/rexchange/dav_delete_request.rb
|
46
|
+
- lib/rexchange/dav_get_request.rb
|
47
|
+
- lib/rexchange/dav_mkcol_request.rb
|
48
|
+
- lib/rexchange/dav_move_request.rb
|
49
|
+
- lib/rexchange/dav_proppatch_request.rb
|
50
|
+
- lib/rexchange/dav_search_request.rb
|
51
|
+
- lib/rexchange/exchange_request.rb
|
52
|
+
- lib/rexchange/folder.rb
|
53
|
+
- lib/rexchange/generic_item.rb
|
54
|
+
- lib/rexchange/message.rb
|
55
|
+
- lib/rexchange/message_href.rb
|
56
|
+
- lib/rexchange/note.rb
|
57
|
+
- lib/rexchange/r_exception.rb
|
58
|
+
- lib/rexchange/session.rb
|
59
|
+
- lib/rexchange/task.rb
|
60
|
+
- test/functional.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/trampoline/sonar-rexchange
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options:
|
67
|
+
- --charset=UTF-8
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.3.6
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Modified rexchange gem
|
91
|
+
test_files:
|
92
|
+
- test/functional.rb
|