the-djmaze / snappymail

Simple, modern & fast web-based email client
https://snappymail.eu
GNU Affero General Public License v3.0
998 stars 121 forks source link

Received date can change just by selecting an email #1554

Closed Massedil closed 4 months ago

Massedil commented 5 months ago

Describe the bug

Received date can change just by selecting an email.

To Reproduce

It changed !

Expected behavior

The date stay the same !

And the good one (but is it the sent date or the received date here ?) !

Screenshots

Not selected :

2024-04-19_18-01

Selected :

2024-04-19_18-01_1

Please complete the following information:

Debug/logging information

Received: XXXXXXXXXX
    XXXXXXXXXX
    XXXXXXXXXX
    XXXXXXXXXX
    by XXXXXXXXXX
    for <XXXXXXXXXX@XXXXXXXXXX>; Fri, 19 Apr 2024 17:57:46 +0200 (CEST)

[...]

Received: from XXXXXXXXXX
 by XXXXXXXXXX
 XXXXXXXXXX
 Fri, 19 Apr 2024 15:12:16 +0000

[...]

Date: Fri, 19 Apr 2024 17:12:16 +0200

Additional context

I think it is because of the long delay ; because the mail is POPed by an intermediate server on the road to my mailbox.

the-djmaze commented 5 months ago

There are two timestamps in use:

internal is only used when the date header parsing failed.

Right click and inspect the the time html element. It should be like:

<time data-bind="attr:{'data-time-format':$root.timeFormat()}, time: dateTimestamp" data-time-format="LT" datetime="2024-04-19T15:12:16.000Z" title="19 Apr 2024 at 13:12">17:12</time>
Massedil commented 5 months ago

Right click and inspect the the time html element.

Before selection :

<time data-time-format="AUTO" data-bind="time: dateTimestamp" datetime="2024-04-28T10:40:11.000Z" title="28 avril 2024 à 12:40">Aujourd'hui à 12:40</time>

After selection :

<time data-time-format="AUTO" data-bind="time: dateTimestamp" datetime="2024-04-28T11:08:16.000Z" title="28 avril 2024 à 13:08">Aujourd'hui à 13:08</time>

internal is only used when the date header parsing failed.

Why is there something that fails in my case ?

the-djmaze commented 5 months ago

Why is there something that fails in my case ?

It seems the message date header fails to parse and then it uses the internal date.

To find out, you could modify https://github.com/the-djmaze/snappymail/blob/53a6f04f1840e76ea92e178c70c7e912af1c6e69/snappymail/v/0.0.0/app/libraries/MailSo/Mail/Message.php#L487-L509

In

    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
/*
        // JMAP-only RFC8621 keywords (RFC5788)
        $keywords = \array_fill_keys(\str_replace(
            ['\\draft', '\\seen', '\\flagged', '\\answered'],
            [ '$draft',  '$seen',  '$flagged',  '$answered'],
            $this->aFlagsLowerCase
        ), true);
*/
        $result = array(
            '@Object' => 'Object/Message',
            'folder' => $this->sFolder,
            'uid' => $this->Uid,
            'hash' => \md5($this->sFolder . $this->Uid),
            'subject' => \trim(Utils::Utf8Clear($this->sSubject)),
            'encrypted' => 'multipart/encrypted' == $this->sContentType || $this->pgpEncrypted || $this->smimeEncrypted,
            'messageId' => $this->sMessageId,
            'spamScore' => $this->bIsSpam ? 100 : $this->SpamScore,
            'spamResult' => $this->sSpamResult,
            'isSpam' => $this->bIsSpam,
            'dateTimestamp' => $this->iHeaderTimeStampInUTC ?: $this->iInternalTimeStampInUTC,
            'dateHeaderTimestamp' => $this->iHeaderTimeStampInUTC,

And then check the dateHeaderTimestamp in responses.

Other option would be to debug the parser, by modifying https://github.com/the-djmaze/snappymail/blob/53a6f04f1840e76ea92e178c70c7e912af1c6e69/snappymail/v/0.0.0/app/libraries/MailSo/Base/DateTimeHelper.php#L36-L46 into

    public static function ParseRFC2822DateString(string $sDateTime) : int
    {
        $sDateTime = \trim($sDateTime);
        if (empty($sDateTime)) {
            \error_log("No RFC 2822 date to parse");
            return 0;
        }

        $sDateTime = \trim(\preg_replace('/ \([a-zA-Z0-9]+\)$/', '', $sDateTime));
        $oDateTime = \DateTime::createFromFormat(\DateTime::RFC2822, $sDateTime, static::GetUtcTimeZoneObject());
        if (!$oDateTime || 943920000 > $oDateTime->getTimestamp()) {
            \error_log("Failed to parse RFC 2822 date '{$sDateTime}'");
        }
        return $oDateTime ? $oDateTime->getTimestamp() : 0;
    }

And then check the PHP error log

Massedil commented 5 months ago

And then check the dateHeaderTimestamp in responses.

{
    "Action": "Message",
    "Result": {
        "@Object": "Object/Message",
        "folder": "INBOX",
        "dateTimestamp": 1714302496,
        "dateHeaderTimestamp": 1714300811,
        "internalTimestamp": 1714302496,

Other option would be to debug the parser, by modifying

After editing the file snappymail/snappymail/v/2.36.0/app/libraries/MailSo/Base/DateTimeHelper.php as you said, I have no new log in the error log file.

Massedil commented 4 months ago

Can I do something more to help you here ?

the-djmaze commented 4 months ago

Yes, SnappyMail should now log when RFC 2822 date header is missing. If the log is empty, it has issues with the Date header in the mail and i have no idea why. Maybe there are multiple Date headers?

Massedil commented 4 months ago

I tried to reproduce, but without success. Even with the emails what triggered the problem before. Don't understand why this is suddenly solved, I'll reopen the issue if I can reproduce it again one day.