maildir 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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