mbox 0.0.4 → 0.0.4.1
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/bin/mbox-daemon +17 -14
- data/bin/mbox-do +0 -2
- data/lib/mbox/mail/content.rb +1 -1
- data/lib/mbox/mail/headers.rb +46 -22
- data/lib/mbox/mbox.rb +8 -0
- metadata +20 -4
data/bin/mbox-daemon
CHANGED
@@ -42,28 +42,33 @@ end.parse!
|
|
42
42
|
end
|
43
43
|
}
|
44
44
|
|
45
|
-
|
46
|
-
@@unread = {}
|
45
|
+
$unread = {}
|
47
46
|
|
47
|
+
class Connection < EventMachine::Protocols::LineAndTextProtocol
|
48
48
|
attr_accessor :boxes
|
49
49
|
|
50
50
|
def receive_line (line)
|
51
51
|
whole, target, command, rest = line.match(/^(.*?)\s+(.*?)(?:\s+(.+))?$/).to_a
|
52
52
|
|
53
|
-
boxes = target == '*' ?
|
53
|
+
boxes = target == '*' ? $boxes : $boxes.select { |box| target.include? box.name }
|
54
54
|
|
55
55
|
if command == 'list'
|
56
56
|
command = rest
|
57
57
|
|
58
58
|
if command == 'unread'
|
59
|
-
send_response boxes.select {
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
send_response boxes.select {|box|
|
60
|
+
if !$unread[box] || $unread[box].last_check < [File.ctime(box.path), File.mtime(box.path)].max
|
61
|
+
unless $unread[:checking]
|
62
|
+
$unread[:checking] = true
|
63
|
+
|
64
|
+
EM.defer {
|
65
|
+
$unread[box] = Struct.new(:status, :last_check).new(box.has_unread?, Time.new)
|
66
|
+
$unread[:checking] = false
|
67
|
+
}
|
68
|
+
end
|
64
69
|
end
|
65
70
|
|
66
|
-
|
71
|
+
$unread[box].status rescue false
|
67
72
|
}.map(&:name)
|
68
73
|
end
|
69
74
|
end
|
@@ -77,15 +82,13 @@ class Connection < EventMachine::Protocols::LineAndTextProtocol
|
|
77
82
|
end
|
78
83
|
|
79
84
|
EM.run {
|
80
|
-
boxes = options[:mail][:boxes].map {|name|
|
85
|
+
$boxes = options[:mail][:boxes].map {|name|
|
81
86
|
Mbox.open("#{options[:mail][:directory]}/#{name}")
|
82
87
|
}
|
83
88
|
|
84
|
-
EM.start_server options[:host], options[:port], Connection
|
85
|
-
c.boxes = boxes
|
86
|
-
end
|
89
|
+
EM.start_server options[:host], options[:port], Connection
|
87
90
|
|
88
91
|
EM.add_periodic_timer options[:every] do
|
89
|
-
|
92
|
+
EM.system 'fetchmail'
|
90
93
|
end
|
91
94
|
}
|
data/bin/mbox-do
CHANGED
data/lib/mbox/mail/content.rb
CHANGED
@@ -35,7 +35,7 @@ class Content < Array
|
|
35
35
|
headers = @headers.merge(headers)
|
36
36
|
type = headers[:content_type]
|
37
37
|
|
38
|
-
if matches = type.mime.match(%r{multipart/(\w+)})
|
38
|
+
if type && type.mime && matches = type.mime.match(%r{multipart/(\w+)})
|
39
39
|
text.sub(/^.*?--#{type.boundary}\n/m, '').sub(/--#{type.boundary}--$/m, '').split("--#{type.boundary}\n").each {|part|
|
40
40
|
stream = StringIO.new(part)
|
41
41
|
|
data/lib/mbox/mail/headers.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
#++
|
19
19
|
|
20
20
|
require 'stringio'
|
21
|
+
require 'call-me/memoize'
|
21
22
|
|
22
23
|
require 'mbox/mail/headers/status'
|
23
24
|
require 'mbox/mail/headers/content_type'
|
@@ -25,22 +26,45 @@ require 'mbox/mail/headers/content_type'
|
|
25
26
|
class Mbox; class Mail
|
26
27
|
|
27
28
|
class Headers
|
28
|
-
|
29
|
-
|
29
|
+
class Name
|
30
|
+
def self.parse (text)
|
31
|
+
return text if text.is_a? self
|
30
32
|
|
31
|
-
|
33
|
+
new(text)
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize (name)
|
37
|
+
name = name.to_s.downcase.gsub('-', '_').to_sym
|
32
38
|
|
33
|
-
|
34
|
-
|
39
|
+
if name.empty?
|
40
|
+
raise ArgumentError, 'cannot pass empty name'
|
41
|
+
end
|
42
|
+
|
43
|
+
@internal = name
|
35
44
|
end
|
36
45
|
|
37
|
-
|
38
|
-
|
46
|
+
def == (other)
|
47
|
+
to_sym == Name.parse(other).to_sym
|
48
|
+
end
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
alias eql? ==
|
51
|
+
|
52
|
+
def hash
|
53
|
+
to_sym.hash
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_sym
|
57
|
+
@internal
|
58
|
+
end
|
59
|
+
|
60
|
+
memoize
|
61
|
+
def to_s
|
62
|
+
to_sym.to_s.downcase.gsub('_', '-').gsub(/(\A|-)(.)/) {|match|
|
63
|
+
match.upcase
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
alias to_str to_s
|
44
68
|
end
|
45
69
|
|
46
70
|
def self.parse (input)
|
@@ -60,16 +84,16 @@ class Headers
|
|
60
84
|
end
|
61
85
|
|
62
86
|
def [] (name)
|
63
|
-
@data[
|
87
|
+
@data[Name.parse(name)]
|
64
88
|
end
|
65
89
|
|
66
90
|
def []= (name, value)
|
67
|
-
name =
|
91
|
+
name = Name.parse(name)
|
68
92
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
93
|
+
if name == :status
|
94
|
+
value = Status.parse(value)
|
95
|
+
elsif name == :content_type
|
96
|
+
value = ContentType.parse(value)
|
73
97
|
end
|
74
98
|
|
75
99
|
if tmp = @data[name] && !tmp.is_a?(Array)
|
@@ -112,7 +136,7 @@ class Headers
|
|
112
136
|
|
113
137
|
until input.eof? || (line = input.readline).chomp.empty?
|
114
138
|
if !line.match(/^\s/)
|
115
|
-
next unless matches = line.match(/^([
|
139
|
+
next unless matches = line.match(/^([\w\-]+):\s*(.+)$/)
|
116
140
|
|
117
141
|
whole, name, value = matches.to_a
|
118
142
|
|
@@ -121,7 +145,7 @@ class Headers
|
|
121
145
|
elsif self[last]
|
122
146
|
if self[last].is_a?(String)
|
123
147
|
self[last] << " #{line}"
|
124
|
-
elsif self[last].is_a?(Array)
|
148
|
+
elsif self[last].is_a?(Array) && self[last].last.is_a?(String)
|
125
149
|
self[last].last << " #{line}"
|
126
150
|
end
|
127
151
|
end
|
@@ -135,12 +159,12 @@ class Headers
|
|
135
159
|
|
136
160
|
each {|name, values|
|
137
161
|
[values].flatten.each {|value|
|
138
|
-
result << "#{
|
162
|
+
result << "#{name}: #{value}\n"
|
139
163
|
}
|
140
164
|
}
|
141
165
|
|
142
166
|
result
|
143
167
|
end
|
144
168
|
end
|
145
|
-
|
146
|
-
end
|
169
|
+
|
170
|
+
end; end
|
data/lib/mbox/mbox.rb
CHANGED
@@ -67,9 +67,17 @@ class Mbox
|
|
67
67
|
def each (opts = {})
|
68
68
|
@input.seek 0
|
69
69
|
|
70
|
+
if @input.respond_to? :flock
|
71
|
+
@input.flock File::LOCK_SH
|
72
|
+
end
|
73
|
+
|
70
74
|
while mail = Mail.parse(@input, options.merge(opts))
|
71
75
|
yield mail
|
72
76
|
end
|
77
|
+
|
78
|
+
if @input.respond_to? :flock
|
79
|
+
@input.flock File::LOCK_UN
|
80
|
+
end
|
73
81
|
end
|
74
82
|
|
75
83
|
def [] (index, opts = {})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.4
|
4
|
+
version: 0.0.4.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-05-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: call-me
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
description: A simple library to read mbox files.
|
15
31
|
email: meh@paranoici.org
|
16
32
|
executables:
|
@@ -50,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
66
|
version: '0'
|
51
67
|
requirements: []
|
52
68
|
rubyforge_project:
|
53
|
-
rubygems_version: 1.8.
|
69
|
+
rubygems_version: 1.8.24
|
54
70
|
signing_key:
|
55
71
|
specification_version: 3
|
56
72
|
summary: A simple library to read mbox files.
|