aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--Makefile2
-rw-r--r--TODO6
-rwxr-xr-xarchivemail.py58
-rwxr-xr-xsetup.py2
-rwxr-xr-xtest_archivemail.py69
6 files changed, 126 insertions, 13 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 92864f5..331dbcd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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
diff --git a/Makefile b/Makefile
index a4df24f..c008b53 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-VERSION=0.4.4
+VERSION=0.4.5
VERSION_TAG=v$(subst .,_,$(VERSION))
TARFILE=archivemail-$(VERSION).tar.gz
diff --git a/TODO b/TODO
index 66a7cef..e178425 100644
--- a/TODO
+++ b/TODO
@@ -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)
diff --git a/archivemail.py b/archivemail.py
index 846e9b0..182d43a 100755
--- a/archivemail.py
+++ b/archivemail.py
@@ -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
diff --git a/setup.py b/setup.py
index bc54008..edfaf21 100755
--- a/setup.py
+++ b/setup.py
@@ -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/",
diff --git a/test_archivemail.py b/test_archivemail.py
index 3f7119e..18d6f4f 100755
--- a/test_archivemail.py
+++ b/test_archivemail.py
@@ -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):