imap_processor 1.1.1 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -3
- data/.autotest +3 -18
- data/History.rdoc +103 -0
- data/Manifest.txt +18 -2
- data/{README.txt → README.rdoc} +35 -5
- data/Rakefile +8 -5
- data/bin/imap_archive +5 -0
- data/bin/imap_cleanse +5 -0
- data/bin/imap_flag +5 -0
- data/bin/imap_idle +6 -0
- data/bin/imap_learn +5 -0
- data/bin/imap_mkdir +5 -0
- data/lib/imap_processor.rb +304 -154
- data/lib/imap_processor/archive.rb +128 -0
- data/lib/imap_processor/cleanse.rb +67 -0
- data/lib/imap_processor/client.rb +145 -0
- data/lib/imap_processor/flag.rb +121 -0
- data/lib/imap_processor/idle.rb +74 -0
- data/lib/imap_processor/keywords.rb +9 -14
- data/lib/imap_processor/learn.rb +231 -0
- data/lib/imap_processor/mkdir.rb +25 -0
- data/lib/imap_sasl_plain.rb +1 -26
- data/lib/net/imap/date.rb +24 -0
- data/lib/net/imap/idle.rb +48 -0
- data/test/test_imap_processor.rb +185 -0
- metadata +120 -71
- metadata.gz.sig +0 -0
- data/History.txt +0 -22
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'net/imap'
|
2
|
+
|
3
|
+
class Net::IMAP
|
4
|
+
|
5
|
+
##
|
6
|
+
# Sends an IDLE command that waits for notifications of new or expunged
|
7
|
+
# messages. Yields responses from the server during the IDLE.
|
8
|
+
#
|
9
|
+
# Use #idle_done to leave IDLE.
|
10
|
+
|
11
|
+
def idle(&response_handler)
|
12
|
+
raise LocalJumpError, "no block given" unless response_handler
|
13
|
+
|
14
|
+
response = nil
|
15
|
+
|
16
|
+
synchronize do
|
17
|
+
tag = Thread.current[:net_imap_tag] = generate_tag
|
18
|
+
put_string "#{tag} IDLE#{CRLF}"
|
19
|
+
|
20
|
+
begin
|
21
|
+
add_response_handler response_handler
|
22
|
+
|
23
|
+
@idle_done_cond = new_cond
|
24
|
+
@idle_done_cond.wait
|
25
|
+
@idle_done_cond = nil
|
26
|
+
ensure
|
27
|
+
remove_response_handler response_handler
|
28
|
+
put_string "DONE#{CRLF}"
|
29
|
+
response = get_tagged_response tag
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
response
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Leaves IDLE
|
38
|
+
|
39
|
+
def idle_done
|
40
|
+
raise Net::IMAP::Error, 'not during idle' unless @idle_done_cond
|
41
|
+
|
42
|
+
synchronize do
|
43
|
+
@idle_done_cond.signal
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end unless Net::IMAP.method_defined? :idle
|
48
|
+
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'imap_processor'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
##
|
7
|
+
# These tests expect a local IMAP server with a 'test' login with a 'test'
|
8
|
+
# password. It's fairly easy to set up dovecot to do this:
|
9
|
+
#
|
10
|
+
# In dovecot.conf:
|
11
|
+
#
|
12
|
+
# mail_location = mbox:~/mail:INBOX=~/Mailbox
|
13
|
+
#
|
14
|
+
# auth default {
|
15
|
+
# mechanisms = plain
|
16
|
+
#
|
17
|
+
# passdb passwd-file {
|
18
|
+
# args = scheme=plain username_format=%n /path/to/etc/dovecot/passwd
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# userdb passwd-file {
|
22
|
+
# args = username_format=%n /path/to/etc/dovecot/passwd
|
23
|
+
# }
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# And in /path/to/etc/dovecot/passwd:
|
27
|
+
#
|
28
|
+
# test:test:<your uid>:<your gid>::/path/to/your/home/dovecot
|
29
|
+
|
30
|
+
class TestIMAPProcessor < MiniTest::Unit::TestCase
|
31
|
+
|
32
|
+
def setup
|
33
|
+
host, port, username, password = 'localhost', 143, 'test', 'test'
|
34
|
+
|
35
|
+
@ip = IMAPProcessor.new :Host => host, :Port => port,
|
36
|
+
:Username => username, :Password => password,
|
37
|
+
:Verbose => false
|
38
|
+
|
39
|
+
@connection = @ip.connect
|
40
|
+
|
41
|
+
@imap = @connection.imap
|
42
|
+
@ip.instance_variable_set :@imap, @imap
|
43
|
+
|
44
|
+
@delim = @imap.list('', 'INBOX').first.delim
|
45
|
+
|
46
|
+
@NI = Net::IMAP
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
@imap.select 'INBOX'
|
51
|
+
uids = @imap.search 'ALL'
|
52
|
+
@imap.store uids, '+FLAGS.SILENT', [:Deleted] unless uids.empty?
|
53
|
+
@imap.expunge
|
54
|
+
@imap.list('', '*').each do |mailbox|
|
55
|
+
next if mailbox.name == 'INBOX'
|
56
|
+
@imap.delete mailbox.name
|
57
|
+
end
|
58
|
+
@imap.disconnect
|
59
|
+
end
|
60
|
+
|
61
|
+
# pre-run cleanup
|
62
|
+
test = self.new nil
|
63
|
+
test.setup
|
64
|
+
test.teardown
|
65
|
+
|
66
|
+
def test_capability
|
67
|
+
res =
|
68
|
+
@NI::UntaggedResponse.new('OK',
|
69
|
+
@NI::ResponseText.new(
|
70
|
+
@NI::ResponseCode.new('CAPABILITY',
|
71
|
+
'IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN'),
|
72
|
+
'Dovecot ready.'),
|
73
|
+
"OK [CAPABAILITY ...] Dovecot ready.\r\n")
|
74
|
+
|
75
|
+
cap = @ip.capability @imap, res
|
76
|
+
|
77
|
+
assert_equal \
|
78
|
+
%w[IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN],
|
79
|
+
cap
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_capability_no_cap
|
83
|
+
res =
|
84
|
+
@NI::TaggedResponse.new('RUBY0001', 'OK',
|
85
|
+
@NI::ResponseText.new(nil,
|
86
|
+
'User logged in'),
|
87
|
+
"RUBY0001 OK User logged in\r\n")
|
88
|
+
|
89
|
+
cap = @ip.capability @imap, res
|
90
|
+
|
91
|
+
assert_includes cap, 'IMAP4REV1'
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_capability_no_res
|
95
|
+
cap = @ip.capability @imap
|
96
|
+
|
97
|
+
assert_includes cap, 'IMAP4REV1'
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_create_mailbox
|
101
|
+
@imap.create "directory#{@delim}"
|
102
|
+
|
103
|
+
assert_equal nil, @ip.create_mailbox('directory')
|
104
|
+
|
105
|
+
refute_nil @ip.create_mailbox('destination')
|
106
|
+
mailbox = @imap.list('', 'destination').first
|
107
|
+
assert_equal 'destination', mailbox.name
|
108
|
+
assert_equal [:Noinferiors, :Unmarked], mailbox.attr
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_delete_messages
|
112
|
+
util_message
|
113
|
+
uids = util_uids
|
114
|
+
|
115
|
+
@ip.delete_messages uids
|
116
|
+
|
117
|
+
assert_empty util_uids
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_delete_messages_no_expunge
|
121
|
+
util_message
|
122
|
+
uids = util_uids
|
123
|
+
|
124
|
+
@ip.delete_messages uids, false
|
125
|
+
|
126
|
+
uids = util_uids
|
127
|
+
|
128
|
+
refute_empty uids
|
129
|
+
assert_includes :Deleted, @imap.fetch(uids, 'FLAGS').first.attr['FLAGS']
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_move_messages
|
133
|
+
util_message
|
134
|
+
uids = util_uids
|
135
|
+
|
136
|
+
@ip.move_messages uids, 'destination'
|
137
|
+
|
138
|
+
assert_equal 0, @imap.search('ALL').length
|
139
|
+
|
140
|
+
assert_equal 1, @imap.list('', 'destination').length
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_show_messages
|
144
|
+
now = Time.now
|
145
|
+
util_message nil, now
|
146
|
+
uids = util_uids
|
147
|
+
|
148
|
+
out, = capture_io do
|
149
|
+
@ip.show_messages uids
|
150
|
+
end
|
151
|
+
|
152
|
+
expected = <<-EXPECTED
|
153
|
+
Subject: message 1
|
154
|
+
Date: #{now.rfc2822}
|
155
|
+
Message-Id: 1
|
156
|
+
|
157
|
+
EXPECTED
|
158
|
+
|
159
|
+
assert_equal expected, out
|
160
|
+
end
|
161
|
+
|
162
|
+
def util_message(flags = nil, time = Time.now)
|
163
|
+
@count ||= 0
|
164
|
+
@count += 1
|
165
|
+
|
166
|
+
message = <<-MESSAGE
|
167
|
+
From: from@example.com
|
168
|
+
To: to@example.com
|
169
|
+
Subject: message #{@count}
|
170
|
+
Date: #{time.rfc2822}
|
171
|
+
Message-Id: #{@count}
|
172
|
+
|
173
|
+
Hi, this is message number #{@count}
|
174
|
+
MESSAGE
|
175
|
+
|
176
|
+
@imap.append 'INBOX', message, flags, time
|
177
|
+
end
|
178
|
+
|
179
|
+
def util_uids
|
180
|
+
@imap.select 'INBOX'
|
181
|
+
@imap.search 'ALL'
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
metadata
CHANGED
@@ -1,103 +1,152 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: imap_processor
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.7'
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
6
|
+
authors:
|
7
|
+
- Ryan Davis
|
7
8
|
- Eric Hodel
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
+
cert_chain:
|
11
12
|
- |
|
12
13
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
MIIDPjCCAiagAwIBAgIBBDANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
|
15
|
+
ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
|
16
|
+
GRYDY29tMB4XDTE5MTIxMzAwMDIwNFoXDTIwMTIxMjAwMDIwNFowRTETMBEGA1UE
|
17
|
+
AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
|
18
|
+
JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
|
19
|
+
b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
|
20
|
+
taCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT
|
21
|
+
oOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh
|
22
|
+
GiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt
|
23
|
+
qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
|
24
|
+
gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
25
|
+
HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBCwUAA4IB
|
26
|
+
AQCkkcHqAa6IKLYGl93rn78J3L+LnqyxaA059n4IGMHWN5bv9KBQnIjOrpLadtYZ
|
27
|
+
vhWkunWDKdfVapBEq5+T4HzqnsEXC3aCv6JEKJY6Zw7iSzl0M8hozuzRr+w46wvT
|
28
|
+
fV2yTN6QTVxqbMsJJyjosks4ZdQYov2zdvQpt1HsLi+Qmckmg8SPZsd+T8uiiBCf
|
29
|
+
b+1ORSM5eEfBQenPXy83LZcoQz8i6zVB4aAfTGGdhxjoMGUEmSZ6xpkOzmnGa9QK
|
30
|
+
m5x9IDiApM+vCELNwDXXGNFEnQBBK+wAe4Pek8o1V1TTOxL1kGPewVOitX1p3xoN
|
31
|
+
h7iEjga8iM1LbZUfiISZ+WrB
|
31
32
|
-----END CERTIFICATE-----
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
date: 2020-06-04 00:00:00.000000000 Z
|
34
|
+
dependencies:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rdoc
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '4.0'
|
42
|
+
- - "<"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '7'
|
38
45
|
type: :development
|
39
|
-
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
requirements:
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
42
49
|
- - ">="
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version:
|
45
|
-
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '4.0'
|
52
|
+
- - "<"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hoe
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.22'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.22'
|
46
69
|
description: |-
|
47
70
|
IMAPProcessor is a client for processing messages on an IMAP server. It
|
48
71
|
provides some basic mechanisms for connecting to an IMAP server, determining
|
49
72
|
capabilities and handling messages.
|
50
|
-
|
51
|
-
IMAPProcessor ships with
|
52
|
-
|
53
|
-
|
73
|
+
|
74
|
+
IMAPProcessor ships with several executables which can query and
|
75
|
+
manipulate IMAP mailboxes in several different ways:
|
76
|
+
|
77
|
+
imap_archive :: Archives old messages to a new dated mailbox.
|
78
|
+
imap_cleanse :: Delete messages older than a certain age in specified mailboxes.
|
79
|
+
imap_flag :: Flag messages to/from certain people.
|
80
|
+
imap_idle :: Shows new messages in a mailbox.
|
81
|
+
imap_keywords :: Queries an IMAP server for keywords set on messages
|
82
|
+
imap_learn :: Flags messages based on what you've flagged before.
|
83
|
+
imap_mkdir :: Ensures that certain mailboxes exist.
|
84
|
+
email:
|
85
|
+
- ryand-ruby@zenspider.com
|
54
86
|
- drbrain@segment7.net
|
55
|
-
executables:
|
87
|
+
executables:
|
88
|
+
- imap_archive
|
89
|
+
- imap_cleanse
|
90
|
+
- imap_flag
|
91
|
+
- imap_idle
|
56
92
|
- imap_keywords
|
93
|
+
- imap_learn
|
94
|
+
- imap_mkdir
|
57
95
|
extensions: []
|
58
|
-
|
59
|
-
|
60
|
-
- History.txt
|
96
|
+
extra_rdoc_files:
|
97
|
+
- History.rdoc
|
61
98
|
- Manifest.txt
|
62
|
-
- README.
|
63
|
-
files:
|
64
|
-
- .autotest
|
65
|
-
- History.
|
99
|
+
- README.rdoc
|
100
|
+
files:
|
101
|
+
- ".autotest"
|
102
|
+
- History.rdoc
|
66
103
|
- Manifest.txt
|
67
|
-
- README.
|
104
|
+
- README.rdoc
|
68
105
|
- Rakefile
|
106
|
+
- bin/imap_archive
|
107
|
+
- bin/imap_cleanse
|
108
|
+
- bin/imap_flag
|
109
|
+
- bin/imap_idle
|
69
110
|
- bin/imap_keywords
|
111
|
+
- bin/imap_learn
|
112
|
+
- bin/imap_mkdir
|
70
113
|
- lib/imap_processor.rb
|
114
|
+
- lib/imap_processor/archive.rb
|
115
|
+
- lib/imap_processor/cleanse.rb
|
116
|
+
- lib/imap_processor/client.rb
|
117
|
+
- lib/imap_processor/flag.rb
|
118
|
+
- lib/imap_processor/idle.rb
|
71
119
|
- lib/imap_processor/keywords.rb
|
120
|
+
- lib/imap_processor/learn.rb
|
121
|
+
- lib/imap_processor/mkdir.rb
|
72
122
|
- lib/imap_sasl_plain.rb
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
123
|
+
- lib/net/imap/date.rb
|
124
|
+
- lib/net/imap/idle.rb
|
125
|
+
- test/test_imap_processor.rb
|
126
|
+
homepage: https://github.com/seattlerb/imap_processor
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata:
|
130
|
+
homepage_uri: https://github.com/seattlerb/imap_processor
|
77
131
|
post_install_message:
|
78
|
-
rdoc_options:
|
79
|
-
- --main
|
80
|
-
- README.
|
81
|
-
require_paths:
|
132
|
+
rdoc_options:
|
133
|
+
- "--main"
|
134
|
+
- README.rdoc
|
135
|
+
require_paths:
|
82
136
|
- lib
|
83
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
-
requirements:
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
85
139
|
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version:
|
88
|
-
|
89
|
-
|
90
|
-
requirements:
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
91
144
|
- - ">="
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version:
|
94
|
-
version:
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
95
147
|
requirements: []
|
96
|
-
|
97
|
-
rubyforge_project: seattlerb
|
98
|
-
rubygems_version: 1.3.3
|
148
|
+
rubygems_version: 3.0.3
|
99
149
|
signing_key:
|
100
|
-
specification_version:
|
150
|
+
specification_version: 4
|
101
151
|
summary: IMAPProcessor is a client for processing messages on an IMAP server
|
102
152
|
test_files: []
|
103
|
-
|