Small bug fixes in attachment handling
This commit is contained in:
parent
7ef2cfc299
commit
59da191fa3
@ -7,6 +7,7 @@ import hashlib
|
|||||||
from email.utils import parsedate_to_datetime
|
from email.utils import parsedate_to_datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
from config import get_config
|
from config import get_config
|
||||||
from stats import add_statistic
|
from stats import add_statistic
|
||||||
@ -53,6 +54,26 @@ def should_extract_attachment(part):
|
|||||||
|
|
||||||
return file_ext in ATTACHMENT_WHITELIST and file_size < MAX_ATTACHMENT_SIZE and file_size > MIN_ATTACHMENT_SIZE
|
return file_ext in ATTACHMENT_WHITELIST and file_size < MAX_ATTACHMENT_SIZE and file_size > MIN_ATTACHMENT_SIZE
|
||||||
|
|
||||||
|
# Helper function to sanitize filenames
|
||||||
|
def make_filename_safe(filename):
|
||||||
|
"""
|
||||||
|
Sanitizes a filename by:
|
||||||
|
- Removing any "file://" prefix.
|
||||||
|
- Replacing characters not allowed on most systems (< > : " / \ | ? *) with an underscore.
|
||||||
|
- Stripping leading/trailing whitespace.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): The original filename.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: A safe filename.
|
||||||
|
"""
|
||||||
|
# Remove any URL scheme if present
|
||||||
|
filename = filename.replace("file://", "")
|
||||||
|
# Replace illegal characters with underscore
|
||||||
|
safe_filename = re.sub(r'[<>:"/\\|?*]', '_', filename)
|
||||||
|
return safe_filename.strip()
|
||||||
|
|
||||||
def save_attachment(part, email_date_str):
|
def save_attachment(part, email_date_str):
|
||||||
"""
|
"""
|
||||||
Save an extracted attachment to disk in a month-based folder (e.g., "2023_10")
|
Save an extracted attachment to disk in a month-based folder (e.g., "2023_10")
|
||||||
@ -70,8 +91,9 @@ def save_attachment(part, email_date_str):
|
|||||||
if not filename:
|
if not filename:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Normalize the filename to remove trailing query strings etc.
|
# Normalize the filename (if you have a normalize_filename function, otherwise, use the safe version)
|
||||||
filename = normalize_filename(filename)
|
# Here we simply sanitize the filename.
|
||||||
|
filename = make_filename_safe(filename)
|
||||||
|
|
||||||
# Strip extra quotes from the date string, if present.
|
# Strip extra quotes from the date string, if present.
|
||||||
date_str = email_date_str.strip('"')
|
date_str = email_date_str.strip('"')
|
||||||
@ -81,7 +103,6 @@ def save_attachment(part, email_date_str):
|
|||||||
email_date = parsedate_to_datetime(date_str)
|
email_date = parsedate_to_datetime(date_str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
try:
|
try:
|
||||||
# Fallback: try using datetime.strptime with the appropriate format.
|
|
||||||
email_date = datetime.strptime(date_str, "%d-%b-%Y %H:%M:%S %z")
|
email_date = datetime.strptime(date_str, "%d-%b-%Y %H:%M:%S %z")
|
||||||
except Exception as e2:
|
except Exception as e2:
|
||||||
print(f"Date parsing failed for: {date_str}")
|
print(f"Date parsing failed for: {date_str}")
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
},
|
},
|
||||||
"archive_folder": "Archive",
|
"archive_folder": "Archive",
|
||||||
"folder_prefix": "INBOX.",
|
"folder_prefix": "INBOX.",
|
||||||
"root_folder": "[Gmail]/All Mail",
|
"root_folder": "[Gmail]/Alle Nachrichten",
|
||||||
"labels_as_flagged": [
|
"labels_as_flagged": [
|
||||||
"Important",
|
"Important",
|
||||||
"[Gmail]/Important",
|
"[Gmail]/Important",
|
||||||
|
|||||||
@ -10,6 +10,9 @@ from dotenv import load_dotenv
|
|||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import ssl # For _ssl.SSLError
|
||||||
|
|
||||||
from config import logger
|
from config import logger
|
||||||
from config import get_config
|
from config import get_config
|
||||||
|
|
||||||
@ -198,7 +201,7 @@ def reconnect_imap(server, email, password, max_retries=5):
|
|||||||
conn.login(email, password)
|
conn.login(email, password)
|
||||||
logger.debug(f"Reconnected successfully to {server}")
|
logger.debug(f"Reconnected successfully to {server}")
|
||||||
return conn
|
return conn
|
||||||
except imaplib.IMAP4.abort as e:
|
except (imaplib.IMAP4.abort, socket.error, ssl.SSLError) as e:
|
||||||
logger.debug(f"Reconnect attempt {attempt + 1} failed: {e}")
|
logger.debug(f"Reconnect attempt {attempt + 1} failed: {e}")
|
||||||
time.sleep(2 ** attempt) # Exponential backoff
|
time.sleep(2 ** attempt) # Exponential backoff
|
||||||
attempt += 1
|
attempt += 1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user