From aa846c3478fed5cee14ce8e7b68775f2a9a22dc1 Mon Sep 17 00:00:00 2001 From: missytake Date: Wed, 3 Jun 2026 10:42:28 +0200 Subject: [PATCH] fix: expire empty directories (#994) * fix: respect --dry when expiring empty directories Co-authored-by: j4n --- chatmaild/src/chatmaild/expire.py | 10 +++++++ chatmaild/src/chatmaild/tests/test_expire.py | 28 ++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/chatmaild/src/chatmaild/expire.py b/chatmaild/src/chatmaild/expire.py index ef8e2328..783f63f9 100644 --- a/chatmaild/src/chatmaild/expire.py +++ b/chatmaild/src/chatmaild/expire.py @@ -168,6 +168,16 @@ class Expiry: if mbox.last_login and mbox.last_login < cutoff_without_login: self.remove_mailbox(mbox.basedir) return + elif mbox.last_login is None: + try: + if not self.dry: + os.rmdir(mbox.basedir) + self.del_mboxes += 1 + except OSError: + print_info( + f"Skipped deleting {mbox.basedir}, doesn't have last_login but isn't empty" + ) + return mboxname = os.path.basename(mbox.basedir) if self.verbose: diff --git a/chatmaild/src/chatmaild/tests/test_expire.py b/chatmaild/src/chatmaild/tests/test_expire.py index 5407c33d..c6ad7f1d 100644 --- a/chatmaild/src/chatmaild/tests/test_expire.py +++ b/chatmaild/src/chatmaild/tests/test_expire.py @@ -1,6 +1,7 @@ import itertools import os import random +import shutil import time from datetime import datetime from fnmatch import fnmatch @@ -9,6 +10,7 @@ from pathlib import Path import pytest from chatmaild.expire import ( + Expiry, FileEntry, MailboxStat, expire_to_target, @@ -104,6 +106,32 @@ def test_stats_mailbox(mbox1): assert mbox3.last_login is None +def test_mbox_without_password(mbox1, example_config, capsys): + password = Path(mbox1.basedir).joinpath("password") + os.remove(password) + mbox_rescan = MailboxStat(mbox1.basedir) + assert mbox_rescan.last_login is None + + exp = Expiry( + example_config, dry=False, now=datetime.now().timestamp(), verbose=False + ) + exp.process_mailbox_stat(mbox_rescan) + out, err = capsys.readouterr() + assert "doesn't have last_login but isn't empty" in err + assert os.path.isdir(mbox_rescan.basedir) + + for entry in os.scandir(mbox_rescan.basedir): + if os.path.isdir(entry): + shutil.rmtree(entry) + else: + os.remove(entry) + + exp.process_mailbox_stat(mbox_rescan) + out, err = capsys.readouterr() + assert "doesn't have last_login but isn't empty" not in err + assert not os.path.isdir(mbox_rescan.basedir) + + def test_report_no_mailboxes(example_config): args = (str(example_config._inipath),) report_main(args)