Fix email fetch reliability for large emails with attachments
- Add 120s IMAP socket timeout (was unlimited, could hang on large emails) - Increase Paperless upload timeout from 60s to 300s for large attachments - Increase manual poll UI timeout from 60s to 300s - Show error count in UI when emails fail to process - Log warning when attachment payload is empty/corrupted Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -137,7 +137,7 @@ def _upload_to_paperless(content: bytes, filename: str, destinataer=None, betref
|
|||||||
headers=headers,
|
headers=headers,
|
||||||
data=form_data,
|
data=form_data,
|
||||||
files=files,
|
files=files,
|
||||||
timeout=60,
|
timeout=300, # 5 Minuten für große Anhänge
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
# Paperless gibt die neue Dokument-ID zurück (als Integer oder UUID-String)
|
# Paperless gibt die neue Dokument-ID zurück (als Integer oder UUID-String)
|
||||||
@@ -196,11 +196,12 @@ def poll_destinataer_emails(self, search_all_recent_days=0):
|
|||||||
errors = 0
|
errors = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# IMAP-Verbindung aufbauen
|
# IMAP-Verbindung aufbauen (mit Socket-Timeout für große E-Mails)
|
||||||
|
imap_timeout = 120 # Sekunden – genug für große Anhänge
|
||||||
if imap_use_ssl:
|
if imap_use_ssl:
|
||||||
mail = imaplib.IMAP4_SSL(imap_host, imap_port)
|
mail = imaplib.IMAP4_SSL(imap_host, imap_port, timeout=imap_timeout)
|
||||||
else:
|
else:
|
||||||
mail = imaplib.IMAP4(imap_host, imap_port)
|
mail = imaplib.IMAP4(imap_host, imap_port, timeout=imap_timeout)
|
||||||
|
|
||||||
mail.login(imap_user, imap_password)
|
mail.login(imap_user, imap_password)
|
||||||
mail.select(imap_folder)
|
mail.select(imap_folder)
|
||||||
@@ -279,6 +280,10 @@ def poll_destinataer_emails(self, search_all_recent_days=0):
|
|||||||
filename = _decode_header_value(part.get_filename() or "")
|
filename = _decode_header_value(part.get_filename() or "")
|
||||||
content = part.get_payload(decode=True)
|
content = part.get_payload(decode=True)
|
||||||
if not content:
|
if not content:
|
||||||
|
logger.warning(
|
||||||
|
"Anhang '%s' hat keinen Inhalt (möglicherweise zu groß oder beschädigt) – wird übersprungen.",
|
||||||
|
filename,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
doc_id = _upload_to_paperless(
|
doc_id = _upload_to_paperless(
|
||||||
|
|||||||
@@ -695,12 +695,20 @@ def email_eingang_poll_trigger(request):
|
|||||||
try:
|
try:
|
||||||
# Synchron ausführen für sofortiges Feedback; sucht auch bereits
|
# Synchron ausführen für sofortiges Feedback; sucht auch bereits
|
||||||
# gelesene E-Mails der letzten 30 Tage (Duplikate werden übersprungen).
|
# gelesene E-Mails der letzten 30 Tage (Duplikate werden übersprungen).
|
||||||
result = poll_destinataer_emails.apply(kwargs={"search_all_recent_days": 30}).get(timeout=60)
|
result = poll_destinataer_emails.apply(kwargs={"search_all_recent_days": 30}).get(timeout=300)
|
||||||
processed = result.get("processed", 0) if isinstance(result, dict) else 0
|
processed = result.get("processed", 0) if isinstance(result, dict) else 0
|
||||||
if result and result.get("status") == "skipped":
|
if result and result.get("status") == "skipped":
|
||||||
messages.warning(request, "IMAP ist nicht konfiguriert. Bitte Einstellungen unter Administration → E-Mail / IMAP prüfen.")
|
messages.warning(request, "IMAP ist nicht konfiguriert. Bitte Einstellungen unter Administration → E-Mail / IMAP prüfen.")
|
||||||
elif processed > 0:
|
elif processed > 0:
|
||||||
|
error_count = result.get("errors", 0) if isinstance(result, dict) else 0
|
||||||
|
if error_count > 0:
|
||||||
|
messages.warning(request, f"{processed} E-Mail(s) importiert, aber {error_count} Fehler aufgetreten. Bitte Logs prüfen.")
|
||||||
|
else:
|
||||||
messages.success(request, f"{processed} neue E-Mail(s) importiert.")
|
messages.success(request, f"{processed} neue E-Mail(s) importiert.")
|
||||||
|
else:
|
||||||
|
error_count = result.get("errors", 0) if isinstance(result, dict) else 0
|
||||||
|
if error_count > 0:
|
||||||
|
messages.warning(request, f"Keine neuen E-Mails importiert, aber {error_count} Fehler aufgetreten. Bitte Logs prüfen.")
|
||||||
else:
|
else:
|
||||||
messages.info(request, "Keine neuen E-Mails gefunden.")
|
messages.info(request, "Keine neuen E-Mails gefunden.")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user