str_printfa(str, "UID FETCH %u (", _mail->uid);
if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
str_append(str, "INTERNALDATE ");
+ if ((fields & MAIL_FETCH_SAVE_DATE) != 0) {
+ i_assert(HAS_ALL_BITS(mbox->capabilities,
+ IMAPC_CAPABILITY_SAVEDATE));
+ str_append(str, "SAVEDATE ");
+ }
if ((fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0)
str_append(str, "RFC822.SIZE ");
if ((fields & MAIL_FETCH_GUID) != 0) {
data->received_date == (time_t)-1)
fields |= MAIL_FETCH_RECEIVED_DATE;
if ((data->wanted_fields & MAIL_FETCH_SAVE_DATE) != 0 &&
- data->save_date == (time_t)-1 && data->received_date == (time_t)-1)
- fields |= MAIL_FETCH_RECEIVED_DATE;
+ data->save_date == (time_t)-1) {
+ if (HAS_ALL_BITS(mbox->capabilities, IMAPC_CAPABILITY_SAVEDATE))
+ fields |= MAIL_FETCH_SAVE_DATE;
+ else
+ fields |= MAIL_FETCH_RECEIVED_DATE;
+ }
if ((data->wanted_fields & (MAIL_FETCH_PHYSICAL_SIZE |
MAIL_FETCH_VIRTUAL_SIZE)) != 0 &&
data->physical_size == (uoff_t)-1 &&
static bool
imapc_mail_have_fields(struct imapc_mail *imail, enum mail_fetch_field fields)
{
+ struct imapc_mailbox *mbox = IMAPC_MAILBOX(imail->imail.mail.mail.box);
+
if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) {
if (imail->imail.data.received_date == (time_t)-1)
return FALSE;
fields &= ~MAIL_FETCH_RECEIVED_DATE;
}
+ if ((fields & MAIL_FETCH_SAVE_DATE) != 0) {
+ i_assert(HAS_ALL_BITS(mbox->capabilities,
+ IMAPC_CAPABILITY_SAVEDATE));
+ if (imail->imail.data.save_date == (time_t)-1)
+ return FALSE;
+ fields &= ~MAIL_FETCH_SAVE_DATE;
+ }
if ((fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0) {
if (imail->imail.data.physical_size == (uoff_t)-1)
return FALSE;
match = TRUE;
} else if (strcasecmp(key, "INTERNALDATE") == 0) {
if (imap_arg_get_astring(&args[i+1], &value) &&
- imap_parse_datetime(value, &t, &tz))
+ imap_parse_datetime(value, &t, &tz)) {
mail->imail.data.received_date = t;
+ if (HAS_NO_BITS(mbox->capabilities,
+ IMAPC_CAPABILITY_SAVEDATE))
+ mail->imail.data.save_date = t;
+ }
+ match = TRUE;
+ } else if (strcasecmp(key, "SAVEDATE") == 0) {
+ if (imap_arg_get_astring(&args[i+1], &value)) {
+ if (strcasecmp(value, "NIL") == 0)
+ mail->imail.data.save_date = 0;
+ else if (imap_parse_datetime(value, &t, &tz))
+ mail->imail.data.save_date = t;
+ }
match = TRUE;
} else if (strcasecmp(key, "BODY") == 0) {
if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_BODYSTRUCTURE)) {
static int imapc_mail_get_save_date(struct mail *_mail, time_t *date_r)
{
+ struct imapc_mailbox *mbox = IMAPC_MAILBOX(_mail->box);
struct index_mail *mail = INDEX_MAIL(_mail);
struct index_mail_data *data = &mail->data;
- if (data->save_date == (time_t)-1) {
- /* FIXME: we could use a value stored in cache */
+ if (data->save_date != 0 && index_mail_get_save_date(_mail, date_r) > 0)
+ return 1;
+
+ if (HAS_NO_BITS(mbox->capabilities, IMAPC_CAPABILITY_SAVEDATE)) {
+ data->save_date = 0;
+ } else if (data->save_date == (time_t)-1) {
+ if (imapc_mail_fetch(_mail, MAIL_FETCH_SAVE_DATE, NULL) < 0)
+ return -1;
+ if (data->save_date == (time_t)-1 &&
+ imapc_mail_failed(_mail, "SAVEDATE") < 0)
+ return -1;
+ }
+ if (data->save_date == (time_t)-1 || data->save_date == 0) {
if (imapc_mail_get_received_date(_mail, date_r) < 0)
return -1;
return 0;
}
*date_r = data->save_date;
- return 0;
+ return 1;
}
static int imapc_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0)
(void)index_mail_get_received_date(_mail, &date);
if ((data->wanted_fields & MAIL_FETCH_SAVE_DATE) != 0) {
- if (index_mail_get_save_date(_mail, &date) < 0) {
+ if (index_mail_get_save_date(_mail, &date) < 0 &&
+ HAS_NO_BITS(mbox->capabilities,
+ IMAPC_CAPABILITY_SAVEDATE)) {
(void)index_mail_get_received_date(_mail, &date);
data->save_date = data->received_date;
}
return TRUE;
case SEARCH_BEFORE:
case SEARCH_SINCE:
- if ((mbox->capabilities & IMAPC_CAPABILITY_WITHIN) == 0) {
+ case SEARCH_ON:
+ if (arg->type != SEARCH_ON &&
+ (mbox->capabilities & IMAPC_CAPABILITY_WITHIN) == 0) {
/* a bit kludgy way to check this.. */
size_t pos = str_len(str);
if (!mail_search_arg_to_imap(str, arg, &error))
return FALSE;
return TRUE;
}
+ if (arg->value.date_type == MAIL_SEARCH_DATE_TYPE_SAVED &&
+ (mbox->capabilities & IMAPC_CAPABILITY_SAVEDATE) == 0) {
+ /* Fall back to internal date if save date is not
+ supported. */
+ arg2.value.date_type = MAIL_SEARCH_DATE_TYPE_RECEIVED;
+ }
/* fall through */
case SEARCH_ALL:
case SEARCH_UIDSET:
case SEARCH_FLAGS:
case SEARCH_KEYWORDS:
- case SEARCH_ON:
case SEARCH_SMALLER:
case SEARCH_LARGER:
case SEARCH_HEADER:
return FALSE;
return mail_search_arg_to_imap(str, arg, &error);
case SEARCH_SAVEDATESUPPORTED:
+ if ((mbox->capabilities & IMAPC_CAPABILITY_SAVEDATE) == 0)
+ return FALSE;
+ return mail_search_arg_to_imap(str, arg, &error);
case SEARCH_INTHREAD:
case SEARCH_GUID:
case SEARCH_MAILBOX: