newerthan #1
94
archivemail
94
archivemail
|
|
@ -180,6 +180,8 @@ class Options:
|
||||||
archive_name = None
|
archive_name = None
|
||||||
days_old_max = 180
|
days_old_max = 180
|
||||||
date_old_max = None
|
date_old_max = None
|
||||||
|
days_old_min = 10950
|
||||||
|
date_old_min = None
|
||||||
delete_old_mail = False
|
delete_old_mail = False
|
||||||
dry_run = False
|
dry_run = False
|
||||||
filter_append = None
|
filter_append = None
|
||||||
|
|
@ -215,8 +217,8 @@ class Options:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(args, '?D:S:Vd:hno:F:P:qs:p:a:uv',
|
opts, args = getopt.getopt(args, '?D:M:S:Vd:m:hno:F:P:qs:p:a:uv',
|
||||||
["date=", "days=", "delete", "dry-run", "help",
|
["date=", "days=", "mindate=", "mindays=", "delete", "dry-run", "help",
|
||||||
"include-flagged", "no-compress", "output-dir=",
|
"include-flagged", "no-compress", "output-dir=",
|
||||||
"filter-append=", "pwfile=", "dont-mangle",
|
"filter-append=", "pwfile=", "dont-mangle",
|
||||||
"preserve-unread", "quiet", "size=", "suffix=",
|
"preserve-unread", "quiet", "size=", "suffix=",
|
||||||
|
|
@ -226,7 +228,8 @@ class Options:
|
||||||
except getopt.error, msg:
|
except getopt.error, msg:
|
||||||
user_error(msg)
|
user_error(msg)
|
||||||
|
|
||||||
archive_by = None
|
archive_by_max = None
|
||||||
|
archive_by_min = None
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
if o == '--delete':
|
if o == '--delete':
|
||||||
|
|
@ -240,15 +243,25 @@ class Options:
|
||||||
if o == '--warn-duplicate':
|
if o == '--warn-duplicate':
|
||||||
self.warn_duplicates = True
|
self.warn_duplicates = True
|
||||||
if o in ('-D', '--date'):
|
if o in ('-D', '--date'):
|
||||||
if archive_by:
|
if archive_by_max:
|
||||||
user_error("you cannot specify both -d and -D options")
|
user_error("you cannot specify both -d and -D options")
|
||||||
archive_by = "date"
|
archive_by_max = "date"
|
||||||
self.date_old_max = self.date_argument(a)
|
self.date_old_max = self.date_argument(a)
|
||||||
if o in ('-d', '--days'):
|
if o in ('-d', '--days'):
|
||||||
if archive_by:
|
if archive_by_max:
|
||||||
user_error("you cannot specify both -d and -D options")
|
user_error("you cannot specify both -d and -D options")
|
||||||
archive_by = "days"
|
archive_by_max = "days"
|
||||||
self.days_old_max = string.atoi(a)
|
self.days_old_max = string.atoi(a)
|
||||||
|
if o in ('-M', '--mindate'):
|
||||||
|
if archive_by_min:
|
||||||
|
user_error("you cannot specify both -m and -M options")
|
||||||
|
archive_by_min = "date"
|
||||||
|
self.date_old_min = self.date_argument(a)
|
||||||
|
if o in ('-m', '--mindays'):
|
||||||
|
if archive_by_min:
|
||||||
|
user_error("you cannot specify both -m and -M options")
|
||||||
|
archive_by_min = "days"
|
||||||
|
self.days_old_min = string.atoi(a)
|
||||||
if o in ('-o', '--output-dir'):
|
if o in ('-o', '--output-dir'):
|
||||||
self.output_dir = os.path.expanduser(a)
|
self.output_dir = os.path.expanduser(a)
|
||||||
if o in ('-P', '--pwfile'):
|
if o in ('-P', '--pwfile'):
|
||||||
|
|
@ -295,8 +308,12 @@ class Options:
|
||||||
check_sane_destdir(self.output_dir)
|
check_sane_destdir(self.output_dir)
|
||||||
if self.days_old_max < 0:
|
if self.days_old_max < 0:
|
||||||
user_error("--days argument must be positive")
|
user_error("--days argument must be positive")
|
||||||
if self.days_old_max >= 10000:
|
if self.days_old_max >= 100000:
|
||||||
user_error("--days argument must be less than 10000")
|
user_error("--days argument must be less than 100000")
|
||||||
|
if self.days_old_min < 0:
|
||||||
|
user_error("--mindays argument must be positive")
|
||||||
|
if self.days_old_max >= 100000:
|
||||||
|
user_error("--mindays argument must be less than 100000")
|
||||||
if self.min_size is not None and self.min_size < 1:
|
if self.min_size is not None and self.min_size < 1:
|
||||||
user_error("--size argument must be greater than zero")
|
user_error("--size argument must be greater than zero")
|
||||||
if self.quiet and self.verbose:
|
if self.quiet and self.verbose:
|
||||||
|
|
@ -653,6 +670,8 @@ mailbox compressed with gzip.
|
||||||
Options are as follows:
|
Options are as follows:
|
||||||
-d, --days=NUM archive messages older than NUM days (default: %d)
|
-d, --days=NUM archive messages older than NUM days (default: %d)
|
||||||
-D, --date=DATE archive messages older than DATE
|
-D, --date=DATE archive messages older than DATE
|
||||||
|
-m, --mindays=NUM archive messages newer than NUM days (default: %d)
|
||||||
|
-N, --mindate=DATE archive messages newer than DATE
|
||||||
-o, --output-dir=DIR directory to store archives (default: same as original)
|
-o, --output-dir=DIR directory to store archives (default: same as original)
|
||||||
-P, --pwfile=FILE file to read imap password from (default: None)
|
-P, --pwfile=FILE file to read imap password from (default: None)
|
||||||
-F, --filter-append=STRING append arbitrary string to the IMAP filter string
|
-F, --filter-append=STRING append arbitrary string to the IMAP filter string
|
||||||
|
|
@ -686,7 +705,7 @@ To archive IMAP mailboxes, format your mailbox argument like this:
|
||||||
(substitute 'imap' with 'imaps' for an SSL connection)
|
(substitute 'imap' with 'imaps' for an SSL connection)
|
||||||
|
|
||||||
Website: http://archivemail.sourceforge.net/ """ % \
|
Website: http://archivemail.sourceforge.net/ """ % \
|
||||||
(options.script_name, options.days_old_max, options.archive_suffix,
|
(options.script_name, options.days_old_max, options.days_old_min, options.archive_suffix,
|
||||||
options.script_name, options.days_old_max)
|
options.script_name, options.days_old_max)
|
||||||
|
|
||||||
args = options.parse_args(args, usage)
|
args = options.parse_args(args, usage)
|
||||||
|
|
@ -997,11 +1016,17 @@ def should_archive(message):
|
||||||
old = is_older_than_days(time_message, options.days_old_max)
|
old = is_older_than_days(time_message, options.days_old_max)
|
||||||
else:
|
else:
|
||||||
old = is_older_than_time(time_message, options.date_old_max)
|
old = is_older_than_time(time_message, options.date_old_max)
|
||||||
|
if options.date_old_min == None:
|
||||||
|
new = is_younger_than_days(time_message, options.days_old_min)
|
||||||
|
else:
|
||||||
|
new = is_younger_than_time(time_message, options.date_old_min)
|
||||||
|
|
||||||
# I could probably do this in one if statement, but then I wouldn't
|
# I could probably do this in one if statement, but then I wouldn't
|
||||||
# understand it.
|
# understand it.
|
||||||
if not old:
|
if not old:
|
||||||
return False
|
return False
|
||||||
|
if not new:
|
||||||
|
return False
|
||||||
if not options.include_flagged and is_flagged(message):
|
if not options.include_flagged and is_flagged(message):
|
||||||
return False
|
return False
|
||||||
if options.min_size and is_smaller(message, options.min_size):
|
if options.min_size and is_smaller(message, options.min_size):
|
||||||
|
|
@ -1050,6 +1075,42 @@ def is_older_than_days(time_message, max_days):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def is_younger_than_time(time_message, min_time):
|
||||||
|
"""Return true if a message is newer than the specified time,
|
||||||
|
false otherwise.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
time_message -- the delivery date of the message measured in seconds
|
||||||
|
since the epoch
|
||||||
|
min_time -- minimum time allowed for message
|
||||||
|
|
||||||
|
"""
|
||||||
|
days_old = (min_time - time_message) / 24 / 60 / 60
|
||||||
|
if time_message >= min_time:
|
||||||
|
vprint("message is %.2f days newer than the specified date" % days_old)
|
||||||
|
return True
|
||||||
|
vprint("message is %.2f days older than the specified date" % \
|
||||||
|
abs(days_old))
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_younger_than_days(time_message, min_days):
|
||||||
|
"""Return true if a message is newer than the specified number of days,
|
||||||
|
false otherwise.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
time_message -- the delivery date of the message measured in seconds
|
||||||
|
since the epoch
|
||||||
|
min_days -- minimum number of days before message is considered old
|
||||||
|
"""
|
||||||
|
time_now = time.time()
|
||||||
|
secs_old_min = (min_days * 24 * 60 * 60)
|
||||||
|
days_old = (time_now - time_message) / 24 / 60 / 60
|
||||||
|
vprint("message is %.2f days old" % days_old)
|
||||||
|
if ((time_message + secs_old_min) >= time_now):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def build_imap_filter():
|
def build_imap_filter():
|
||||||
"""Return an imap filter string"""
|
"""Return an imap filter string"""
|
||||||
|
|
||||||
|
|
@ -1057,12 +1118,21 @@ def build_imap_filter():
|
||||||
if options.date_old_max == None:
|
if options.date_old_max == None:
|
||||||
time_now = time.time()
|
time_now = time.time()
|
||||||
secs_old_max = (options.days_old_max * 24 * 60 * 60)
|
secs_old_max = (options.days_old_max * 24 * 60 * 60)
|
||||||
time_old = time.gmtime(time_now - secs_old_max)
|
time_old = time.localtime(time_now - secs_old_max)
|
||||||
else:
|
else:
|
||||||
time_old = time.gmtime(options.date_old_max)
|
time_old = time.localtime(options.date_old_max)
|
||||||
time_str = time.strftime('%d-%b-%Y', time_old)
|
time_str = time.strftime('%d-%b-%Y', time_old)
|
||||||
imap_filter.append("BEFORE %s" % time_str)
|
imap_filter.append("BEFORE %s" % time_str)
|
||||||
|
|
||||||
|
if options.date_old_min == None:
|
||||||
|
time_now = time.time()
|
||||||
|
secs_old_min = (options.days_old_min * 24 * 60 * 60)
|
||||||
|
time_old = time.localtime(time_now - secs_old_min)
|
||||||
|
else:
|
||||||
|
time_old = time.localtime(options.date_old_min)
|
||||||
|
time_str = time.strftime('%d-%b-%Y', time_old)
|
||||||
|
imap_filter.append("SINCE %s" % time_str)
|
||||||
|
|
||||||
if not options.include_flagged:
|
if not options.include_flagged:
|
||||||
imap_filter.append("UNFLAGGED")
|
imap_filter.append("UNFLAGGED")
|
||||||
if options.min_size:
|
if options.min_size:
|
||||||
|
|
|
||||||
|
|
@ -544,6 +544,47 @@ class TestIsTooOld(unittest.TestCase):
|
||||||
assert not archivemail.is_older_than_days(time_message=time_msg,
|
assert not archivemail.is_older_than_days(time_message=time_msg,
|
||||||
max_days=1)
|
max_days=1)
|
||||||
|
|
||||||
|
########## archivemail.is_younger_than_days() unit testing #################
|
||||||
|
|
||||||
|
class TestIsTooYoung(unittest.TestCase):
|
||||||
|
def testVeryNotYoung(self):
|
||||||
|
"""with min_days=360, should be false for these dates > 1 year"""
|
||||||
|
ctime = time.time()
|
||||||
|
for years in range(1, 10):
|
||||||
|
time_msg = ctime - (years * 365 * 24 * 60 * 60)
|
||||||
|
assert not archivemail.is_younger_than_days(time_message=time_msg,
|
||||||
|
min_days=360)
|
||||||
|
|
||||||
|
def testNotYoung(self):
|
||||||
|
"""with min_days=14, should be false for these dates > 14 days"""
|
||||||
|
ctime = time.time()
|
||||||
|
for days in range(14, 360):
|
||||||
|
time_msg = ctime - (days * 24 * 60 * 60)
|
||||||
|
assert not archivemail.is_younger_than_days(time_message=time_msg,
|
||||||
|
min_days=14)
|
||||||
|
|
||||||
|
def testJustNotYoung(self):
|
||||||
|
"""with min_days=1, should be false for these dates >= 1 day"""
|
||||||
|
ctime = time.time()
|
||||||
|
for minutes in range(0, 61):
|
||||||
|
time_msg = ctime - (25 * 60 * 60) + (minutes * 60)
|
||||||
|
assert not archivemail.is_younger_than_days(time_message=time_msg,
|
||||||
|
min_days=1)
|
||||||
|
|
||||||
|
def testYoung(self):
|
||||||
|
"""with min_days=9, should be true for these dates < 9 days"""
|
||||||
|
for days in range(0, 9):
|
||||||
|
time_msg = time.time() - (days * 24 * 60 * 60)
|
||||||
|
assert archivemail.is_younger_than_days(time_message=time_msg,
|
||||||
|
min_days=9)
|
||||||
|
|
||||||
|
def testJustYoung(self):
|
||||||
|
"""with min_days=1, should be true for these hours <= 1 day"""
|
||||||
|
for minutes in range(0, 60):
|
||||||
|
time_msg = time.time() - (23 * 60 * 60) - (minutes * 60)
|
||||||
|
assert archivemail.is_younger_than_days(time_message=time_msg,
|
||||||
|
min_days=1)
|
||||||
|
|
||||||
########## archivemail.parse_imap_url() unit testing #################
|
########## archivemail.parse_imap_url() unit testing #################
|
||||||
|
|
||||||
class TestParseIMAPUrl(unittest.TestCase):
|
class TestParseIMAPUrl(unittest.TestCase):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue