Coverage for paperless_mail/tasks.py: 34%
33 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
1import logging
2from typing import Final
4from celery import Task
5from celery import shared_task
6from django.core.cache import cache
8from paperless_mail.mail import MailAccountHandler
9from paperless_mail.mail import MailError
10from paperless_mail.models import MailAccount
11from paperless_mail.models import MailRule
13logger = logging.getLogger("paperless.mail.tasks")
15# Cache-backed lock guarding overlapping mail-account processing runs; unlike
16# a PaperlessTask row, it self-heals if the owning worker dies mid-run.
17MAIL_FETCH_LOCK_KEY: Final = "paperless_mail_fetch_lock"
18# Ceiling on how long a run may hold the lock; renewed after each account.
19MAIL_FETCH_LOCK_TTL: Final = 30 * 60
22@shared_task(bind=True)
23def process_mail_accounts(self: Task, account_ids: list[int] | None = None) -> str:
24 if not cache.add(MAIL_FETCH_LOCK_KEY, self.request.id, timeout=MAIL_FETCH_LOCK_TTL):
25 logger.info(
26 "Mail account processing is already running; skipping this run.",
27 )
28 return "Skipped: mail account processing already in progress."
30 try:
31 total_new_documents = 0
32 accounts = (
33 MailAccount.objects.filter(pk__in=account_ids)
34 if account_ids
35 else MailAccount.objects.all()
36 )
37 for account in accounts:
38 if not MailRule.objects.filter(account=account, enabled=True).exists():
39 logger.info(f"No rules enabled for account {account}. Skipping.")
40 continue
41 try:
42 total_new_documents += MailAccountHandler().handle_mail_account(
43 account,
44 )
45 except MailError:
46 logger.exception(f"Error while processing mail account {account}")
47 # Renew the lock so a run still genuinely in progress doesn't
48 # lose it to the TTL partway through a long account list.
49 cache.touch(MAIL_FETCH_LOCK_KEY, MAIL_FETCH_LOCK_TTL)
51 if total_new_documents > 0:
52 return f"Added {total_new_documents} document(s)."
53 else:
54 return "No new documents were added."
55 finally:
56 cache.delete(MAIL_FETCH_LOCK_KEY)