@@ -22,11 +22,30 @@ def iter_mailboxes(basedir, maxnum):
2222 print_info (f"no mailboxes found at: { basedir } " )
2323 return
2424
25- for name in os . listdir (basedir )[:maxnum ]:
25+ for name in os_listdir_if_exists (basedir )[:maxnum ]:
2626 if "@" in name :
2727 yield MailboxStat (basedir + "/" + name )
2828
2929
30+ def get_file_entry (path ):
31+ """return a FileEntry or None if the path does not exist or is not a regular file."""
32+ try :
33+ st = os .stat (path )
34+ except FileNotFoundError :
35+ return None
36+ if not S_ISREG (st .st_mode ):
37+ return None
38+ return FileEntry (path , st .st_mtime , st .st_size )
39+
40+
41+ def os_listdir_if_exists (path ):
42+ """return a list of names obtained from os.listdir or an empty list if the path does not exist."""
43+ try :
44+ return os .listdir (path )
45+ except FileNotFoundError :
46+ return []
47+
48+
3049class MailboxStat :
3150 last_login = None
3251
@@ -40,19 +59,23 @@ def __init__(self, basedir):
4059
4160 # scan all relevant files (without recursion)
4261 old_cwd = os .getcwd ()
43- os .chdir (self .basedir )
44- for name in os .listdir ("." ):
62+ try :
63+ os .chdir (self .basedir )
64+ except FileNotFoundError :
65+ return
66+ for name in os_listdir_if_exists ("." ):
4567 if name in ("cur" , "new" , "tmp" ):
46- for msg_name in os .listdir (name ):
47- relpath = name + "/" + msg_name
48- st = os .stat (relpath )
49- self .messages .append (FileEntry (relpath , st .st_mtime , st .st_size ))
68+ for msg_name in os_listdir_if_exists (name ):
69+ entry = get_file_entry (f"{ name } /{ msg_name } " )
70+ if entry is not None :
71+ self .messages .append (entry )
72+
5073 else :
51- st = os . stat (name )
52- if S_ISREG ( st . st_mode ) :
53- self .extrafiles .append (FileEntry ( name , st . st_mtime , st . st_size ) )
74+ entry = get_file_entry (name )
75+ if entry is not None :
76+ self .extrafiles .append (entry )
5477 if name == "password" :
55- self .last_login = st . st_mtime
78+ self .last_login = entry . mtime
5679 self .extrafiles .sort (key = lambda x : - x .size )
5780 os .chdir (old_cwd )
5881
@@ -80,9 +103,13 @@ def remove_mailbox(self, mboxdir):
80103 shutil .rmtree (mboxdir )
81104 self .del_mboxes += 1
82105
83- def remove_file (self , path ):
106+ def remove_file (self , path , mtime = None ):
84107 if self .verbose :
85- print_info (f"removing { path } " )
108+ if mtime is not None :
109+ date = datetime .fromtimestamp (mtime ).strftime ("%b %d" )
110+ print_info (f"removing { date } { path } " )
111+ else :
112+ print_info (f"removing { path } " )
86113 if not self .dry :
87114 try :
88115 os .unlink (path )
@@ -104,18 +131,27 @@ def process_mailbox_stat(self, mbox):
104131 return
105132
106133 # all to-be-removed files are relative to the mailbox basedir
107- os .chdir (mbox .basedir )
134+ try :
135+ os .chdir (mbox .basedir )
136+ except FileNotFoundError :
137+ print_info (f"mailbox not found/vanished { mbox .basedir } " )
138+ return
139+
108140 mboxname = os .path .basename (mbox .basedir )
109141 if self .verbose :
110- print_info (f"checking for mailbox messages in: { mboxname } " )
142+ date = datetime .fromtimestamp (mbox .last_login ) if mbox .last_login else None
143+ if date :
144+ print_info (f"checking mailbox { date .strftime ('%b %d' )} { mboxname } " )
145+ else :
146+ print_info (f"checking mailbox (no last_login) { mboxname } " )
111147 self .all_files += len (mbox .messages )
112148 for message in mbox .messages :
113149 if message .mtime < cutoff_mails :
114- self .remove_file (message .relpath )
150+ self .remove_file (message .relpath , mtime = message . mtime )
115151 elif message .size > 200000 and message .mtime < cutoff_large_mails :
116152 # we only remove noticed large files (not unnoticed ones in new/)
117153 if message .relpath .startswith ("cur/" ):
118- self .remove_file (message .relpath )
154+ self .remove_file (message .relpath , mtime = message . mtime )
119155 else :
120156 continue
121157 changed = True
0 commit comments