fix(imap): use message header date for timestamps
Fixes
Ensures message timestamps mirror the actual send/receive time rather than the cache file’s modification time (Fixes #912)
What’s Changed
ImapMessageFetcher.php
-
Resolves the canonical message timestamp by:
- Parsing the RFC 822
Dateheader` - Falling back to IMAP
INTERNALDATEif the header is missing or invalid - Using the current time only as a last-resort fallback
- Parsing the RFC 822
-
The final resolved timestamp is cached and passed to
IMAPMessage -
This ensures
dateInt(and all UI components depending on it) reflects the true email date, even after:- Mailbox restores
- Cache rebuilds
ImapMessageFetcherTest.php
-
Adds PHPUnit test coverage for the new resolution logic
-
Confirms:
- Preference for the RFC 822 Date header
- Fallback to IMAP INTERNALDATE
- Handling of malformed or missing headers
- Final fallback behavior when no date can be determined
Testing
phpunit --filter ImapMessageFetcherTest
@ChristophWurst could you please check this one!
@kesselb could you please review this one
Thanks for your pr :pray:
Relying on the date header instead of, or in addition to, the IMAP date is something I've also noticed in Thunderbird, and I think that's a reasonable approach.
Failing test:
1) OCA\Mail\Tests\Unit\IMAP\ImapMessageFetcherTest::testResolveMessageDateFallsBackToInternalOnInvalidHeader
PHP Deprecated: SebastianBergmann\GlobalState\Snapshot::__construct(): Implicitly marking parameter $excludeList as nullable is deprecated, the explicit nullable type must be used instead in /home/runner/actions-runner/_work/mail/mail/nextcloud/apps/mail/vendor-bin/phpunit/vendor/sebastian/global-state/src/Snapshot.php on line 104
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'2025-10-20T10:00:00+00:00'
+'1969-12-31T23:59:59+00:00'
Failing test:
1) OCA\Mail\Tests\Unit\IMAP\ImapMessageFetcherTest::testResolveMessageDateFallsBackToInternalOnInvalidHeader PHP Deprecated: SebastianBergmann\GlobalState\Snapshot::__construct(): Implicitly marking parameter $excludeList as nullable is deprecated, the explicit nullable type must be used instead in /home/runner/actions-runner/_work/mail/mail/nextcloud/apps/mail/vendor-bin/phpunit/vendor/sebastian/global-state/src/Snapshot.php on line 104 Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ -'2025-10-20T10:00:00+00:00' +'1969-12-31T23:59:59+00:00'
i'll fix this!
Failing test:
1) OCA\Mail\Tests\Unit\IMAP\ImapMessageFetcherTest::testResolveMessageDateFallsBackToInternalOnInvalidHeader PHP Deprecated: SebastianBergmann\GlobalState\Snapshot::__construct(): Implicitly marking parameter $excludeList as nullable is deprecated, the explicit nullable type must be used instead in /home/runner/actions-runner/_work/mail/mail/nextcloud/apps/mail/vendor-bin/phpunit/vendor/sebastian/global-state/src/Snapshot.php on line 104 Failed asserting that two strings are identical. --- Expected +++ Actual @@ @@ -'2025-10-20T10:00:00+00:00' +'1969-12-31T23:59:59+00:00'
@kesselb To fix this, I will modify resolveMessageDate in ImapMessageFetcher.php to check if the parsed date is valid (i.e., has a positive timestamp) before returning it. If the date is invalid, it will fall back to the internal date, as intended by the test.
Hello there, Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.
We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.
Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6
Thank you for contributing to Nextcloud and we hope to hear from you soon!
(If you believe you should not receive this message, you can add yourself to the blocklist.)