static void index_mail_update_access_parts(struct index_mail *mail) { struct mail *_mail = &mail->mail.mail; struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; struct index_mail_data *data = &mail->data; struct mailbox_header_lookup_ctx *header_ctx; time_t date; uoff_t size; if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0) (void)index_mail_get_received_date(_mail, &date); if ((data->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE) != 0) { if (index_mail_get_physical_size(_mail, &size) < 0 && !IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE)) data->access_part |= READ_HDR | READ_BODY; } if (data->access_part == 0 && data->wanted_headers != NULL) { /* see if all wanted headers exist in cache */ if (!imapc_mail_has_headers_in_cache(mail, data->wanted_headers)) data->access_part |= PARSE_HDR; } if (data->access_part == 0 && (data->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) != 0) { /* the common code already checked this partially, but we need a guaranteed correct answer */ header_ctx = mailbox_header_lookup_init(_mail->box, imap_envelope_headers); if (!imapc_mail_has_headers_in_cache(mail, header_ctx)) data->access_part |= PARSE_HDR; mailbox_header_lookup_unref(&header_ctx); } }
static int imapc_mail_get_header_stream(struct mail *_mail, struct mailbox_header_lookup_ctx *headers, struct istream **stream_r) { struct imapc_mail *mail = (struct imapc_mail *)_mail; struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; enum mail_lookup_abort old_abort = _mail->lookup_abort; int ret; if (mail->imail.data.access_part != 0 || !IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_HEADERS)) { /* we're going to be reading the header/body anyway */ return index_mail_get_header_stream(_mail, headers, stream_r); } /* see if the wanted headers are already in cache */ _mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL; ret = index_mail_get_header_stream(_mail, headers, stream_r); _mail->lookup_abort = old_abort; if (ret == 0) return 0; /* fetch only the wanted headers */ if (imapc_mail_fetch(_mail, 0, headers->name) < 0) return -1; /* the headers should cached now. */ return index_mail_get_header_stream(_mail, headers, stream_r); }
static int imapc_mail_get_physical_size(struct mail *_mail, uoff_t *size_r) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; struct index_mail *mail = (struct index_mail *)_mail; struct index_mail_data *data = &mail->data; struct istream *input; uoff_t old_offset; int ret; if (data->physical_size == (uoff_t)-1) { (void)index_mail_get_physical_size(_mail, size_r); if (data->physical_size != (uoff_t)-1) { *size_r = data->physical_size; return 0; } } if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE) && data->stream == NULL) { /* trust RFC822.SIZE to be correct */ if (imapc_mail_fetch(_mail, MAIL_FETCH_PHYSICAL_SIZE) < 0) return -1; if (data->physical_size == (uoff_t)-1) { if (imapc_mail_failed(_mail, "RFC822.SIZE") < 0) return -1; /* assume that the server never returns RFC822.SIZE for this mail (see BODY[] failure handling) */ data->physical_size = 0; } *size_r = data->physical_size; return 0; } old_offset = data->stream == NULL ? 0 : data->stream->v_offset; if (mail_get_stream(_mail, NULL, NULL, &input) < 0) return -1; i_stream_seek(data->stream, old_offset); ret = i_stream_get_size(data->stream, TRUE, &data->physical_size); if (ret <= 0) { i_assert(ret != 0); mail_storage_set_critical(_mail->box->storage, "imapc: stat(%s) failed: %m", i_stream_get_name(data->stream)); return -1; } *size_r = data->physical_size; return 0; }
static int imapc_mail_get_special(struct mail *_mail, enum mail_fetch_field field, const char **value_r) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; struct index_mail *imail = (struct index_mail *)_mail; uint64_t num; switch (field) { case MAIL_FETCH_GUID: if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GUID_FORCED) && mbox->guid_fetch_field_name == NULL) { /* GUIDs not supported by server */ break; } *value_r = ""; return imapc_mail_get_guid(_mail, value_r); case MAIL_FETCH_UIDL_BACKEND: if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_MIGRATION)) break; if (imapc_mail_get_guid(_mail, value_r) < 0) return -1; if (str_to_uint64(*value_r, &num) < 0) { mail_storage_set_critical(_mail->box->storage, "X-GM-MSGID not 64bit integer as expected for POP3 UIDL generation: %s", *value_r); return -1; } *value_r = p_strdup_printf(imail->mail.data_pool, "GmailId%llx", (unsigned long long)num); return 0; default: break; } return index_mail_get_special(_mail, field, value_r); }
static int imapc_mail_get_special(struct mail *_mail, enum mail_fetch_field field, const char **value_r) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; switch (field) { case MAIL_FETCH_GUID: if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GUID_FORCED) && mbox->guid_fetch_field_name == NULL) { /* GUIDs not supported by server */ break; } *value_r = ""; return imapc_mail_get_guid(_mail, value_r); default: break; } return index_mail_get_special(_mail, field, value_r); }