no reporting by default, and adding a summary line

This commit is contained in:
holger krekel
2025-09-15 13:41:16 +02:00
parent 10e53d17e8
commit c9f80bffd8
2 changed files with 34 additions and 6 deletions

View File

@@ -6,6 +6,7 @@ Expire old messages and addresses.
import os import os
import shutil import shutil
import sys import sys
import time
from argparse import ArgumentParser from argparse import ArgumentParser
from datetime import datetime from datetime import datetime
from stat import S_ISREG from stat import S_ISREG
@@ -92,24 +93,34 @@ def print_info(msg):
class Expiry: class Expiry:
def __init__(self, config, stats, dry, now): def __init__(self, config, stats, dry, now, verbose):
self.config = config self.config = config
self.stats = stats self.stats = stats
self.dry = dry self.dry = dry
self.now = now self.now = now
self.verbose = verbose
self.del_mboxes = 0
self.all_mboxes = 0
self.del_files = 0
self.all_files = 0
self.start = time.time()
def remove_mailbox(self, mboxdir): def remove_mailbox(self, mboxdir):
print_info(f"removing {mboxdir}") if self.verbose:
print_info(f"removing {mboxdir}")
if not self.dry: if not self.dry:
shutil.rmtree(mboxdir) shutil.rmtree(mboxdir)
self.del_mboxes += 1
def remove_file(self, path): def remove_file(self, path):
print_info(f"removing {path}") if self.verbose:
print_info(f"removing {path}")
if not self.dry: if not self.dry:
try: try:
os.unlink(path) os.unlink(path)
except FileNotFoundError: except FileNotFoundError:
print_info(f"file not found/vanished {path}") print_info(f"file not found/vanished {path}")
self.del_files += 1
def process_mailbox_stat(self, mbox): def process_mailbox_stat(self, mbox):
cutoff_without_login = ( cutoff_without_login = (
@@ -118,12 +129,15 @@ class Expiry:
cutoff_mails = self.now - int(self.config.delete_mails_after) * 86400 cutoff_mails = self.now - int(self.config.delete_mails_after) * 86400
cutoff_large_mails = self.now - int(self.config.delete_large_after) * 86400 cutoff_large_mails = self.now - int(self.config.delete_large_after) * 86400
self.all_mboxes += 1
changed = False changed = False
if mbox.last_login and mbox.last_login < cutoff_without_login: if mbox.last_login and mbox.last_login < cutoff_without_login:
self.remove_mailbox(mbox.basedir) self.remove_mailbox(mbox.basedir)
return return
# all to-be-removed files are relative to the mailbox basedir
os.chdir(mbox.basedir) os.chdir(mbox.basedir)
self.all_files += len(mbox.messages)
for message in mbox.messages: for message in mbox.messages:
if message.mtime < cutoff_mails: if message.mtime < cutoff_mails:
self.remove_file(message.relpath) self.remove_file(message.relpath)
@@ -135,6 +149,13 @@ class Expiry:
if changed: if changed:
self.remove_file("maildirsize") self.remove_file("maildirsize")
def get_summary(self):
return (
f"Removed {self.del_mboxes} out of {self.all_mboxes} mailboxes "
f"and {self.del_files} out of {self.all_files} files "
f"in {time.time()-self.start:2.2f} seconds"
)
def main(args): def main(args):
"""Expire mailboxes and messages according to chatmail config""" """Expire mailboxes and messages according to chatmail config"""
@@ -155,6 +176,12 @@ def main(args):
action="store", action="store",
help="maximum number of mailbxoes to iterate on", help="maximum number of mailbxoes to iterate on",
) )
parser.add_argument(
"-v",
dest="verbose",
action="store_true",
help="print out removed files and mailboxes",
)
parser.add_argument( parser.add_argument(
"--remove", "--remove",
@@ -170,9 +197,10 @@ def main(args):
now = now - 86400 * int(args.days) now = now - 86400 * int(args.days)
maxnum = int(args.maxnum) if args.maxnum else None maxnum = int(args.maxnum) if args.maxnum else None
stats = Stats(args.mailboxes_dir, maxnum=maxnum) stats = Stats(os.path.abspath(args.mailboxes_dir), maxnum=maxnum)
exp = Expiry(config, stats, dry=not args.remove, now=now) exp = Expiry(config, stats, dry=not args.remove, now=now, verbose=args.verbose)
stats.iter_mailboxes(exp.process_mailbox_stat) stats.iter_mailboxes(exp.process_mailbox_stat)
print(exp.get_summary())
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -102,7 +102,7 @@ def test_expiry_cli_old_files(capsys, example_config, mbox1):
create_new_messages(mbox1.basedir, ["cur/shouldstay"], size=1000 * 300, days=1) create_new_messages(mbox1.basedir, ["cur/shouldstay"], size=1000 * 300, days=1)
args = example_config._inipath, Path(mbox1.basedir).parent, "--remove" args = example_config._inipath, Path(mbox1.basedir).parent, "--remove", "-v"
expiry_main(args) expiry_main(args)
out, err = capsys.readouterr() out, err = capsys.readouterr()