将交换文件夹擦除到指定大小
wipe exchange folder to specified size
我正在尝试删除 Exchange 文件夹中的邮件,直到文件夹大小达到以字节为单位的指定值。
这是我的示例代码:
def get_foldersize(folder):
if folder.__class__ != folders.Messages:
return -1
return sum(folder.all().values_list('size', flat=True))
def wipe_by_size(folder=account.inbox, size='4.8gb', result_as_str=True):
"""
Delete all old messages in specified exchange folder to specified size
size may setted like str ("4,9gb", "500.5 Mb", "1024kB") or like int (means size setted in bytes)
if result_as_str == True, func returns a stats delete msg,
otherwise tuple (deleted_files_count, deleted_bytes, before_files_count, before_bytes, after_files_count, after_bytes)
"""
if folder.__class__ != folders.Messages:
raise ValueError("Param 'folder' not a exchange-server folder object!")
m = {
'gb': 1024 ** 3,
'mb': 1024 ** 2,
'kb': 1024,
}
size_bytes = None
if isinstance(size, str):
if ',' in size:
size = size.replace(',', '.')
for k, v in m.items():
if k in size.lower():
size = size.split(k)[0].strip()
try:
size_float = float(size)
size_bytes = round(size_float * v)
except ValueError:
raise ValueError(f"Incorrect format of param 'size', recieve '{size_str}'")
break
else:
raise ValueError(
f"Incorrect format of 'size' param, '{size_str}' must contains int or float number and something from '{list(m.keys())}'")
elif isinstance(size, (int, float,)):
size_bytes = int(size)
else:
raise ValueError(
'Parameter "size" can be a str (example:"4,9gb", "500.5 Mb", "1024kB") or int folder size in bytes')
if get_foldersize(folder) < size_bytes:
return
before = folder.total_count
before_bytes = get_foldersize(folder)
while get_foldersize(folder) > size_bytes:
msg = folder.all().order_by('datetime_received')[0]
try:
# print(msg.subject, msg.sender)
msg.delete()
except Exception as e:
if msg is not None:
print(f"wipe_by_size: Can't delete {msg.sender}({msg.subject})")
else:
print("wipe_by_size: msg = None")
after = folder.total_count
deleted = before - after
after_bytes = get_foldersize(folder)
deleted_bytes = before_bytes - after_bytes
if result_as_str:
return f"""Wiped {deleted} file(s), freed {'{0:12,d}'.format(
deleted_bytes)} bytes. Before: {before} files, {'{0:12,d}'.format(
before_bytes)} bytes. After: {after} files, {'{0:12,d}'.format(after_bytes)} bytes"""
return deleted, deleted_bytes, before, before_bytes, after, after_bytes
delete_msg = wipe_by_size(folder=account.sent, size='4,8gb')
deleted, deleted_bytes, before, before_bytes, after, after_bytes = wipe_by_size(folder=account.sent, size='4,8gb')
该功能有效但非常缓慢 -
慢慢地,因为 while 循环的每次迭代都会调用 get_foldersize()
。
我建议我需要以相反的顺序获取文件夹中的所有消息(就像现在一样),存储每条消息的大小,然后计算我需要一次性擦除和删除多少条消息和哪些消息。我认为那会更快。但我不知道如何(以及是否可能?)获取消息大小。
如您所见,邮件大小包含在 size
字段中。因此,您可以计算一次文件夹大小,然后读取 msg.size
并循环递减文件夹总大小。最后,通过仅获取文件夹中每条消息的 size
字段来减少网络流量:
class FolderSize(ExtendedProperty):
property_tag = 0x0e08
property_type = 'Integer'
Folder.register('size', FolderSize)
folder = account.inbox
folder_size = folder.size
max_size = 123456789 # Bytes
for msg in folder.all().only('size'):
if folder_size <= max_size:
break
msg.delete()
folder_size -= msg.size
我正在尝试删除 Exchange 文件夹中的邮件,直到文件夹大小达到以字节为单位的指定值。
这是我的示例代码:
def get_foldersize(folder):
if folder.__class__ != folders.Messages:
return -1
return sum(folder.all().values_list('size', flat=True))
def wipe_by_size(folder=account.inbox, size='4.8gb', result_as_str=True):
"""
Delete all old messages in specified exchange folder to specified size
size may setted like str ("4,9gb", "500.5 Mb", "1024kB") or like int (means size setted in bytes)
if result_as_str == True, func returns a stats delete msg,
otherwise tuple (deleted_files_count, deleted_bytes, before_files_count, before_bytes, after_files_count, after_bytes)
"""
if folder.__class__ != folders.Messages:
raise ValueError("Param 'folder' not a exchange-server folder object!")
m = {
'gb': 1024 ** 3,
'mb': 1024 ** 2,
'kb': 1024,
}
size_bytes = None
if isinstance(size, str):
if ',' in size:
size = size.replace(',', '.')
for k, v in m.items():
if k in size.lower():
size = size.split(k)[0].strip()
try:
size_float = float(size)
size_bytes = round(size_float * v)
except ValueError:
raise ValueError(f"Incorrect format of param 'size', recieve '{size_str}'")
break
else:
raise ValueError(
f"Incorrect format of 'size' param, '{size_str}' must contains int or float number and something from '{list(m.keys())}'")
elif isinstance(size, (int, float,)):
size_bytes = int(size)
else:
raise ValueError(
'Parameter "size" can be a str (example:"4,9gb", "500.5 Mb", "1024kB") or int folder size in bytes')
if get_foldersize(folder) < size_bytes:
return
before = folder.total_count
before_bytes = get_foldersize(folder)
while get_foldersize(folder) > size_bytes:
msg = folder.all().order_by('datetime_received')[0]
try:
# print(msg.subject, msg.sender)
msg.delete()
except Exception as e:
if msg is not None:
print(f"wipe_by_size: Can't delete {msg.sender}({msg.subject})")
else:
print("wipe_by_size: msg = None")
after = folder.total_count
deleted = before - after
after_bytes = get_foldersize(folder)
deleted_bytes = before_bytes - after_bytes
if result_as_str:
return f"""Wiped {deleted} file(s), freed {'{0:12,d}'.format(
deleted_bytes)} bytes. Before: {before} files, {'{0:12,d}'.format(
before_bytes)} bytes. After: {after} files, {'{0:12,d}'.format(after_bytes)} bytes"""
return deleted, deleted_bytes, before, before_bytes, after, after_bytes
delete_msg = wipe_by_size(folder=account.sent, size='4,8gb')
deleted, deleted_bytes, before, before_bytes, after, after_bytes = wipe_by_size(folder=account.sent, size='4,8gb')
该功能有效但非常缓慢 -
慢慢地,因为 while 循环的每次迭代都会调用 get_foldersize()
。
我建议我需要以相反的顺序获取文件夹中的所有消息(就像现在一样),存储每条消息的大小,然后计算我需要一次性擦除和删除多少条消息和哪些消息。我认为那会更快。但我不知道如何(以及是否可能?)获取消息大小。
如您所见,邮件大小包含在 size
字段中。因此,您可以计算一次文件夹大小,然后读取 msg.size
并循环递减文件夹总大小。最后,通过仅获取文件夹中每条消息的 size
字段来减少网络流量:
class FolderSize(ExtendedProperty):
property_tag = 0x0e08
property_type = 'Integer'
Folder.register('size', FolderSize)
folder = account.inbox
folder_size = folder.size
max_size = 123456789 # Bytes
for msg in folder.all().only('size'):
if folder_size <= max_size:
break
msg.delete()
folder_size -= msg.size