split by year received

This commit is contained in:
Antonio J. Delgado 2025-03-28 10:20:14 +02:00
parent 8d3ccc573a
commit 79df8cbaa3

View file

@ -64,19 +64,6 @@ class BackupImap:
) )
self._process_mailbox(self.config['mailbox']) self._process_mailbox(self.config['mailbox'])
def _better_imap_search(self, charset='UTF-8', criterion='UNDELETED'):
current = time.gmtime()
result = {
"result": b"NO",
"data": b""
}
for year in range(current.tm_year-10, current.tm_year+1):
search_response, search_data = self.imap.search(charset, criterion, f'BEFORE={year}')
if search_response == 'OK':
result['result'] = 'OK'
result[search_data] += result[search_data]
return result
def _process_mailbox(self, mailbox): def _process_mailbox(self, mailbox):
self._log.debug("Searching for all mailboxes in mailbox '%s'...", mailbox) self._log.debug("Searching for all mailboxes in mailbox '%s'...", mailbox)
list_response, list_data = self.imap.list(f"\"{mailbox}\"", '*') list_response, list_data = self.imap.list(f"\"{mailbox}\"", '*')
@ -112,81 +99,68 @@ class BackupImap:
os.mkdir(os.path.dirname(mailbox_path)) os.mkdir(os.path.dirname(mailbox_path))
if not os.path.exists(mailbox_path): if not os.path.exists(mailbox_path):
os.mkdir(mailbox_path) os.mkdir(mailbox_path)
search_result = self._better_imap_search('UTF-8', 'UNDELETED') current = time.gmtime()
if search_result['result'] == 'OK': for year in range(current.tm_year-10, current.tm_year+1):
all_msgs_uids = search_result['data'][0].split() search_response, search_data = self.imap.search('UTF-8', 'UNDELETED', f'BEFORE={year}')
self._log.debug( if search_response == 'OK':
"Found %s messages", all_msgs_uids = search_data[0].split()
len(all_msgs_uids)
)
msg_counter = 1
for message_uid in all_msgs_uids:
self._log.debug( self._log.debug(
"Processing message %s (%s/%s)", "Found %s messages",
message_uid.decode(),
msg_counter,
len(all_msgs_uids) len(all_msgs_uids)
) )
msg_counter += 1 msg_counter = 1
fetch_response, fetch_data = self.imap.fetch(message_uid, "(RFC822)") for message_uid in all_msgs_uids:
self._log.debug(fetch_data) self._log.debug(
if fetch_response == 'OK': "Processing message %s (%s/%s)",
store_result, unseen_data = self.imap.store(message_uid, '-FLAGS', '\\Seen') message_uid.decode(),
if store_result != 'OK': msg_counter,
self._log.error( len(all_msgs_uids)
"Error marking as unseen the message '%s'. %s",
message_uid,
unseen_data
)
sys.exit(6)
subject = f'__no_subject__{message_uid}'
data = fetch_data[0][1]
subjects = self._get_mail_header('Subject', data)
if len(subjects) > 0:
subject = subjects[-1].replace(
os.path.sep,
'_'
).replace(
'\r',
'_'
).replace(
'\n',
'_'
).replace(
':',
'_'
)
message_path = os.path.join(
mailbox_path,
subject
) )
original_subject = subject msg_counter += 1
message_id = self._get_mail_header('Message-ID', data)[-1] fetch_response, fetch_data = self.imap.fetch(message_uid, "(RFC822)")
if not self._backedup_message(message_id, mailbox): self._log.debug(fetch_data)
counter = 1 if fetch_response == 'OK':
while os.path.exists(message_path): store_result, unseen_data = self.imap.store(message_uid, '-FLAGS', '\\Seen')
subject = f"{original_subject}_{counter}" if store_result != 'OK':
message_path = os.path.join( self._log.error(
mailbox_path, "Error marking as unseen the message '%s'. %s",
subject message_uid,
unseen_data
) )
counter += 1 sys.exit(6)
try: subject = f'__no_subject__{message_uid}'
with open(message_path, 'wb') as file_pointer: data = fetch_data[0][1]
file_pointer.write(data) subjects = self._get_mail_header('Subject', data)
self.data['backedup_messages'].append( if len(subjects) > 0:
{ subject = subjects[-1].replace(
"message_id": message_id, os.path.sep,
"mailbox": mailbox '_'
} ).replace(
'\r',
'_'
).replace(
'\n',
'_'
).replace(
':',
'_'
) )
self._save_cached_data(self.data) message_path = os.path.join(
except OSError as error: mailbox_path,
if error.errno == 36: # File name too long subject
)
original_subject = subject
message_id = self._get_mail_header('Message-ID', data)[-1]
if not self._backedup_message(message_id, mailbox):
counter = 1
while os.path.exists(message_path):
subject = f"{original_subject}_{counter}"
message_path = os.path.join( message_path = os.path.join(
mailbox_path, mailbox_path,
f"message_uid_{message_uid.decode()}" subject
) )
counter += 1
try:
with open(message_path, 'wb') as file_pointer: with open(message_path, 'wb') as file_pointer:
file_pointer.write(data) file_pointer.write(data)
self.data['backedup_messages'].append( self.data['backedup_messages'].append(
@ -196,16 +170,31 @@ class BackupImap:
} }
) )
self._save_cached_data(self.data) self._save_cached_data(self.data)
else: except OSError as error:
self._log.error( if error.errno == 36: # File name too long
"Error writing email '%s'. %s", message_path = os.path.join(
message_path, mailbox_path,
error f"message_uid_{message_uid.decode()}"
) )
else: with open(message_path, 'wb') as file_pointer:
self._log.debug( file_pointer.write(data)
"Skipping already backed up message" self.data['backedup_messages'].append(
) {
"message_id": message_id,
"mailbox": mailbox
}
)
self._save_cached_data(self.data)
else:
self._log.error(
"Error writing email '%s'. %s",
message_path,
error
)
else:
self._log.debug(
"Skipping already backed up message"
)
def _backedup_message(self, message_id, mailbox): def _backedup_message(self, message_id, mailbox):
for message in self.data['backedup_messages']: for message in self.data['backedup_messages']: