imap_processor 1.1.1 → 1.7
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.
- 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
|
-
|