maildir 1.0.1 → 2.0.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.
@@ -95,10 +95,17 @@ The following serializers are included:
95
95
 
96
96
  Maildir::Serializer::Base simply reads and writes strings to disk.
97
97
 
98
- Maildir::Message.serializer # => Maildir::Serializer::Base.new (by default)
98
+ `Maildir.serializer` and `Maildir.serializer=` allow you to set default serializer.
99
+
100
+ Maildir.serializer # => Maildir::Serializer::Base.new (default)
99
101
  message = maildir.add("Hello World!") # writes "Hello World!" to disk
100
102
  message.data # => "Hello World!"
101
103
 
104
+ You can also set the serializer per maildir:
105
+
106
+ maildir = Maildir.new 'Maildir'
107
+ maildir.serializer = Maildir::Serializer::JSON.new
108
+
102
109
  As of version 1.0.0, the Maildir::Serializer::Base can write IO streams as well as strings. For example:
103
110
 
104
111
  message.add(STDIN)
@@ -106,18 +113,18 @@ As of version 1.0.0, the Maildir::Serializer::Base can write IO streams as well
106
113
  This will use Ruby 1.9's more efficient IO.copy_stream method if available,
107
114
  and degrade gracefully in Ruby 1.8.
108
115
 
116
+ As of version 1.0.2, serializers are autoloaded. Thus it is no longer necessary to manually require them.
117
+
109
118
  The Mail serializer takes a ruby Mail object (http://github.com/mikel/mail) and writes RFC2822 email messages.
110
119
 
111
- require 'maildir/serializer/mail'
112
- Maildir::Message.serializer = Maildir::Serializer::Mail.new
120
+ maildir.serializer = Maildir::Serializer::Mail.new
113
121
  mail = Mail.new(...)
114
122
  message = maildir.add(mail) # writes an RFC2822 message to disk
115
123
  message.data == mail # => true; data is parsed as a Mail object
116
124
 
117
125
  The Marshal, JSON, and YAML serializers work similarly. E.g.:
118
126
 
119
- require 'maildir/serializer/json'
120
- Maildir::Message.serializer = Maildir::Serializer::JSON.new
127
+ maildir.serializer = Maildir::Serializer::JSON.new
121
128
  my_data = {"foo" => nil, "my_array" => [1,2,3]}
122
129
  message = maildir.add(my_data) # writes {"foo":null,"my_array":[1,2,3]}
123
130
  message.data == my_data # => true
@@ -127,13 +134,16 @@ It's trivial to create a custom serializer. Implement the following two methods:
127
134
  load(path)
128
135
  dump(data, path)
129
136
 
137
+ == Author
138
+
139
+ * Aaron Suggs (github[http://github.com/ktheory])
140
+
130
141
  == Contributors
131
142
 
132
- * Aaron Suggs (github[http://github.com/ktheory]) Primary author
133
- * Niklas E. Cathor (github[http://github.com/nilclass]) added subdir & courierimapkeywords support
134
- * Ali Polatel (github[http://github.com/alip]) for suggesting IO.copy_stream
135
- * Harry Vangberg (github[http://github.com/vangberg]) for fixing tests in ruby 1.9
136
- * Alexander Flatter (github[http://github.com/aflatter]) for improving serializers
143
+ * Niklas E. Cathor (github[http://github.com/nilclass])
144
+ * Ali Polatel (github[http://github.com/alip])
145
+ * Harry Vangberg (github[http://github.com/vangberg])
146
+ * Alexander Flatter (github[http://github.com/aflatter])
137
147
 
138
148
  == Copyright
139
149
 
@@ -1,6 +1,14 @@
1
1
  require 'fileutils' # For create_directories
2
2
  class Maildir
3
3
 
4
+ module Serializer
5
+ autoload :Base, 'maildir/serializer/base'
6
+ autoload :Mail, 'maildir/serializer/mail'
7
+ autoload :Marshal, 'maildir/serializer/marshal'
8
+ autoload :JSON, 'maildir/serializer/json'
9
+ autoload :YAML, 'maildir/serializer/yaml'
10
+ end
11
+
4
12
  SUBDIRS = [:tmp, :new, :cur].freeze
5
13
 
6
14
  include Comparable
@@ -8,6 +16,19 @@ class Maildir
8
16
  attr_reader :path
9
17
  attr_accessor :serializer
10
18
 
19
+ # Default serializer.
20
+ @@serializer = Maildir::Serializer::Base.new
21
+
22
+ # Gets the default serializer.
23
+ def self.serializer
24
+ @@serializer
25
+ end
26
+
27
+ # Sets the default serializer.
28
+ def self.serializer=(serializer)
29
+ @@serializer = serializer
30
+ end
31
+
11
32
  # Create a new maildir at +path+. If +create+ is true, will ensure that the
12
33
  # required subdirectories exist.
13
34
  def initialize(path, create = true)
@@ -17,6 +38,11 @@ class Maildir
17
38
  create_directories if create
18
39
  end
19
40
 
41
+ # Returns own serializer or falls back to default.
42
+ def serializer
43
+ @serializer || @@serializer
44
+ end
45
+
20
46
  # Compare maildirs by their paths.
21
47
  # If maildir is a different class, return nil.
22
48
  # Otherwise, return 1, 0, or -1.
@@ -17,19 +17,16 @@ class Maildir::Message
17
17
  message
18
18
  end
19
19
 
20
- # The serializer processes data before it is written to disk and after
21
- # reading from disk.
22
- # Default serializer
23
- @@serializer = Maildir::Serializer::Base.new
24
-
25
- # Get the serializer
20
+ # DEPRECATED: Get the serializer.
21
+ # @see Maildir.serializer
26
22
  def self.serializer
27
- @@serializer
23
+ Maildir.serializer
28
24
  end
29
25
 
30
- # Set the serializer
26
+ # DEPRECATED: Set the serializer.
27
+ # @see Maildir.serializer=
31
28
  def self.serializer=(serializer)
32
- @@serializer = serializer
29
+ Maildir.serializer = serializer
33
30
  end
34
31
 
35
32
  attr_reader :dir, :unique_name, :info
@@ -70,10 +67,9 @@ class Maildir::Message
70
67
  "#<#{self.class} key=#{key} maildir=#{@maildir.inspect}>"
71
68
  end
72
69
 
73
- # Determines the serializer by first trying the maildir and then falling
74
- # back to the default serializer.
70
+ # Helper to get serializer.
75
71
  def serializer
76
- @maildir.serializer || @@serializer
72
+ @maildir.serializer
77
73
  end
78
74
 
79
75
  # Writes data to disk. Can only be called on messages instantiated without
@@ -1,36 +1,38 @@
1
- module Maildir::Serializer
2
- # The Maildir::Serializer::Base class reads & writes data to disk as a
3
- # string. Other serializers (e.g. Maildir::Serializer::Mail) can extend this
4
- # class to do some pre- and post-processing of the string.
5
- #
6
- # The Serializer API has two methods:
7
- # load(path) # => returns data
8
- # dump(data, path) # => returns number of bytes written
9
- class Base
10
- # Reads the file at path. Returns the contents of path.
11
- def load(path)
12
- File.read(path)
13
- end
1
+ class Maildir
2
+ module Serializer
3
+ # The Maildir::Serializer::Base class reads & writes data to disk as a
4
+ # string. Other serializers (e.g. Maildir::Serializer::Mail) can extend this
5
+ # class to do some pre- and post-processing of the string.
6
+ #
7
+ # The Serializer API has two methods:
8
+ # load(path) # => returns data
9
+ # dump(data, path) # => returns number of bytes written
10
+ class Base
11
+ # Reads the file at path. Returns the contents of path.
12
+ def load(path)
13
+ File.read(path)
14
+ end
14
15
 
15
- # Writes data to path. Returns number of bytes written.
16
- # If data acts like an IO object (i.e., data responds to the read method),
17
- # we call data.read or the more efficient IO.copy_stream available in
18
- # ruby 1.9.1.
19
- def dump(data, path)
20
- if data.respond_to?(:read)
21
- if IO.respond_to?(:copy_stream)
22
- IO.copy_stream(data, path)
16
+ # Writes data to path. Returns number of bytes written.
17
+ # If data acts like an IO object (i.e., data responds to the read method),
18
+ # we call data.read or the more efficient IO.copy_stream available in
19
+ # ruby 1.9.1.
20
+ def dump(data, path)
21
+ if data.respond_to?(:read)
22
+ if IO.respond_to?(:copy_stream)
23
+ IO.copy_stream(data, path)
24
+ else
25
+ write(data.read, path)
26
+ end
23
27
  else
24
- write(data.read, path)
28
+ write(data, path)
25
29
  end
26
- else
27
- write(data, path)
28
30
  end
29
- end
30
31
 
31
- protected
32
- def write(data, path)
33
- File.open(path, "w") {|file| file.write(data)}
32
+ protected
33
+ def write(data, path)
34
+ File.open(path, "w") {|file| file.write(data)}
35
+ end
34
36
  end
35
37
  end
36
38
  end
@@ -5,17 +5,19 @@ rescue LoadError
5
5
  require 'json'
6
6
  end
7
7
 
8
- # Serialize messages as JSON
9
- module Maildir::Serializer
10
- class JSON < Base
11
- # Read data from path and parse it as JSON.
12
- def load(path)
13
- ::JSON.load(super(path))
14
- end
8
+ class Maildir
9
+ module Serializer
10
+ # Serialize messages as JSON
11
+ class JSON < Base
12
+ # Read data from path and parse it as JSON.
13
+ def load(path)
14
+ ::JSON.load(super(path))
15
+ end
15
16
 
16
- # Dump data as JSON and writes it to path.
17
- def dump(data, path)
18
- super(data.to_json, path)
17
+ # Dump data as JSON and writes it to path.
18
+ def dump(data, path)
19
+ super(data.to_json, path)
20
+ end
19
21
  end
20
22
  end
21
23
  end
@@ -1,13 +1,17 @@
1
1
  require 'mail'
2
- # Serialize messages as a ruby Mail object
3
- class Maildir::Serializer::Mail < Maildir::Serializer::Base
4
- # Build a new Mail object from the data at path.
5
- def load(path)
6
- ::Mail.new(super(path))
7
- end
2
+ class Maildir
3
+ module Serializer
4
+ # Serialize messages as a ruby Mail object
5
+ class Mail < Maildir::Serializer::Base
6
+ # Build a new Mail object from the data at path.
7
+ def load(path)
8
+ ::Mail.new(super(path))
9
+ end
8
10
 
9
- # Write data to path as a Mail message.
10
- def dump(data, path)
11
- super(data.to_s, path)
11
+ # Write data to path as a Mail message.
12
+ def dump(data, path)
13
+ super(data.to_s, path)
14
+ end
15
+ end
12
16
  end
13
17
  end
@@ -1,12 +1,16 @@
1
- # Serialize messages as Marshalled ruby objects
2
- class Maildir::Serializer::Marshal < Maildir::Serializer::Base
3
- # Read data from path and unmarshal it.
4
- def load(path)
5
- ::Marshal.load(super(path))
6
- end
1
+ class Maildir
2
+ module Serializer
3
+ # Serialize messages as Marshalled ruby objects
4
+ class Marshal < Maildir::Serializer::Base
5
+ # Read data from path and unmarshal it.
6
+ def load(path)
7
+ ::Marshal.load(super(path))
8
+ end
7
9
 
8
- # Marshal data and write it to path.
9
- def dump(data, path)
10
- super(::Marshal.dump(data), path)
10
+ # Marshal data and write it to path.
11
+ def dump(data, path)
12
+ super(::Marshal.dump(data), path)
13
+ end
14
+ end
11
15
  end
12
16
  end
@@ -1,13 +1,17 @@
1
1
  require 'yaml'
2
- # Serialize messages as YAML
3
- class Maildir::Serializer::YAML < Maildir::Serializer::Base
4
- # Read data from path and parse it as YAML.
5
- def load(path)
6
- ::YAML.load(super(path))
7
- end
2
+ class Maildir
3
+ module Serializer
4
+ # Serialize messages as YAML
5
+ class YAML < Maildir::Serializer::Base
6
+ # Read data from path and parse it as YAML.
7
+ def load(path)
8
+ ::YAML.load(super(path))
9
+ end
8
10
 
9
- # Dump data as YAML and writes it to path.
10
- def dump(data, path)
11
- super(data.to_yaml, path)
11
+ # Dump data as YAML and writes it to path.
12
+ def dump(data, path)
13
+ super(data.to_yaml, path)
14
+ end
15
+ end
12
16
  end
13
17
  end
@@ -1,3 +1,3 @@
1
1
  class Maildir
2
- VERSION = '1.0.1'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -17,8 +17,8 @@ class TestMaildir < Test::Unit::TestCase
17
17
  end
18
18
  end
19
19
 
20
- should "have no serializer" do
21
- assert temp_maildir.serializer.nil?
20
+ should "have default serializer" do
21
+ assert_equal temp_maildir.serializer, Maildir::Message.serializer
22
22
  end
23
23
 
24
24
  should "set serializer" do
@@ -8,11 +8,7 @@ class TestMessage < Test::Unit::TestCase
8
8
  @message = Maildir::Message.new(@maildir)
9
9
  end
10
10
 
11
- should "use default serializer" do
12
- assert_equal @message.serializer, Maildir::Message.serializer
13
- end
14
-
15
- should "prefer serializer of its maildir" do
11
+ should "use serializer of its maildir" do
16
12
  @maildir.serializer = :foo
17
13
  assert_equal @message.serializer, :foo
18
14
  end
metadata CHANGED
@@ -1,113 +1,84 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: maildir
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 1
10
- version: 1.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Aaron Suggs
14
- - Niklas E. Cathor
15
9
  autorequire:
16
10
  bindir: bin
17
11
  cert_chain: []
18
-
19
- date: 2011-05-08 00:00:00 -04:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
12
+ date: 2011-09-09 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
23
15
  name: rake
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70101941878220 !ruby/object:Gem::Requirement
26
17
  none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
34
22
  type: :development
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: shoulda
38
23
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70101941878220
25
+ - !ruby/object:Gem::Dependency
26
+ name: shoulda
27
+ requirement: &70101941877660 !ruby/object:Gem::Requirement
40
28
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
48
33
  type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: mail
52
34
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *70101941877660
36
+ - !ruby/object:Gem::Dependency
37
+ name: mail
38
+ requirement: &70101941877140 !ruby/object:Gem::Requirement
54
39
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
62
44
  type: :development
63
- version_requirements: *id003
64
- - !ruby/object:Gem::Dependency
65
- name: json
66
45
  prerelease: false
67
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *70101941877140
47
+ - !ruby/object:Gem::Dependency
48
+ name: json
49
+ requirement: &70101941876660 !ruby/object:Gem::Requirement
68
50
  none: false
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- hash: 3
73
- segments:
74
- - 0
75
- version: "0"
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
76
55
  type: :development
77
- version_requirements: *id004
78
- - !ruby/object:Gem::Dependency
79
- name: fakefs
80
56
  prerelease: false
81
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *70101941876660
58
+ - !ruby/object:Gem::Dependency
59
+ name: fakefs
60
+ requirement: &70101941876060 !ruby/object:Gem::Requirement
82
61
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- hash: 23
87
- segments:
88
- - 0
89
- - 3
90
- - 2
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
91
65
  version: 0.3.2
92
66
  type: :development
93
- version_requirements: *id005
94
- description: A ruby library for reading and writing arbitrary messages in DJB's maildir format
67
+ prerelease: false
68
+ version_requirements: *70101941876060
69
+ description: A ruby library for reading and writing arbitrary messages in DJB's maildir
70
+ format
95
71
  email: aaron@ktheory.com
96
72
  executables: []
97
-
98
73
  extensions: []
99
-
100
74
  extra_rdoc_files: []
101
-
102
- files:
103
- - lib/maildir/keywords.rb
75
+ files:
104
76
  - lib/maildir/message.rb
105
77
  - lib/maildir/serializer/base.rb
106
78
  - lib/maildir/serializer/json.rb
107
79
  - lib/maildir/serializer/mail.rb
108
80
  - lib/maildir/serializer/marshal.rb
109
81
  - lib/maildir/serializer/yaml.rb
110
- - lib/maildir/subdirs.rb
111
82
  - lib/maildir/unique_name.rb
112
83
  - lib/maildir/version.rb
113
84
  - lib/maildir.rb
@@ -115,53 +86,38 @@ files:
115
86
  - README.rdoc
116
87
  - Rakefile
117
88
  - test/test_helper.rb
118
- - test/test_keywords.rb
119
89
  - test/test_maildir.rb
120
90
  - test/test_message.rb
121
91
  - test/test_serializers.rb
122
- - test/test_subdirs.rb
123
92
  - test/test_unique_name.rb
124
- has_rdoc: true
125
93
  homepage: http://github.com/ktheory/maildir
126
94
  licenses: []
127
-
128
95
  post_install_message:
129
- rdoc_options:
96
+ rdoc_options:
130
97
  - --charset=UTF-8
131
- require_paths:
98
+ require_paths:
132
99
  - lib
133
- required_ruby_version: !ruby/object:Gem::Requirement
100
+ required_ruby_version: !ruby/object:Gem::Requirement
134
101
  none: false
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- hash: 3
139
- segments:
140
- - 0
141
- version: "0"
142
- required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
107
  none: false
144
- requirements:
145
- - - ">="
146
- - !ruby/object:Gem::Version
147
- hash: 17
148
- segments:
149
- - 1
150
- - 3
151
- - 5
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
152
111
  version: 1.3.5
153
112
  requirements: []
154
-
155
113
  rubyforge_project:
156
- rubygems_version: 1.6.2
114
+ rubygems_version: 1.8.7
157
115
  signing_key:
158
116
  specification_version: 3
159
117
  summary: Read & write messages in the maildir format
160
- test_files:
118
+ test_files:
161
119
  - test/test_helper.rb
162
- - test/test_keywords.rb
163
120
  - test/test_maildir.rb
164
121
  - test/test_message.rb
165
122
  - test/test_serializers.rb
166
- - test/test_subdirs.rb
167
123
  - test/test_unique_name.rb
@@ -1,110 +0,0 @@
1
- # implements IMAP Keywords as used by the Courier Mail Server
2
- # see http://www.courier-mta.org/imap/README.imapkeywords.html for details
3
-
4
- require 'maildir'
5
- module Maildir::Keywords
6
- def self.included(base)
7
- Maildir::Message.send(:include, MessageExtension)
8
- end
9
-
10
- def keyword_dir
11
- @keyword_dir ||= File.join(path, 'courierimapkeywords')
12
- Dir.mkdir(@keyword_dir) unless File.directory?(@keyword_dir)
13
- return @keyword_dir
14
- end
15
-
16
- # process contents of courierimapkeywords/ directory as described in README.imapkeywords
17
- def read_keywords
18
- messages = (list(:cur) + list(:new)).inject({}) { |m, msg| m[msg.unique_name] = msg ; m }
19
- t = Time.now.to_i / 300
20
- keywords = []
21
- state = :head
22
- # process :list
23
- list_file = File.join(keyword_dir, ':list')
24
- File.open(list_file).each_line do |line|
25
- line.strip!
26
- if state == :head
27
- if line.empty?
28
- state = :messages
29
- next
30
- end
31
- keywords << line
32
- else
33
- key, ids = line.split(':')
34
- if msg = messages[key]
35
- msg.set_keywords(ids.split(/\s/).map {|id| keywords[id.to_i - 1] })
36
- end
37
- end
38
- end if File.exist?(list_file)
39
- # collect keyword files
40
- keyword_files = (Dir.entries(keyword_dir) - %w(. .. :list)).inject({}) do |keyword_files, file|
41
- if file =~ /^\.(\d+)\.(.*)$/
42
- n = $1
43
- key = $2
44
- else
45
- n = t + 1
46
- key = file
47
- FileUtils.mv(File.join(keyword_dir, file), File.join(keyword_dir, ".#{n}.#{key}"))
48
- end
49
- if msg = messages[key]
50
- (keyword_files[key] ||= []) << [n, key]
51
- else # message doesn't exist
52
- fname = File.join(keyword_dir, file)
53
- if File.stat(fname).ctime < (Time.now - (15 * 60))
54
- File.unlink(fname)
55
- end
56
- end
57
- next(keyword_files)
58
- end
59
- # process keyword files
60
- keyword_files.each_pair do |key, files|
61
- files.sort! { |a, b| a[0] <=> b[0] }
62
- files[0..-2].each { |f| File.unlink(File.join(keyword_dir, ".#{f.join('.')}")) } if files.last[0] < t
63
- msg = messages[key]
64
- file = (File.exist?(File.join(keyword_dir, files.last[1])) ? files.last[1] : ".#{files.last.join('.')}")
65
- current_keywords = File.read(File.join(keyword_dir, file)).split(/\s+/)
66
- msg.set_keywords(current_keywords)
67
- if (add = (current_keywords - keywords)).any?
68
- keywords += add
69
- end
70
- end
71
- # rebuild :list
72
- @keywords = {}
73
- tmp_file = File.join(path, 'tmp', ':list')
74
- File.open(tmp_file, 'w') { |f|
75
- f.write(keywords.join("\n")+"\n\n")
76
- messages.each_pair do |key, msg|
77
- next unless msg.keywords
78
- f.puts([key, msg.keywords.map{|kw| keywords.index(kw) + 1 }.sort.join(' ')].join(':'))
79
- @keywords[key] = msg.keywords
80
- end
81
- }
82
- FileUtils.mv(tmp_file, list_file)
83
- end
84
-
85
- def keywords(key)
86
- read_keywords unless @keywords
87
- @keywords[key] || []
88
- end
89
-
90
- module MessageExtension
91
- def keywords
92
- return @keywords if @keywords
93
- @maildir.keywords(unique_name)
94
- end
95
-
96
- # sets given keywords on the message.
97
- def keywords=(list)
98
- tmp_fname = File.join(@maildir.path, 'tmp', unique_name)
99
- File.open(tmp_fname, 'w') { |f| f.write(list.join("\n")) }
100
- FileUtils.mv(tmp_fname, File.join(@maildir.keyword_dir, unique_name))
101
- end
102
-
103
- # sets @keywords to the given list
104
- def set_keywords(list)
105
- @keywords = list
106
- end
107
- end
108
- end
109
-
110
- Maildir.send(:include, Maildir::Keywords)
@@ -1,70 +0,0 @@
1
- # implements subdirs as used by the Courier Mail Server (courier-mta.org)
2
- require 'maildir'
3
- module Maildir::Subdirs
4
- ROOT_NAME = 'INBOX'
5
- DELIM = '.'
6
-
7
- def self.included(base)
8
- base.instance_eval do
9
- alias_method :inspect_without_subdirs, :inspect
10
- alias_method :inspect, :inspect_with_subdirs
11
- end
12
- end
13
-
14
- def name
15
- root? ? ROOT_NAME : subdir_parts(path).last
16
- end
17
-
18
- def create_subdir(name)
19
- raise ArgumentError.new("'name' may not contain delimiter character (#{DELIM})") if name.include?(DELIM)
20
- full_name = (root? ? [] : subdir_parts(File.basename(path))).push(name).unshift('').join(DELIM)
21
- md = Maildir.new(File.join(path, full_name), true)
22
- @subdirs << md if @subdirs
23
- md
24
- end
25
-
26
- # returns the logical mailbox path
27
- def mailbox_path
28
- @mailbox_path ||= root? ? ROOT_NAME : subdir_parts(File.basename(path)).unshift(ROOT_NAME).join(DELIM)
29
- end
30
-
31
- # returns an array of Maildir objects representing the direct subdirectories of this Maildir
32
- def subdirs(only_direct=true)
33
- if root?
34
- @subdirs ||= (Dir.entries(path) - %w(. ..)).select {|e|
35
- e =~ /^\./ && File.directory?(File.join(path, e)) && (only_direct ? subdir_parts(e).size == 1 : true)
36
- }.map { |e| Maildir.new(File.join(path, e), false) }
37
- else
38
- my_parts = subdir_parts(File.basename(path))
39
- @subdirs ||= root.subdirs(false).select { |md| subdir_parts(File.basename(md.path))[0..-2] == my_parts }
40
- end
41
- end
42
-
43
- # Friendly inspect method
44
- def inspect_with_subdirs
45
- "#<#{self.class} path=#{@path} mailbox_path=#{mailbox_path}>"
46
- end
47
-
48
- # returns the Maildir representing the root directory
49
- def root
50
- root? ? self : Maildir.new(File.dirname(path), false)
51
- end
52
-
53
- # returns true if the parent directory doesn't look like a maildir
54
- def root?
55
- ! ((Dir.entries(File.dirname(path)) & %w(cur new tmp)).size == 3)
56
- end
57
-
58
- private
59
-
60
- def subdir_parts(path)
61
- path.sub!(/\/$/, '') # remove trailing slash
62
- parts = (path.split(DELIM) - [''])
63
- # some clients (e.g. Thunderbird) mess up namespaces so subdirs
64
- # end up looking like '.INBOX.Trash' instead of '.Trash'
65
- parts.shift if parts.first == ROOT_NAME
66
- parts
67
- end
68
- end
69
-
70
- Maildir.send(:include, Maildir::Subdirs)
@@ -1,16 +0,0 @@
1
- require 'test_helper'
2
- require 'maildir/keywords'
3
- class TestKeywords < Test::Unit::TestCase
4
- context "A message" do
5
- setup do
6
- @data = "foo\n"
7
- @msg = Maildir::Message.create(temp_maildir, @data)
8
- end
9
-
10
- should "remember keywords" do
11
- kw = %w(Junk Seen)
12
- @msg.keywords = kw
13
- assert (@msg.keywords & kw).size == 2
14
- end
15
- end
16
- end
@@ -1,46 +0,0 @@
1
- require 'test_helper'
2
- require 'maildir/subdirs'
3
- class TestSubdirs < Test::Unit::TestCase
4
- context "A maildir" do
5
- setup do
6
- FakeFS::FileSystem.clear
7
- @maildir = temp_maildir
8
- setup_subdirs(@maildir)
9
- end
10
-
11
- should "have subdirs" do
12
- assert @maildir.subdirs.any?
13
- end
14
-
15
- should "be called INBOX" do
16
- assert @maildir.name == 'INBOX'
17
- end
18
-
19
- should "include direct subdirs" do
20
- subdir_names = @maildir.subdirs.map(&:name)
21
- assert subdir_names.include?('a') && subdir_names.include?('b')
22
- end
23
-
24
- should "not include deeper subdirs" do
25
- subdir_names = @maildir.subdirs.map(&:name)
26
- assert ! subdir_names.include?('x') && ! subdir_names.include?('a.x')
27
- end
28
-
29
- should "create more subdirs" do
30
- @maildir.create_subdir("test")
31
- assert @maildir.subdirs.map(&:name).include?("test")
32
- end
33
- end
34
-
35
- context "A subdir" do
36
- setup do
37
- FakeFS::FileSystem.clear
38
- @maildir = temp_maildir
39
- setup_subdirs(@maildir)
40
- end
41
-
42
- should "include more subdirs" do
43
- assert_not_empty @maildir.subdirs.select{ |sd| sd.name == 'a'}.first.subdirs
44
- end
45
- end
46
- end