Added a --size option to only archive messages over a certain byte size.

This commit is contained in:
Paul Rodger 2002-04-29 12:20:45 +00:00
parent 244c88d4b9
commit dcff0c0c85
6 changed files with 126 additions and 13 deletions

View File

@ -4,6 +4,8 @@ Version 0.4.5 - 28 April 2002
an mbox mailbox you would get a python error.
* Added a lot more testing to test_archivemail.py (test_archivemail.py is
now 37% bigger than archivemail -- scary)
* Added a new '--size' option which allows you to only archive messages
over a certain size.
Version 0.4.4 - 27 April 2002
* Fixed a bug where the long --suffix option was not working (although the

View File

@ -1,5 +1,5 @@
VERSION=0.4.4
VERSION=0.4.5
VERSION_TAG=v$(subst .,_,$(VERSION))
TARFILE=archivemail-$(VERSION).tar.gz

6
TODO
View File

@ -1,16 +1,14 @@
Goals for next minor release (0.4.5):
Goals for next minor release (0.4.6):
-------------------------------------
* Think about the best way to specify the names of archives created with
possibly an --archive-name option.
* Add a lot more tests (see top of test_archivemail.py)
* Add more tests (see top of test_archivemail.py)
* We need some better checking to see if we are really looking at a valid
mbox-format mailbox.
Goals for next major release (0.5.0):
-------------------------------------
* Add a --size option to only archive messages greater than a certain byte
size.
* Lock any original .gz files
- is this necessary?
* Check for symlink attacks for tempfiles (although we don't use /var/tmp)

View File

@ -22,7 +22,7 @@ Website: http://archivemail.sourceforge.net/
"""
# global administrivia
__version__ = "archivemail v0.4.4"
__version__ = "archivemail v0.4.5"
__cvs_id__ = "$Id$"
__copyright__ = """Copyright (C) 2002 Paul Rodger <paul@paulrodger.com>
This is free software; see the source for copying conditions. There is NO
@ -147,6 +147,7 @@ class Options:
quiet = 0
read_buffer_size = 8192
script_name = os.path.basename(sys.argv[0])
min_size = None
verbose = 0
warn_duplicates = 0
@ -162,11 +163,11 @@ class Options:
"""
try:
opts, args = getopt.getopt(args, '?D:Vd:hno:qs:uv',
opts, args = getopt.getopt(args, '?D:S:Vd:hno:qs:uv',
["date=", "days=", "delete", "dry-run", "help",
"include-flagged", "no-compress", "output-dir=",
"preserve-unread", "quiet", "suffix=", "verbose",
"version", "warn-duplicate"])
"include-flagged", "no-compress", "output-dir=",
"preserve-unread", "quiet", "size=", "suffix=",
"verbose", "version", "warn-duplicate"])
except getopt.error, msg:
user_error(msg)
@ -202,6 +203,8 @@ class Options:
self.quiet = 1
if o in ('-s', '--suffix'):
self.archive_suffix = a
if o in ('-S', '--size'):
self.min_size = string.atoi(a)
if o in ('-u', '--preserve-unread'):
self.preserve_unread = 1
if o in ('-v', '--verbose'):
@ -224,9 +227,11 @@ class Options:
unexpected_error(("output directory is world-writable: " + \
"%s -- I feel nervous!") % self.output_dir)
if self.days_old_max < 1:
user_error("argument to -d must be greater than zero")
user_error("--days argument must be greater than zero")
if self.days_old_max >= 10000:
user_error("argument to -d must be less than 10000")
user_error("--days argument must be less than 10000")
if self.min_size is not None and self.min_size < 1:
user_error("--size argument must be greater than zero")
if self.quiet and self.verbose:
user_error("you cannot use both the --quiet and --verbose options")
@ -563,6 +568,7 @@ Options are as follows:
-D, --date=DATE archive messages older than DATE
-o, --output-dir=DIR directory to store archives (default: same as original)
-s, --suffix=NAME suffix for archive filename (default: '%s')
-S, --size=NUM only archive messages NUM bytes or larger
-n, --dry-run don't write to anything - just show what would be done
-u, --preserve-unread never archive unread messages
--delete delete rather than archive old mail (use with caution!)
@ -780,6 +786,42 @@ def is_unread(message):
return 1
def is_smaller(message, size):
"""Return true if the message is smaller than size bytes, false otherwise"""
assert(message)
assert(size > 0)
file_name = None
message_size = None
try:
file_name = message.fp.name
except AttributeError:
pass
if file_name:
# with maildir and MH mailboxes, we can just use the file size
message_size = os.path.getsize(file_name)
else:
# with mbox mailboxes, not so easy
message_size = 0
if message.unixfrom:
message_size = message_size + len(message.unixfrom)
for header in message.headers:
message_size = message_size + len(header)
message_size = message_size + 1 # the blank line after the headers
start_offset = message.fp.tell()
message.fp.seek(0, 2) # seek to the end of the message
end_offset = message.fp.tell()
message.rewindbody()
message_size = message_size + (end_offset - start_offset)
if message_size < size:
vprint("message is too small (%d bytes), minimum bytes : %d" % \
(message_size, size))
return 1
else:
vprint("message is not too small (%d bytes), minimum bytes: %d" % \
(message_size, size))
return 0
def should_archive(message):
"""Return true if we should archive the message, false otherwise"""
old = 0
@ -795,6 +837,8 @@ def should_archive(message):
return 0
if not options.include_flagged and is_flagged(message):
return 0
if options.min_size and is_smaller(message, options.min_size):
return 0
if options.preserve_unread and is_unread(message):
return 0
return 1

View File

@ -19,7 +19,7 @@ check_python_version() # define & run this early - 'distutils.core' is new
from distutils.core import setup
setup(name="archivemail",
version="0.4.4",
version="0.4.5",
description="archive and compress old email",
license="GNU GPL",
url="http://archivemail.sourceforge.net/",

View File

@ -1216,6 +1216,75 @@ class TestArchiveMboxUncompressed(unittest.TestCase):
os.remove(name)
class TestArchiveSize(unittest.TestCase):
"""check that the 'size' argument works"""
def testSmaller(self):
"""giving a size argument smaller than the message"""
for execute in ("package", "system_long", "system_short"):
self.mbox_name = make_mbox(messages=1, hours_old=(24 * 181))
size_arg = os.path.getsize(self.mbox_name) - 1
self.copy_name = tempfile.mktemp()
shutil.copyfile(self.mbox_name, self.copy_name)
if execute == "package":
archivemail.options.quiet = 1
archivemail.options.min_size = size_arg
archivemail.archive(self.mbox_name)
elif execute == "system_long":
run = "./archivemail.py --size=%d --quiet %s" % \
(size_arg, self.mbox_name)
self.assertEqual(os.system(run), 0)
elif execute == "system_short":
run = "./archivemail.py -S%d --quiet %s" % \
(size_arg, self.mbox_name)
self.assertEqual(os.system(run), 0)
else:
sys.exit(1)
assert(os.path.exists(self.mbox_name))
self.assertEqual(os.path.getsize(self.mbox_name), 0)
archive_name = self.mbox_name + "_archive.gz"
assert(os.path.exists(archive_name))
self.assertEqual(os.system("gzip -d %s" % archive_name), 0)
archive_name = self.mbox_name + "_archive"
assert(os.path.exists(archive_name))
assert(filecmp.cmp(archive_name, self.copy_name, shallow=0))
self.tearDown()
def testBigger(self):
"""giving a size argument bigger than the message"""
for execute in ("package", "system_long", "system_short"):
self.mbox_name = make_mbox(messages=1, hours_old=(24 * 181))
size_arg = os.path.getsize(self.mbox_name) + 1
self.copy_name = tempfile.mktemp()
shutil.copyfile(self.mbox_name, self.copy_name)
if execute == "package":
archivemail.options.quiet = 1
archivemail.options.min_size = size_arg
archivemail.archive(self.mbox_name)
elif execute == "system_long":
run = "./archivemail.py --size=%d --quiet %s" % \
(size_arg, self.mbox_name)
self.assertEqual(os.system(run), 0)
elif execute == "system_short":
run = "./archivemail.py -S%d --quiet %s" % \
(size_arg, self.mbox_name)
self.assertEqual(os.system(run), 0)
else:
sys.exit(1)
assert(os.path.exists(self.mbox_name))
assert(filecmp.cmp(self.mbox_name, self.copy_name, shallow=0))
archive_name = self.mbox_name + "_archive.gz"
assert(not os.path.exists(archive_name))
self.tearDown()
def tearDown(self):
archivemail.options.quiet = 0
archivemail.options.min_size = None
archive = self.mbox_name + "_archive"
for name in (self.mbox_name, self.copy_name, archive, archive + ".gz"):
if name and os.path.exists(name):
os.remove(name)
class TestArchiveMboxMode(unittest.TestCase):
"""file mode (permissions) of the original mbox should be preserved"""
def testOld(self):