IMAPCleanse 1.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.
- data/.DS_Store +0 -0
- data/CVS/Entries +6 -0
- data/CVS/Repository +1 -0
- data/CVS/Root +1 -0
- data/LICENSE +27 -0
- data/Manifest.txt +16 -0
- data/README +80 -0
- data/Rakefile +58 -0
- data/bin/CVS/Entries +2 -0
- data/bin/CVS/Repository +1 -0
- data/bin/CVS/Root +1 -0
- data/bin/imap_cleanse +6 -0
- data/lib/CVS/Entries +2 -0
- data/lib/CVS/Repository +1 -0
- data/lib/CVS/Root +1 -0
- data/lib/imap_cleanse.rb +347 -0
- metadata +61 -0
data/.DS_Store
ADDED
Binary file
|
data/CVS/Entries
ADDED
data/CVS/Repository
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby/imap_cleanse
|
data/CVS/Root
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
:ext:drbrain@ziz:/home/cvs/
|
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright 2005 Eric Hodel. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
3. Neither the names of the authors nor the names of their contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
17
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
20
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
21
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
22
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
23
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
25
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
data/Manifest.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
.DS_Store
|
2
|
+
CVS/Entries
|
3
|
+
CVS/Repository
|
4
|
+
CVS/Root
|
5
|
+
LICENSE
|
6
|
+
Manifest.txt
|
7
|
+
README
|
8
|
+
Rakefile
|
9
|
+
bin/CVS/Entries
|
10
|
+
bin/CVS/Repository
|
11
|
+
bin/CVS/Root
|
12
|
+
bin/imap_cleanse
|
13
|
+
lib/CVS/Entries
|
14
|
+
lib/CVS/Repository
|
15
|
+
lib/CVS/Root
|
16
|
+
lib/imap_cleanse.rb
|
data/README
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
= IMAPCleanse
|
2
|
+
|
3
|
+
Rubyforge Project:
|
4
|
+
|
5
|
+
http://rubyforge.org/projects/seattlerb/
|
6
|
+
|
7
|
+
Documentation:
|
8
|
+
|
9
|
+
http://seattlerb.rubyforge.org/IMAPCleanse/
|
10
|
+
|
11
|
+
== About
|
12
|
+
|
13
|
+
IMAPCleanse removes old, read, unflagged messages from your IMAP mailboxes.
|
14
|
+
|
15
|
+
== Why?
|
16
|
+
|
17
|
+
I'm lazy. I don't delete read messages from my mailboxes because I like to
|
18
|
+
have context when reading threads. Since I'm lazy my more-trafficed mailboxes
|
19
|
+
can end up with tens of thousands of read messages. Deleting this many
|
20
|
+
messages with Mail.app is time consuming and boring.
|
21
|
+
|
22
|
+
So I wrote IMAPCleanse to clean out my old mailboxes for me. If I want to keep
|
23
|
+
a message around for forever I'll just flag it and IMAPCleanse won't touch it.
|
24
|
+
|
25
|
+
== Installing IMAPCleanse
|
26
|
+
|
27
|
+
Just install the gem:
|
28
|
+
|
29
|
+
$ sudo gem install IMAPCleanse
|
30
|
+
|
31
|
+
== Using IMAPCleanse
|
32
|
+
|
33
|
+
In short:
|
34
|
+
|
35
|
+
imap_cleanse -H mail.example.com -p mypassword -b Lists/FreeBSD/current,Lists/Ruby -a 30
|
36
|
+
|
37
|
+
The help for IMAPCleanse should be sufficiently verbose, but here's a couple of
|
38
|
+
tips:
|
39
|
+
|
40
|
+
=== --noop and --verbose
|
41
|
+
|
42
|
+
The --noop flag tells IMAPCleanse not to delete anything. When combined with
|
43
|
+
the --verbose flag you can see how many messages IMAPCleanse would have deleted
|
44
|
+
from which mailboxes.
|
45
|
+
|
46
|
+
$ ruby -Ilib bin/imap_cleanse -nv
|
47
|
+
# Connected to mail.example.com:993
|
48
|
+
# Logged in as drbrain
|
49
|
+
# Cleansing read, unflagged messages older than 26-Feb-2006 17:04 PST
|
50
|
+
# Found 23 mailboxes to cleanse:
|
51
|
+
# mail/Lists/FreeBSD/current
|
52
|
+
[...]
|
53
|
+
# mail/Lists/Ruby/ZineBoard
|
54
|
+
# Selected mail/Lists/FreeBSD/current
|
55
|
+
# Scanning for messages
|
56
|
+
# Found 0 messages
|
57
|
+
[...]
|
58
|
+
# Selected mail/Lists/Ruby/ZineBoard
|
59
|
+
# Scanning for messages
|
60
|
+
# Found 0 messages
|
61
|
+
# Done. Found 0 messages in 23 mailboxes
|
62
|
+
|
63
|
+
(Since I just ran IMAPCleanse it didn't have anything to do.)
|
64
|
+
|
65
|
+
=== ~/.imap_cleanse
|
66
|
+
|
67
|
+
The ~/.imap_cleanse file can hold your password and other options so you don't
|
68
|
+
have to type them in on the command line every time. The format is simple,
|
69
|
+
just the options file name followed by '=' followed by the argument.
|
70
|
+
|
71
|
+
No whitespace is stripped from options, so be sure to do that yourself. Mine
|
72
|
+
looks something like this:
|
73
|
+
|
74
|
+
Host=mail.example.com
|
75
|
+
SSL=true
|
76
|
+
Username=drbrain
|
77
|
+
Boxes=Lists/FreeBSD/current,Lists/FreeBSD/performance,Lists/FreeBSD/Soekris,Lists/FreeBSD/stable,Lists/Ruby
|
78
|
+
Age=30
|
79
|
+
Password=my password
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
$VERBOSE = nil
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'IMAPCleanse'
|
11
|
+
s.version = '1.0.0'
|
12
|
+
s.summary = 'Cleanses your IMAP mailboxes of oldness'
|
13
|
+
s.description = 'IMAPCleanse removes old, read, unflagged messages from your IMAP mailboxes so you don\'t have to!'
|
14
|
+
s.author = 'Eric Hodel'
|
15
|
+
s.email = 'drbrain@segment7.net'
|
16
|
+
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.files = File.read('Manifest.txt').split($/)
|
19
|
+
s.require_path = 'lib'
|
20
|
+
s.executables = 'imap_cleanse'
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Run tests'
|
24
|
+
task :default => [ :test ]
|
25
|
+
|
26
|
+
Rake::TestTask.new('test') do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/test_*.rb'
|
29
|
+
t.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Update Manifest.txt'
|
33
|
+
task :update_manifest do
|
34
|
+
sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Generate RDoc'
|
38
|
+
Rake::RDocTask.new :rdoc do |rd|
|
39
|
+
rd.rdoc_dir = 'doc'
|
40
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
41
|
+
rd.main = 'README'
|
42
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
43
|
+
rd.options << '-t IMAPCreate'
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Build Gem'
|
47
|
+
Rake::GemPackageTask.new spec do |pkg|
|
48
|
+
pkg.need_tar = true
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Clean up'
|
52
|
+
task :clean => [ :clobber_rdoc, :clobber_package ]
|
53
|
+
|
54
|
+
desc 'Clean up'
|
55
|
+
task :clobber => [ :clean ]
|
56
|
+
|
57
|
+
# vim: syntax=Ruby
|
58
|
+
|
data/bin/CVS/Entries
ADDED
data/bin/CVS/Repository
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby/imap_cleanse/bin
|
data/bin/CVS/Root
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
:ext:drbrain@ziz:/home/cvs/
|
data/bin/imap_cleanse
ADDED
data/lib/CVS/Entries
ADDED
data/lib/CVS/Repository
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby/imap_cleanse/lib
|
data/lib/CVS/Root
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
:ext:drbrain@ziz:/home/cvs/
|
data/lib/imap_cleanse.rb
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
require 'net/imap'
|
2
|
+
require 'optparse'
|
3
|
+
require 'pp'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
class Time
|
7
|
+
|
8
|
+
##
|
9
|
+
# Formats this Time as an IMAP-style date.
|
10
|
+
#
|
11
|
+
# RFC 2060 doesn't specify the format of its times. Unfortunately it is
|
12
|
+
# almost but not quite RFC 822 dates.
|
13
|
+
|
14
|
+
def imapdate
|
15
|
+
strftime '%d-%b-%Y %H:%M %Z'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# RFC 2595 PLAIN Authenticator for Net::IMAP. Only for use with SSL (but not
|
21
|
+
# enforced).
|
22
|
+
|
23
|
+
class Net::IMAP::PlainAuthenticator
|
24
|
+
|
25
|
+
##
|
26
|
+
# From RFC 2595 Section 6. PLAIN SASL Authentication
|
27
|
+
#
|
28
|
+
# The mechanism consists of a single message from the client to the
|
29
|
+
# server. The client sends the authorization identity (identity to
|
30
|
+
# login as), followed by a US-ASCII NUL character, followed by the
|
31
|
+
# authentication identity (identity whose password will be used),
|
32
|
+
# followed by a US-ASCII NUL character, followed by the clear-text
|
33
|
+
# password. The client may leave the authorization identity empty to
|
34
|
+
# indicate that it is the same as the authentication identity.
|
35
|
+
|
36
|
+
def process(data)
|
37
|
+
return [@user, @user, @password].join("\0")
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
##
|
43
|
+
# Creates a new PlainAuthenticator that will authenticate with +user+ and
|
44
|
+
# +password+.
|
45
|
+
|
46
|
+
def initialize(user, password)
|
47
|
+
@user = user
|
48
|
+
@password = password
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
if defined? OpenSSL then
|
54
|
+
Net::IMAP.add_authenticator 'PLAIN', Net::IMAP::PlainAuthenticator
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# IMAPCleanse removes old messages from your IMAP mailboxes so you don't have
|
59
|
+
# to!
|
60
|
+
|
61
|
+
class IMAPCleanse
|
62
|
+
|
63
|
+
##
|
64
|
+
# Handles processing of +args+.
|
65
|
+
|
66
|
+
def self.process_args(args)
|
67
|
+
opts_file = File.expand_path '~/.imap_cleanse'
|
68
|
+
|
69
|
+
unless File.stat(opts_file).mode & 077 == 0 then
|
70
|
+
STDERR.puts "WARNING! #{opts_file} is group/other readable or writable!"
|
71
|
+
STDERR.puts "WARNING! I'm not doing a thing until you fix it!"
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
|
75
|
+
options = {}
|
76
|
+
|
77
|
+
File.readlines(opts_file).map { |l| l.chomp.split '=', 2 }.each do |k,v|
|
78
|
+
v = true if v == 'true'
|
79
|
+
v = false if v == 'false'
|
80
|
+
v = Integer(v) rescue v
|
81
|
+
options[k.intern] = v
|
82
|
+
end
|
83
|
+
|
84
|
+
options[:SSL] ||= true
|
85
|
+
options[:Username] ||= ENV['USER']
|
86
|
+
options[:Root] ||= 'mail'
|
87
|
+
options[:Noop] ||= false
|
88
|
+
options[:Verbose] ||= false
|
89
|
+
|
90
|
+
opts = OptionParser.new do |opts|
|
91
|
+
opts.banner = 'Usage: imap_cleanse [options]'
|
92
|
+
opts.separator ''
|
93
|
+
opts.separator 'Options may also be set in the options file ~/.imap_cleanse.'
|
94
|
+
opts.separator ''
|
95
|
+
opts.separator 'Example ~/.imap_cleanse:'
|
96
|
+
opts.separator "\tHost=mail.example.com"
|
97
|
+
opts.separator "\tPassword=my password"
|
98
|
+
|
99
|
+
opts.separator ''
|
100
|
+
opts.separator 'Connection options:'
|
101
|
+
|
102
|
+
opts.on("-H", "--host HOST",
|
103
|
+
"IMAP server host",
|
104
|
+
"Default: #{options[:Host].inspect}",
|
105
|
+
"Options file name: Host") do |host|
|
106
|
+
options[:Host] = host
|
107
|
+
end
|
108
|
+
|
109
|
+
opts.on("-P", "--port PORT",
|
110
|
+
"IMAP server port",
|
111
|
+
"Default: The correct port SSL/non-SSL mode",
|
112
|
+
"Options file name: Port") do |port|
|
113
|
+
options[:Port] = port
|
114
|
+
end
|
115
|
+
|
116
|
+
opts.on("-s", "--[no-]ssl",
|
117
|
+
"Use SSL for IMAP connection",
|
118
|
+
"Default: #{options[:SSL].inspect}",
|
119
|
+
"Options file name: SSL") do |ssl|
|
120
|
+
options[:SSL] = ssl
|
121
|
+
end
|
122
|
+
|
123
|
+
opts.separator ''
|
124
|
+
opts.separator 'Login options:'
|
125
|
+
|
126
|
+
opts.on("-u", "--username USERNAME",
|
127
|
+
"IMAP username",
|
128
|
+
"Default: #{options[:Username].inspect}",
|
129
|
+
"Options file name: Username") do |username|
|
130
|
+
options[:Username] = username
|
131
|
+
end
|
132
|
+
|
133
|
+
opts.on("-p", "--password PASSWORD",
|
134
|
+
"IMAP password",
|
135
|
+
"Default: Read from ~/.imap_cleanse",
|
136
|
+
"Options file name: Password") do |password|
|
137
|
+
options[:Password] = password
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.separator ''
|
141
|
+
opts.separator 'Cleansing options:'
|
142
|
+
|
143
|
+
opts.on("-r", "--root ROOT",
|
144
|
+
"Root of mailbox hierarchy",
|
145
|
+
"Default: #{options[:Root].inspect}",
|
146
|
+
"Options file name: Root") do |root|
|
147
|
+
options[:Root] = root
|
148
|
+
end
|
149
|
+
|
150
|
+
opts.on("-b", "--boxes BOXES",
|
151
|
+
"Comma-separated list of mailbox name",
|
152
|
+
"prefixes to cleanse",
|
153
|
+
"Default: #{options[:Boxes].inspect}",
|
154
|
+
"Options file name: Boxes") do |boxes|
|
155
|
+
options[:Boxes] = boxes
|
156
|
+
end
|
157
|
+
|
158
|
+
opts.on("-a", "--age AGE",
|
159
|
+
"Delete messages more than AGE days old",
|
160
|
+
"Default: #{options[:Age].inspect}",
|
161
|
+
"Options file name: Age", Integer) do |age|
|
162
|
+
options[:Age] = age
|
163
|
+
end
|
164
|
+
|
165
|
+
opts.on("-n", "--noop",
|
166
|
+
"Perform no destructive operations",
|
167
|
+
"Best used with the verbose option",
|
168
|
+
"Default: #{options[:Noop].inspect}",
|
169
|
+
"Options file name: Noop") do |noop|
|
170
|
+
options[:Noop] = noop
|
171
|
+
end
|
172
|
+
|
173
|
+
opts.on("-v", "--[no-]verbose",
|
174
|
+
"Be verbose",
|
175
|
+
"Default: #{options[:Verbose].inspect}",
|
176
|
+
"Options file name: Verbose") do |verbose|
|
177
|
+
options[:Verbose] = verbose
|
178
|
+
end
|
179
|
+
|
180
|
+
opts.separator ''
|
181
|
+
|
182
|
+
opts.on("-h", "--help",
|
183
|
+
"You're looking at it") do
|
184
|
+
STDERR.puts opts
|
185
|
+
exit 1
|
186
|
+
end
|
187
|
+
|
188
|
+
opts.separator ''
|
189
|
+
end
|
190
|
+
|
191
|
+
opts.parse! args
|
192
|
+
|
193
|
+
options[:Port] ||= options[:SSL] ? 993 : 143
|
194
|
+
|
195
|
+
if options[:Host].nil? or
|
196
|
+
options[:Password].nil? or
|
197
|
+
options[:Boxes].nil? or
|
198
|
+
options[:Age].nil? then
|
199
|
+
STDERR.puts opts
|
200
|
+
STDERR.puts
|
201
|
+
STDERR.puts "Host name not set" if options[:Host].nil?
|
202
|
+
STDERR.puts "Password not set" if options[:Password].nil?
|
203
|
+
STDERR.puts "Boxes option not set" if options[:Boxes].nil?
|
204
|
+
STDERR.puts "Age option not set" if options[:Age].nil?
|
205
|
+
exit 1
|
206
|
+
end
|
207
|
+
|
208
|
+
return options
|
209
|
+
end
|
210
|
+
|
211
|
+
##
|
212
|
+
# Sets up IMAPCleanse options then cleanses mailboxes.
|
213
|
+
|
214
|
+
def self.run(args = ARGV)
|
215
|
+
options = process_args args
|
216
|
+
cleanser = new options
|
217
|
+
cleanser.cleanse
|
218
|
+
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# Creates a new IMAPCleanse from +options+.
|
222
|
+
#
|
223
|
+
# Options include:
|
224
|
+
# +:Verbose+:: Verbose flag
|
225
|
+
# +:Noop+:: Don't delete anything flag
|
226
|
+
# +:Root+:: IMAP root path
|
227
|
+
# +:Boxes+:: Comma-separated list of mailbox prefixes to cleanse
|
228
|
+
# +:Age+:: Delete messages older than this many days ago
|
229
|
+
# +:Host+:: IMAP server
|
230
|
+
# +:Port+:: IMAP server port
|
231
|
+
# +:SSL+:: SSL flag
|
232
|
+
# +:Username+:: IMAP username
|
233
|
+
# +:Password+:: IMAP password
|
234
|
+
|
235
|
+
def initialize(options)
|
236
|
+
@verbose = options[:Verbose]
|
237
|
+
@noop = options[:Noop]
|
238
|
+
@root = options[:Root]
|
239
|
+
|
240
|
+
boxes = options[:Boxes].split(',').map { |b| Regexp.escape b }
|
241
|
+
@box_re = /^#{Regexp.escape @root}\/#{Regexp.union(*boxes)}/
|
242
|
+
|
243
|
+
@before_date = (Time.now - 86400 * options[:Age]).imapdate
|
244
|
+
|
245
|
+
connect options[:Host], options[:Port], options[:SSL],
|
246
|
+
options[:Username], options[:Password]
|
247
|
+
end
|
248
|
+
|
249
|
+
##
|
250
|
+
# Removes read, unflagged messages from all selected mailboxes...
|
251
|
+
#
|
252
|
+
# Unless :Noop was set, then it just prints out what it would do.
|
253
|
+
|
254
|
+
def cleanse
|
255
|
+
log "Cleansing read, unflagged messages older than #{@before_date}"
|
256
|
+
|
257
|
+
message_count = 0
|
258
|
+
mailboxes = find_mailboxes
|
259
|
+
|
260
|
+
mailboxes.each do |mailbox|
|
261
|
+
@imap.select mailbox
|
262
|
+
log "Selected #{mailbox}"
|
263
|
+
|
264
|
+
messages = old_messages_in_curr
|
265
|
+
next if messages.empty?
|
266
|
+
|
267
|
+
message_count += messages.length
|
268
|
+
|
269
|
+
if @noop then
|
270
|
+
log "Noop - nothing deleted"
|
271
|
+
next
|
272
|
+
end
|
273
|
+
|
274
|
+
purge messages
|
275
|
+
end
|
276
|
+
|
277
|
+
log "Done. Found #{message_count} messages in #{mailboxes.length} mailboxes"
|
278
|
+
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
##
|
283
|
+
# Connects to IMAP server +host+ at +port+ using ssl if +ssl+ is true then
|
284
|
+
# logs in as +username+ with +password+. IMAPCleanse will really only work
|
285
|
+
# with PLAIN auth on SSL sockets, sorry.
|
286
|
+
|
287
|
+
def connect(host, port, ssl, username, password)
|
288
|
+
@imap = Net::IMAP.new host, port, ssl
|
289
|
+
log "Connected to #{host}:#{port}"
|
290
|
+
@imap.authenticate 'PLAIN', username, password
|
291
|
+
log "Logged in as #{username}"
|
292
|
+
end
|
293
|
+
|
294
|
+
##
|
295
|
+
# Finds mailboxes with messages that were selected by the :Boxes option.
|
296
|
+
|
297
|
+
def find_mailboxes
|
298
|
+
mailboxes = @imap.list(@root, "*")
|
299
|
+
mailboxes.reject! { |mailbox| mailbox.attr.include? :Noselect }
|
300
|
+
mailboxes.map! { |mailbox| mailbox.name }
|
301
|
+
mailboxes.reject! { |mailbox| mailbox !~ @box_re }
|
302
|
+
mailboxes = mailboxes.sort_by { |m| m.downcase }
|
303
|
+
log "Found #{mailboxes.length} mailboxes to cleanse:"
|
304
|
+
mailboxes.each { |mailbox| log "\t#{mailbox}" } if @verbose
|
305
|
+
return mailboxes
|
306
|
+
end
|
307
|
+
|
308
|
+
##
|
309
|
+
# Logs +message+ to STDERR if :Verbose was selected.
|
310
|
+
|
311
|
+
def log(message)
|
312
|
+
return unless @verbose
|
313
|
+
STDERR.puts "# #{message}"
|
314
|
+
end
|
315
|
+
|
316
|
+
##
|
317
|
+
# Searches for read, unflagged messages older than :Age in the currently
|
318
|
+
# selected mailbox (see Net::IMAP#select).
|
319
|
+
|
320
|
+
def old_messages_in_curr
|
321
|
+
log "Scanning for messages"
|
322
|
+
messages = @imap.search [
|
323
|
+
'NOT', 'NEW',
|
324
|
+
'NOT', 'FLAGGED',
|
325
|
+
'BEFORE', @before_date
|
326
|
+
]
|
327
|
+
log "Found #{messages.length} messages"
|
328
|
+
return messages
|
329
|
+
end
|
330
|
+
|
331
|
+
##
|
332
|
+
# Marks +messages+ in the currently selected mailbox for deletion then
|
333
|
+
# expunges the mailbox (see Net::IMAP#store and Net::IMAP#expunge).
|
334
|
+
|
335
|
+
def purge(messages)
|
336
|
+
until messages.empty? do
|
337
|
+
chunk = messages.slice! 0, 500
|
338
|
+
@imap.store chunk, '+FLAGS', [:Deleted]
|
339
|
+
end
|
340
|
+
log "Marked messages for deletion"
|
341
|
+
|
342
|
+
@imap.expunge
|
343
|
+
log "Expunged deleted messages"
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
347
|
+
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11.6
|
3
|
+
specification_version: 1
|
4
|
+
name: IMAPCleanse
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2006-03-28 00:00:00 -08:00
|
8
|
+
summary: Cleanses your IMAP mailboxes of oldness
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: drbrain@segment7.net
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: IMAPCleanse removes old, read, unflagged messages from your IMAP mailboxes so you don't have to!
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Eric Hodel
|
31
|
+
files:
|
32
|
+
- .DS_Store
|
33
|
+
- CVS/Entries
|
34
|
+
- CVS/Repository
|
35
|
+
- CVS/Root
|
36
|
+
- LICENSE
|
37
|
+
- Manifest.txt
|
38
|
+
- README
|
39
|
+
- Rakefile
|
40
|
+
- bin/CVS/Entries
|
41
|
+
- bin/CVS/Repository
|
42
|
+
- bin/CVS/Root
|
43
|
+
- bin/imap_cleanse
|
44
|
+
- lib/CVS/Entries
|
45
|
+
- lib/CVS/Repository
|
46
|
+
- lib/CVS/Root
|
47
|
+
- lib/imap_cleanse.rb
|
48
|
+
test_files: []
|
49
|
+
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
extra_rdoc_files: []
|
53
|
+
|
54
|
+
executables:
|
55
|
+
- imap_cleanse
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
dependencies: []
|
61
|
+
|