Skip to content

Preserve the original message date on import of EML messages (#5559)#10251

Open
MiMoHo wants to merge 1 commit into
roundcube:masterfrom
MiMoHo:import-eml-internaldate
Open

Preserve the original message date on import of EML messages (#5559)#10251
MiMoHo wants to merge 1 commit into
roundcube:masterfrom
MiMoHo:import-eml-internaldate

Conversation

@MiMoHo

@MiMoHo MiMoHo commented Jul 6, 2026

Copy link
Copy Markdown

Problem

Since #5559 the import action preserves the original message date, but only for mbox input, where the received date is taken from the mbox from-line and passed to IMAP APPEND as the message INTERNALDATE. As noted back then:

Implemented. Of course it works only with mbox format which stores the date in "from line".

For EML input (single files or inside ZIP archives) no date is extracted at all, so every imported message gets the time of the import as its INTERNALDATE. That affects sorting by arrival date, SEARCH BEFORE/SINCE, and the message list when the arrival date is displayed — a mailbox restored from EML backups shows all messages as "received" at import time.

Change

When no date was found, rcmail_action_mail_import::save_message() now falls back to the message's Date header:

  • EML input — the Date header is the only original date an EML file carries, and it is close enough to the delivery time that INTERNALDATE is supposed to hold. Other clients (e.g. Thunderbird's ImportExportTools) do the same on EML import.
  • mbox input whose from-line has no recognized date — previously these messages also fell through to null; the Date header is a strictly better fallback than the import time.
  • The mbox from-line date keeps precedence when present (it is the actual received date).

Implementation notes:

  • The header block is split off at the first empty line before parsing (rcube_mime::parse_headers()), so Date:-like lines in the message body cannot be picked up.
  • Parsing uses the existing rcube_utils::anytodatetime(); RFC 2822 dates keep their original UTC offset all the way into the APPEND date-time string.
  • A missing or unparsable Date header keeps the previous behavior (APPEND without a date-time, i.e. server assigns the current time).

Testing

  • New ImportTest::test_save_message_date() covers: EML with Date header, header-only message, missing Date header with a Date-like line in the body (must be ignored), unparsable Date header, and the mbox from-line fallback.
  • The existing upload tests in ImportTest now also assert the date argument passed to save_message() for both the EML and the mbox path (the mbox from-line date extraction was previously untested).
  • Full chain verified locally down to the APPEND command: Date: Fri, 23 May 2014 19:44:50 +0200rcube_utils::anytodatetime()rcube_imap::date_format()"23-May-2014 19:44:50 +0200"; null propagates to an APPEND without date-time.
  • Full PHPUnit suite passes; php-cs-fixer and phpstan clean on the changed files.

This contribution was prepared with AI assistance (Claude); the analysis, implementation and tests were reviewed and verified by test runs as described above.

🤖 Generated with Claude Code

…be#5559)

The import action extracts the received date from the mbox from-line and
passes it to IMAP APPEND as the message INTERNALDATE (roundcube#5559), but for EML
input no date was extracted at all, so imported messages got the time of
the import as their INTERNALDATE. This affects sorting by arrival date,
SEARCH BEFORE/SINCE, and the list display with mail_pagesize arrival date.

Fall back to the message's Date header when no date was found - i.e. for
EML input, and also for mbox messages whose from-line has no recognized
date. The header block is split off before parsing, so Date-like lines in
the message body are ignored, and an invalid or missing Date header keeps
the previous behavior (APPEND without a date-time).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant