rexchange 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ -- 0.2.0:
2
+ * Fixed a bug in Message#move_to when passing folders
3
+ * Added support for Contact browsing
4
+ * Added GenericItem to abstract Contacts and Messages
5
+ * Renamed Folder#messages to Folder#get_messages to avoid naming collisions
6
+
1
7
  -- 0.1.4:
2
8
  * Moved Folder::normalize_folder_name to String#normalize, and added support for MixedCase sources.
3
9
  * Fixed a bug where the normalized folder name was being used for the Folder#to_s result.
data/RAKEFILE CHANGED
@@ -7,7 +7,7 @@ require 'rake/gempackagetask'
7
7
  require 'rake/contrib/rubyforgepublisher'
8
8
  require 'pscp'
9
9
 
10
- PACKAGE_VERSION = '0.1.4'
10
+ PACKAGE_VERSION = '0.2.0'
11
11
 
12
12
  PACKAGE_FILES = FileList[
13
13
  'README',
@@ -0,0 +1,2 @@
1
+ # Provided for compatibility with RubyOnRails auto-require functionality.
2
+ require 'rexchange'
@@ -1,8 +1,22 @@
1
1
  require 'rexchange/session'
2
2
 
3
+ class String
4
+ def ends_with?(partial)
5
+ self[self.size - partial.size..self.size] == partial
6
+ end
7
+
8
+ def ensure_ends_with(partial)
9
+ self.ends_with?(partial) ? self : self + partial
10
+ end
11
+
12
+ def normalize
13
+ self.split(/(?=[A-Z][a-z]*)/).join('_').tr('- ', '_').squeeze('_').downcase
14
+ end
15
+ end
16
+
3
17
  module RExchange
4
18
  # Use STDOUT or another stream if you'd like to capture the HTTP debug output
5
- DEBUG_STREAM = nil
19
+ DEBUG_STREAM = $log
6
20
 
7
21
  # A shortcut to RExchange::Session#new's block syntax
8
22
  def self.open(uri, options = {})
@@ -0,0 +1,45 @@
1
+ require 'rexchange/generic_item'
2
+
3
+ module RExchange
4
+ class Contact < GenericItem
5
+
6
+ attribute_mappings :first_name => 'given_name',
7
+ :middle_name => 'middlename',
8
+ :last_name => 'sn',
9
+ :created_at => 'creationdate',
10
+ :address => 'mailingstreet',
11
+ :city => 'mailingcity',
12
+ :state => 'st',
13
+ :zip_code => 'mailingpostalcode',
14
+ :country => 'co',
15
+ :phone => 'home_phone',
16
+ :business_phone => 'telephone_number',
17
+ :fax => 'facsimiletelephonenumber',
18
+ :email => 'email1',
19
+ :website => 'businesshomepage',
20
+ :company => 'o'
21
+
22
+ def self.query(path)
23
+ <<-QBODY
24
+ <?xml version="1.0"?>
25
+ <D:searchrequest xmlns:D = "DAV:">
26
+ <D:sql>
27
+ SELECT "urn:schemas:contacts:givenName", "urn:schemas:contacts:middlename",
28
+ "urn:schemas:contacts:sn", "urn:schemas:contacts:title",
29
+ "urn:schemas:contacts:mailingstreet", "urn:schemas:contacts:mailingcity",
30
+ "urn:schemas:contacts:st", "urn:schemas:contacts:mailingpostalcode",
31
+ "urn:schemas:contacts:co", "urn:schemas:contacts:homePhone",
32
+ "urn:schemas:contacts:telephoneNumber", "urn:schemas:contacts:facsimiletelephonenumber",
33
+ "urn:schemas:contacts:mobile", "urn:schemas:contacts:email1",
34
+ "urn:schemas:contacts:businesshomepage", "urn:schemas:contacts:o", "DAV:creationdate"
35
+ FROM SCOPE('shallow traversal of "#{path}"')
36
+ WHERE "DAV:ishidden" = false
37
+ AND "DAV:isfolder" = false
38
+ AND "DAV:contentclass" = 'urn:content-classes:person'
39
+ </D:sql>
40
+ </D:searchrequest>
41
+ QBODY
42
+ end
43
+
44
+ end
45
+ end
@@ -1,8 +1,8 @@
1
1
  require 'rexml/document'
2
2
  require 'net/https'
3
- require 'rexchange/extensions'
4
3
  require 'rexchange/dav_search_request'
5
4
  require 'rexchange/message'
5
+ require 'rexchange/contact'
6
6
 
7
7
  module RExchange
8
8
 
@@ -31,8 +31,12 @@ module RExchange
31
31
 
32
32
  # Iterate through each RExchange::Message in this folder
33
33
  def each
34
- messages.each do |msg|
35
- yield msg
34
+ if @folder =~ /^contacts$/i || @parent =~ /\/contacts\//i
35
+ get_contacts
36
+ else
37
+ get_messages
38
+ end.each do |item|
39
+ yield item
36
40
  end
37
41
  end
38
42
 
@@ -46,13 +50,17 @@ module RExchange
46
50
  def messages_in(folder)
47
51
  folder.split('/').inject(@credentials.uri.path) do |final_path, current_path|
48
52
  Folder.new(@credentials, final_path, current_path)
49
- end.messages
53
+ end.get_messages
50
54
  end
51
55
 
52
- def messages
56
+ def get_messages
53
57
  RExchange::Message::find(@credentials, to_s)
54
58
  end
55
59
 
60
+ def get_contacts
61
+ RExchange::Contact::find(@credentials, to_s)
62
+ end
63
+
56
64
  # Join the strings passed in with '/'s between them
57
65
  def self.join(*args)
58
66
  args.collect { |f| f.to_s.ensure_ends_with('/') }.to_s.squeeze('/')
@@ -0,0 +1,64 @@
1
+ require 'rexml/document'
2
+ require 'ostruct'
3
+ require 'rexchange/dav_move_request'
4
+ require 'time'
5
+
6
+ module RExchange
7
+ class GenericItem
8
+ include REXML
9
+ include Enumerable
10
+
11
+ attr_accessor :attributes
12
+
13
+ # Used to access the attributes of the item as a hash.
14
+ def [](key)
15
+ return @attributes[key]
16
+ end
17
+
18
+ # Used to access the attributes of the item.
19
+ def method_missing(sym, *args)
20
+ return @attributes[sym.to_s] if @attributes.include?(sym.to_s)
21
+ end
22
+
23
+ def initialize(session, dav_property_node)
24
+ @attributes = {}
25
+ @session = session
26
+
27
+ dav_property_node.elements.each do |element|
28
+ if element.name.normalize =~ /date$/i
29
+ @attributes[element.name.normalize] = Time::parse(element.text)
30
+ else
31
+ @attributes[element.name.normalize] = element.text
32
+ end
33
+ end
34
+
35
+ return self
36
+ end
37
+
38
+ def self.attribute_mappings(mappings)
39
+ mappings.each_pair do |k,v|
40
+ define_method k do
41
+ @attributes[v]
42
+ end
43
+ end
44
+ end
45
+
46
+ def self.query(path)
47
+ raise 'YOU MUST DEFINE THIS'
48
+ end
49
+
50
+ # Retrieve an Array of items (such as Contact, Message, etc)
51
+ def self.find(credentials, path)
52
+ response = DavSearchRequest.execute(credentials, :body => query(path))
53
+
54
+ items = []
55
+ xpath_query = "//a:propstat[a:status/text() = 'HTTP/1.1 200 OK']/a:prop"
56
+
57
+ Document.new(response.body).elements.each(xpath_query) do |m|
58
+ items << self.new(credentials, m)
59
+ end
60
+
61
+ return items
62
+ end
63
+ end
64
+ end
@@ -1,40 +1,13 @@
1
- require 'rexml/document'
2
- require 'ostruct'
3
- require 'rexchange/dav_move_request'
1
+ require 'rexchange/generic_item'
4
2
 
5
3
  module RExchange
6
- class Message
7
- include REXML
8
- include Enumerable
9
-
10
- attr_accessor :attributes
4
+ class Message < GenericItem
11
5
 
12
6
  def to_s
13
7
  "To: #{to}, From: #{from}, Subject: #{subject}"
14
8
  end
15
9
 
16
- # Used to access the attributes of the message as a hash.
17
- def [](key)
18
- return @attributes[key]
19
- end
20
-
21
- # Used to access the attributes of the message. The following are available:
22
- # * href
23
- # * from
24
- # * to
25
- # * subject
26
- # * message-id
27
- # * date
28
- # * importance
29
- # * hasattachment
30
- def method_missing(sym, *args)
31
- return @attributes[sym.to_s] if @attributes.include?(sym.to_s)
32
- end
33
-
34
- # This is an alias for httpmail:hasattachment attribute.
35
- def has_attachments?
36
- return self['hasattachment']
37
- end
10
+ attribute_mappings 'has_attachments?' => 'hasattachment'
38
11
 
39
12
  # Returns the body of the message. This is either a httpmail:textdescription,
40
13
  # or a httpmail:htmldescription
@@ -42,17 +15,6 @@ module RExchange
42
15
  @attributes['textdescription'] || @attributes['htmldescription']
43
16
  end
44
17
 
45
- def initialize(session, dav_property_node)
46
- @attributes = {}
47
- @session = session
48
-
49
- dav_property_node.elements.each do |element|
50
- @attributes[element.name.tr('-', '_')] = element.text
51
- end
52
-
53
- return self
54
- end
55
-
56
18
  # Move this message to the specified folder.
57
19
  # The folder can be a string such as 'inbox/archive' or a RExchange::Folder.
58
20
  # === Example
@@ -61,15 +23,18 @@ module RExchange
61
23
  # end
62
24
  def move_to(folder)
63
25
  source = URI.parse(self.href).path
64
- destination = @session.uri.path.ensure_ends_with('/') + folder.to_s.ensure_ends_with('/') + source.split('/').last
26
+ destination = if folder.is_a?(RExchange::Folder)
27
+ folder.to_s.ensure_ends_with('/') + source.split('/').last
28
+ else
29
+ @session.uri.path.ensure_ends_with('/') + folder.to_s.ensure_ends_with('/') + source.split('/').last
30
+ end
65
31
 
32
+ $log.debug "move_to: source => \"#{source}\", destination => \"#{destination}\""
66
33
  DavMoveRequest.execute(@session, source, destination)
67
34
  end
68
35
 
69
- # Retrieve an Array of messages in this folder
70
- def Message.find(credentials, path)
71
-
72
- body = <<DABODY
36
+ def self.query(path)
37
+ <<-QBODY
73
38
  <?xml version="1.0"?>
74
39
  <D:searchrequest xmlns:D = "DAV:">
75
40
  <D:sql>
@@ -84,18 +49,7 @@ module RExchange
84
49
  AND "DAV:contentclass" = 'urn:content-classes:message'
85
50
  </D:sql>
86
51
  </D:searchrequest>
87
- DABODY
88
-
89
- response = DavSearchRequest.execute(credentials, :body => body)
90
-
91
- mail_messages = []
92
- xpath_query = "//a:propstat[a:status/text() = 'HTTP/1.1 200 OK']/a:prop"
93
-
94
- Document.new(response.body).elements.each(xpath_query) do |m|
95
- mail_messages << Message.new(credentials, m)
96
- end
97
-
98
- return mail_messages
52
+ QBODY
99
53
  end
100
54
  end
101
55
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: rexchange
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.4
7
- date: 2006-02-01
6
+ version: 0.2.0
7
+ date: 2006-02-23
8
8
  summary: "A simple wrapper around Microsoft Exchange Server's WebDAV API"
9
9
  require_paths:
10
10
  - lib
@@ -31,13 +31,15 @@ files:
31
31
  - README
32
32
  - CHANGELOG
33
33
  - RAKEFILE
34
+ - lib/r_exchange.rb
34
35
  - lib/rexchange.rb
36
+ - lib/rexchange/contact.rb
35
37
  - lib/rexchange/credentials.rb
36
38
  - lib/rexchange/dav_move_request.rb
37
39
  - lib/rexchange/dav_search_request.rb
38
40
  - lib/rexchange/exchange_request.rb
39
- - lib/rexchange/extensions.rb
40
41
  - lib/rexchange/folder.rb
42
+ - lib/rexchange/generic_item.rb
41
43
  - lib/rexchange/message.rb
42
44
  - lib/rexchange/session.rb
43
45
  - test/functional.rb
@@ -1,13 +0,0 @@
1
- class String
2
- def ends_with?(partial)
3
- self[self.size - partial.size..self.size] == partial
4
- end
5
-
6
- def ensure_ends_with(partial)
7
- self.ends_with?(partial) ? self : self + partial
8
- end
9
-
10
- def normalize
11
- self.split(/(?=[A-Z][a-z]*)/).join('_').tr('- ', '_').squeeze('_').downcase
12
- end
13
- end