Created
April 7, 2017 18:38
-
-
Save tehlers/8b49ccbbd5c461217bed30cbea429161 to your computer and use it in GitHub Desktop.
Delete old mails from a directory with folders in the maildir format.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
# -*- coding: utf-8 -*- | |
"""Delete old mails from a directory with folders in the maildir format. | |
This script is intended to be used on a directory that contains mails managed by offlineimap. | |
Since offlineimap only provides the means to download mails of a maximal age but doesn't remove | |
them once they have been downloaded and became outdated, this script fills the void and removes | |
any mail exceeding a given age. | |
Use '--help' to get a detailed explanation of the available options. | |
The non standard module 'dateutil' is used to parse the mail headers. You have to install | |
it, if you haven't done so already. | |
""" | |
import argparse | |
from datetime import datetime, timedelta | |
import dateutil.parser | |
import logging | |
import mailbox | |
import os | |
def main(): | |
"""Delete mails according to the given arguments""" | |
args = parse_args() | |
configure_logging( args.verbose, args.quiet ) | |
for mail_folder in os.listdir( args.maildirs ): | |
path = os.path.join( args.maildirs, mail_folder ) | |
logging.debug( "Checking messages in %s" % path ) | |
maildir = mailbox.Maildir( path ) | |
keys_of_old_mails = [] | |
try: | |
for mail_key in maildir.iterkeys(): | |
mail = maildir[ mail_key ] | |
date = dateutil.parser.parse( mail["date"] ) | |
oldest_date = datetime.now( date.tzinfo ) - timedelta( days = args.max_age ) | |
if ( date < oldest_date ): | |
log_message = "Marking '%s' received on '%s' for deletion" % ( mail["subject"], mail["date"] ) | |
keys_of_old_mails.append( mail_key ) | |
else: | |
log_message = "Keeping '%s' received on '%s'" % ( mail["subject"], mail["date"] ) | |
logging.debug( log_message ) | |
if ( len( keys_of_old_mails ) ): | |
logging.info( "Deleting %d mails from %s" % ( len( keys_of_old_mails ), mail_folder ) ) | |
if ( not args.dry_run ): | |
maildir.lock() | |
try: | |
for mail_key in keys_of_old_mails: | |
maildir.remove( mail_key ) | |
finally: | |
maildir.flush() | |
maildir.unlock() | |
except ( FileNotFoundError, NotADirectoryError ): | |
logging.warn( "'%s' is not a valid maildir" % path ) | |
except ( PermissionError ): | |
logging.warn( "'%s' is not readable" % path ) | |
def parse_args(): | |
"""Evaluate the arguments that have been passed on the command line.""" | |
parser = argparse.ArgumentParser( description = "Delete old mails from a directory with folders in the maildir format", formatter_class = argparse.RawDescriptionHelpFormatter ) | |
parser.add_argument( "--dry-run", help = "run without deletion of mails", action = "store_true" ) | |
parser.add_argument( "--max-age", type = int, help = "maximum age of mails before deletion in days (default: %(default)s)", default = 365 ) | |
parser.add_argument( "--maildirs", help = "directory containing maildir folders (default: %(default)s)", default = os.path.join( os.path.expanduser( "~" ), "mail" ) ) | |
parser.add_argument( "--quiet", help = "don't print any status information", action = "store_true" ) | |
parser.add_argument( "--verbose", help = "enable additional debug output", action = "store_true" ) | |
return parser.parse_args() | |
def configure_logging( verbose, quiet ): | |
"""Set the log level according to the given preferences. | |
'--quiet' takes precedence over '--verbose'. | |
""" | |
stdout_handler = logging.StreamHandler() | |
stdout_handler.setFormatter( logging.Formatter( "%(message)s" ) ) | |
if ( quiet ): | |
level = logging.WARN | |
elif ( verbose ): | |
level = logging.DEBUG | |
else: | |
level = logging.INFO | |
stdout_handler.setLevel( level ) | |
logging.getLogger().setLevel( level ) | |
logging.getLogger().addHandler( stdout_handler ) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment