On Sunday, October 28 at 03:16 AM, quoth Timo Sirainen:
- SORT: If Date: header is missing or broken, fallback to using INTERNALDATE (as the SORT draft nowadays specifies).
Since this is a subject I looked at before, I'm rather curious. Where in the SORT draft does it say to fall back to INTERNALDATE? What I read (from http://tools.ietf.org/id/draft-ietf-imapext-sort-19.txt, section 2.2) is this:
As used in this document, the term "sent date" refers to the date
and time from the Date: header, adjusted by time zone to normalize
to UTC. For example, "31 Dec 2000 16:01:33 -0800" is equivalent
to the UTC date and time of "1 Jan 2001 00:01:33 +0000".
If the time zone is invalid, the date and time SHOULD be treated
as UTC. If the time is also invalid, the time SHOULD be treated
as 00:00:00. If there is no valid date or time, the date and time
SHOULD be treated as 00:00:00 on the earliest possible date.
The key part is that last sentence: without a Date header, there is no valid date or time, so the date and time SHOULD be treated as 00:00:00 on the *earliest possible* date. The earliest possible date, however, is not INTERNALDATE, but is instead the earliest timestamp in any of the Received headers (or INTERNALDATE, if that's earlier, though that would be pretty rare).
Even if we didn't feel like parsing Received headers, mail_get_received_date() (i.e. the current 1.0.7 implementation) is wrong because it isn't 00:00:00 on that date.
Thus, I think mail_sort_get_date() in imap-sort.c should look more like this:
static time_t mail_sort_get_date(struct mail *mail) { time_t t, t2;
t = mail_get_date(mail, NULL);
if (t == 0 || t == (time_t)-1) {
/* missing or broken Date: header */
const char *const *headers = mail_get_headers(mail, "Received");
if (headers != NULL && headers[0] != NULL) {
while (headers[1] != NULL) headers++; // find the last one
/* first, find the semicolon */
const char * curs = headers[0];
while (curs[0] != ';' && curs[0] != 0) {
if (curs[0] == '(')
while (curs[0] != ')' && curs[0] != 0) curs++;
curs++;
}
if (curs[0] == ';') {
curs++;
if (curs[0] != 0) {
int tz;
message_date_parse((const unsigned char *)curs,
strlen(curs), &t, &tz);
}
}
}
t2 = mail_get_received_date(mail); // INTERNALDATE
if (t2 < t) t = t2;
}
return t;
}
However, this doesn't follow the spec's requirement of being 00:00:00 on that date. I'm not sure if there's an easy fix, though (be nice if we could just apply a bitmask; but we can't).
What do you think?
~Kyle
A tyrant must put on the appearance of uncommon devotion to religion. Subjects are less apprehensive of illegal treatment from a ruler whom they consider God-fearing and pious. On the other hand, they do less easily move against him, believing that he has the gods on his side. -- Aristotle