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

1import logging 

2from typing import Final 

3 

4from celery import Task 

5from celery import shared_task 

6from django.core.cache import cache 

7 

8from paperless_mail.mail import MailAccountHandler 

9from paperless_mail.mail import MailError 

10from paperless_mail.models import MailAccount 

11from paperless_mail.models import MailRule 

12 

13logger = logging.getLogger("paperless.mail.tasks") 

14 

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 

20 

21 

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." 

29 

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) 

50 

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)