Repository: paperless-ngx/paperless-ngx

Issue:
[BUG] Consumption Template / filename matching doesnt work with email fetching
### Description

I have a fetch all email consumption and try to sort & match it with the consumption templates feature. Unfortunately, it doesnt work as i thought it should. It shows a totally different filename in the logs ("paperless-mail-ebpr0mcs") when consuming via mail fetcher but as soon as consumtion is finished the original file name is shown in the database ("2023_12rechnung_123456789.pdf")  

The feature works as intended when uploading it manually via the frontend. 

Any suggestions?

### Steps to reproduce

1. send email to fetchall mail address
2. let the consumer consume the document
3. it does not recognize the title made in the consumption template (shows another file name)

### Webserver logs

```bash
Log when consumed via email fetching:
[2023-12-11 14:40:04,587] [INFO] [paperless.matching] Document did not match template Telekom Festnetz-Rechnung
[2023-12-11 14:40:04,587] [DEBUG] [paperless.matching] Document filename paperless-mail-ebpr0mcs does not match *123456789.pdf


Log when consumed via manual upload / frontend:
[2023-12-11 14:33:28,697] [INFO] [paperless.matching] Document did not match template Entgeltabrechnung
[2023-12-11 14:33:28,698] [DEBUG] [paperless.matching] Document filename 2023_12rechnung_123456789.pdf does not match entgeltabrechnung*
[2023-12-11 14:33:28,698] [INFO] [paperless.matching] Document matched template Telekom Festnetz-Rechnung
[2023-12-11 14:33:28,727] [INFO] [paperless.consumer] Consuming 2023_12rechnung_123456789.pdf
```


### Browser logs

_No response_

### Paperless-ngx version

2.1.1

### Host OS

Linux / Proxmox

### Installation method

Bare metal

### Browser

_No response_

### Configuration changes

_No response_

### Other

_No response_


Discussion:

Resolving patch:
diff --git a/src/paperless_mail/mail.py b/src/paperless_mail/mail.py
--- a/src/paperless_mail/mail.py
+++ b/src/paperless_mail/mail.py
@@ -8,6 +8,7 @@
 from datetime import date
 from datetime import timedelta
 from fnmatch import fnmatch
+from pathlib import Path
 from typing import Optional
 from typing import Union
 
@@ -703,12 +704,15 @@ def _process_attachments(
 
             if is_mime_type_supported(mime_type):
                 os.makedirs(settings.SCRATCH_DIR, exist_ok=True)
-                _, temp_filename = tempfile.mkstemp(
-                    prefix="paperless-mail-",
-                    dir=settings.SCRATCH_DIR,
+
+                temp_dir = Path(
+                    tempfile.mkdtemp(
+                        prefix="paperless-mail-",
+                        dir=settings.SCRATCH_DIR,
+                    ),
                 )
-                with open(temp_filename, "wb") as f:
-                    f.write(att.payload)
+                temp_filename = temp_dir / pathvalidate.sanitize_filename(att.filename)
+                temp_filename.write_bytes(att.payload)
 
                 self.log.info(
                     f"Rule {rule}: "


Test patch:
diff --git a/src/paperless_mail/tests/test_mail.py b/src/paperless_mail/tests/test_mail.py
--- a/src/paperless_mail/tests/test_mail.py
+++ b/src/paperless_mail/tests/test_mail.py
@@ -1271,7 +1271,10 @@ def test_auth_with_valid_token(self):
         self.assertEqual(len(self.bogus_mailbox.fetch("UNSEEN", False)), 0)
         self.assertEqual(len(self.bogus_mailbox.messages), 3)
 
-    def assert_queue_consumption_tasks_call_args(self, expected_call_args: list):
+    def assert_queue_consumption_tasks_call_args(
+        self,
+        expected_call_args: list[list[dict[str, str]]],
+    ):
         """
         Verifies that queue_consumption_tasks has been called with the expected arguments.
 
@@ -1283,7 +1286,7 @@ def assert_queue_consumption_tasks_call_args(self, expected_call_args: list):
 
         """
 
-        # assert number of calls to queue_consumption_tasks mathc
+        # assert number of calls to queue_consumption_tasks match
         self.assertEqual(
             len(self._queue_consumption_tasks_mock.call_args_list),
             len(expected_call_args),