index-mail.c revision 61e27995aadbc2f97927d3635f98d1d4ac4751e0
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinastruct mail_cache_field global_cache_fields[MAIL_INDEX_CACHE_FIELD_COUNT] = {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "flags", 0, MAIL_CACHE_FIELD_BITMASK, sizeof(uint32_t), 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "date.sent", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina sizeof(struct mail_sent_date), 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "date.received", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "date.save", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose { "size.virtual", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina sizeof(uoff_t), 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "size.physical", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
4169fb26ea2ff93c19ecdad6e09382732ea5deebPavel Březina sizeof(uoff_t), 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "imap.body", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina { "imap.bodystructure", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina { "imap.envelope", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "pop3.uidl", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina { "mime.parts", 0, MAIL_CACHE_FIELD_VARIABLE_SIZE, 0, 0 }
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozekstatic int index_mail_parse_body(struct index_mail *mail,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozekint index_mail_cache_lookup_field(struct index_mail *mail, buffer_t *buf,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek ret = mail_cache_lookup_field(mail->trans->cache_view, buf,
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinastatic struct message_part *get_unserialized_parts(struct index_mail *mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina unsigned int field_idx =
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina part_buf = buffer_create_dynamic(pool_datastack_create(), 128);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina ret = index_mail_cache_lookup_field(mail, part_buf, field_idx);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina parts = message_part_deserialize(mail->data_pool, part_buf->data,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_cache_set_corrupted(mail->mail.mail.box->cache,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina "Corrupted cached message_part data (%s)", error);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic bool get_cached_parts(struct index_mail *mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina /* we know the NULs now, update them */
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina if ((part->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinastatic bool index_mail_get_fixed_field(struct index_mail *mail,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek unsigned int field_idx = mail->ibox->cache_fields[field].idx;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina if (index_mail_cache_lookup_field(mail, &buf, field_idx) <= 0)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinabool index_mail_get_cached_uoff_t(struct index_mail *mail,
b206e1abb7f6ea373d12537b3338552aed6b656dPavel Březinaenum mail_flags index_mail_get_flags(struct mail *mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina rec = mail_index_lookup(mail->transaction->view, mail->seq);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina if (index_mailbox_is_recent(mail->box, mail->uid))
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinauint64_t index_mail_get_modseq(struct mail *_mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina mail_index_modseq_lookup(_mail->transaction->view, _mail->seq);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinaconst char *const *index_mail_get_keywords(struct mail *_mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina const char *const *names;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina const unsigned int *keyword_indexes;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina keyword_indexes = array_get(&data->keyword_indexes, &count);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina names = array_get(mail->ibox->keyword_names, &names_count);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina p_array_init(&data->keywords, mail->data_pool, count + 1);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina for (i = 0; i < count; i++) {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina /* end with NULL */
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinaindex_mail_get_keyword_indexes(struct mail *_mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
b206e1abb7f6ea373d12537b3338552aed6b656dPavel Březina if (!array_is_created(&data->keyword_indexes)) {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina p_array_init(&data->keyword_indexes, mail->data_pool, 32);
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina mail_index_lookup_keywords(_mail->transaction->view,
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinaint index_mail_get_parts(struct mail *_mail, struct message_part **parts_r)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina data->cache_fetch_fields |= MAIL_FETCH_MESSAGE_PARTS;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina if (data->parts != NULL || get_cached_parts(mail)) {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinaint index_mail_get_received_date(struct mail *_mail, time_t *date_r)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose data->cache_fetch_fields |= MAIL_FETCH_RECEIVED_DATE;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose if (index_mail_get_fixed_field(mail, MAIL_CACHE_RECEIVED_DATE,
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose &t, sizeof(t)))
827a016a07d5f911cc4195be89896a376fd71f59Sumit Boseint index_mail_get_save_date(struct mail *_mail, time_t *date_r)
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose struct index_mail *mail = (struct index_mail *)_mail;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose data->cache_fetch_fields |= MAIL_FETCH_SAVE_DATE;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose if (index_mail_get_fixed_field(mail, MAIL_CACHE_SAVE_DATE,
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose &t, sizeof(t)))
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bosestatic int index_mail_cache_sent_date(struct index_mail *mail)
cee85e8fb9534ec997e5388fce59f392cf029573Jakub Hrozek const char *str;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose if ((ret = mail_get_first_header(&mail->mail.mail, "Date", &str)) < 0)
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose /* 0 = not found / invalid */
827a016a07d5f911cc4195be89896a376fd71f59Sumit Boseint index_mail_get_date(struct mail *_mail, time_t *date_r, int *timezone_r)
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose struct index_mail *mail = (struct index_mail *)_mail;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose (void)index_mail_get_fixed_field(mail, MAIL_CACHE_SENT_DATE,
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bosestatic bool get_cached_msgpart_sizes(struct index_mail *mail)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->virtual_size = data->parts->header_size.virtual_size +
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->physical_size = data->parts->header_size.physical_size +
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bosebool index_mail_get_cached_virtual_size(struct index_mail *mail, uoff_t *size_r)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (data->hdr_size_set && data->physical_size != (uoff_t)-1) {
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->body_size.physical_size = data->physical_size -
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->body_size.virtual_size = data->virtual_size -
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bosestatic void index_mail_get_cached_body_size(struct index_mail *mail)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose /* we've already called get_cached_msgpart_sizes() and it didn't work.
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose try to do this by using cached virtual size and a quick physical
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose size lookup. */
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (!index_mail_get_cached_virtual_size(mail, &tmp))
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (mail_get_physical_size(&mail->mail.mail, &tmp) < 0)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose /* we should have everything now. try again. */
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose (void)index_mail_get_cached_virtual_size(mail, &tmp);
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Boseint index_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose struct index_mail *mail = (struct index_mail *)_mail;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (index_mail_get_cached_virtual_size(mail, size_r))
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Boseint index_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose struct index_mail *mail = (struct index_mail *)_mail;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose data->cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bosevoid index_mail_cache_add(struct index_mail *mail, enum index_cache_field field,
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose index_mail_cache_add_idx(mail, mail->ibox->cache_fields[field].idx,
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bosevoid index_mail_cache_add_idx(struct index_mail *mail, unsigned int field_idx,
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose /* First check if we've configured caching not to be used with
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose low enough message count. */
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose hdr = mail_index_get_header(mail->mail.mail.box->view);
861dbe0794739a1c93a5bed00913c7442a2bdac9Sumit Bose if (hdr->messages_count < set->mail_cache_min_mail_count)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail->data.dont_cache_field_idx != field_idx) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_cache_add(mail->trans->cache_trans, mail->data.seq,
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidênciostatic void parse_bodystructure_part_header(struct message_part *part,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek imap_bodystructure_parse_header(pool, part, hdr);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic bool want_plain_bodystructure_cached(struct index_mail *mail)
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidêncio if ((mail->wanted_fields & (MAIL_FETCH_IMAP_BODY |
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODY].idx))
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidêncio if (mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq,
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidêncio mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx))
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic void index_mail_body_parsed_cache_flags(struct index_mail *mail)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose cache_flags_idx = mail->ibox->cache_fields[MAIL_CACHE_FLAGS].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose want_cached = mail_cache_field_want_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose (want_cached || want_plain_bodystructure_cached(mail))) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose cache_flags |= MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* we need message_parts cached to be able to
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose actually use it in BODY/BODYSTRUCTURE reply */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* cache flags should never get unset as long as the message doesn't
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose change, but try to handle it anyway */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if (data->hdr_size.virtual_size == data->hdr_size.physical_size)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if (data->body_size.virtual_size == data->body_size.physical_size)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if (cache_flags != data->cache_flags && want_cached) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic void index_mail_body_parsed_cache_message_parts(struct index_mail *mail)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose unsigned int cache_field =
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_exists(mail->trans->cache_view, mail->data.seq,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* already cached */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose decision = mail_cache_field_get_decision(mail->mail.mail.box->cache,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if (decision == (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* we never want it cached */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose (mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) == 0) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* we didn't really care about the message parts themselves,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose just wanted to use something that depended on it */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose buffer = buffer_create_dynamic(pool_datastack_create(), 1024);
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose message_part_serialize(mail->data.parts, buffer);
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Boseindex_mail_body_parsed_cache_bodystructure(struct index_mail *mail,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODY].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if ((data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_exists(mail->trans->cache_view, data->seq,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* cached it as flag + message_parts */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* If BODY is fetched first but BODYSTRUCTURE is also wanted, we don't
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose normally want to first cache BODY and then BODYSTRUCTURE. So check
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose the wanted_fields also in here. */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose else if (field == MAIL_CACHE_IMAP_BODYSTRUCTURE ||
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose (mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_can_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_want_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose imap_bodystructure_write(data->parts, str, TRUE);
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODYSTRUCTURE,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* normally don't cache both BODY and BODYSTRUCTURE, but do it
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if BODY is forced to be cached */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose dec = mail_cache_field_get_decision(mail->mail.mail.box->cache,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose (dec != (MAIL_CACHE_DECISION_FORCED | MAIL_CACHE_DECISION_YES))))
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_can_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_cache_field_want_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose imap_bodystructure_write(data->parts, str, FALSE);
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODY,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Boseindex_mail_want_cache(struct index_mail *mail, enum index_cache_field field)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if ((mail->data.dont_cache_fetch_fields & fetch_field) != 0)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose cache_field = mail->ibox->cache_fields[field].idx;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if ((mail->data.cache_fetch_fields & fetch_field) != 0) {
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose return mail_cache_field_can_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose return mail_cache_field_want_add(mail->trans->cache_trans,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic void index_mail_cache_sizes(struct index_mail *mail)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose unsigned int i;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic void index_mail_cache_dates(struct index_mail *mail)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose unsigned int i;
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose &t, sizeof(t));
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose index_mail_want_cache(mail, MAIL_CACHE_SENT_DATE))
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic int index_mail_parse_body_finish(struct index_mail *mail,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose if (message_parser_deinit(&mail->data.parser_ctx,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose /* if we're here because we aborted parsing, don't get any
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose further or we may crash while generating output from
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose incomplete data */
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose index_mail_body_parsed_cache_message_parts(mail);
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose index_mail_body_parsed_cache_bodystructure(mail, field);
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bosestatic int index_mail_stream_check_failure(struct index_mail *mail)
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose mail_storage_set_critical(mail->mail.mail.box->storage,
ef55b0e470a8fbcf6e6d0a55883145e02a907842Sumit Bose "read(mail, uid=%u) failed: %m", mail->mail.mail.uid);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int index_mail_parse_body(struct index_mail *mail,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_stream_seek(data->stream, data->hdr_size.physical_size);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* bodystructure header is parsed, we want the body's mime
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek headers too */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (index_mail_parse_body_finish(mail, field) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic void index_mail_stream_destroy_callback(struct index_mail *mail)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březinavoid index_mail_set_read_buffer_size(struct mail *_mail, struct istream *input)
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_stream_set_max_buffer_size(input, MAIL_READ_FULL_BLOCK_SIZE);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek block_size = (mail->data.access_part & READ_BODY) != 0 ?
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek MAIL_READ_FULL_BLOCK_SIZE : MAIL_READ_HDR_BLOCK_SIZE;
b010f24f4d96d15c5c85021bb4aa83db25cd3df5Jakub Hrozek i_stream_set_init_buffer_size(input, block_size);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekint index_mail_init_stream(struct index_mail *mail,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (!data->initialized_wrapper_stream && mail->mail.stats_track) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek input = i_stream_create_mail_stats_counter(&mail->mail,
b010f24f4d96d15c5c85021bb4aa83db25cd3df5Jakub Hrozek /* do this only once in case a plugin changes the stream.
b010f24f4d96d15c5c85021bb4aa83db25cd3df5Jakub Hrozek otherwise the check would break. */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (data->hdr_size_set && data->body_size_set) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek data->virtual_size = data->hdr_size.virtual_size +
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek data->physical_size = data->hdr_size.physical_size +
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int index_mail_parse_bodystructure(struct index_mail *mail,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* we have everything parsed already, but just not written to
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek index_mail_body_parsed_cache_bodystructure(mail, field);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* we haven't parsed the header yet */
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidêncio /* if we didn't want to have the body(structure) cached,
5d855b5d546eb995023d80d61433bbe91888dbdfFabiano Fidêncio it's still not written. */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek imap_bodystructure_write(data->parts, str, FALSE);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek imap_bodystructure_write(data->parts, str, TRUE);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekindex_mail_get_plain_bodystructure(struct index_mail *mail, string_t *str,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek str_printfa(str, IMAP_BODY_PLAIN_7BIT_ASCII" %"PRIuUOFF_T" %u",
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek enum mail_fetch_field field, const char **value_r)
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek struct index_mail *mail = (struct index_mail *)_mail;
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek /* 1) use plain-7bit-ascii flag if it exists
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek 2) get BODY if it exists
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek 3) get it using BODYSTRUCTURE if it exists
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek 4) parse body structure, and save BODY/BODYSTRUCTURE
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek depending on what we want cached */
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek index_mail_get_plain_bodystructure(mail, str, FALSE);
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek } else if (index_mail_cache_lookup_field(mail, str,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek else if (index_mail_cache_lookup_field(mail, str,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek /* broken, continue.. */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0 &&
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek index_mail_get_plain_bodystructure(mail, str, TRUE);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina } else if (index_mail_cache_lookup_field(mail, str,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (index_mail_headers_get_envelope(mail) < 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastruct mail *index_mail_get_real_mail(struct mail *mail)
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozekindex_mail_alloc(struct mailbox_transaction_context *t,
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek struct mailbox_header_lookup_ctx *wanted_headers)
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek index_mail_init(mail, t, wanted_fields, wanted_headers);
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek struct mailbox_header_lookup_ctx *_wanted_headers)
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek struct index_header_lookup_ctx *wanted_headers =
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek (struct index_header_lookup_ctx *)_wanted_headers;
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek array_create(&mail->mail.module_contexts, mail->mail.pool,
d0faaf01fd24a935d9779032886d228b3861fa48Jakub Hrozek sizeof(void *), 5);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail->data_pool = pool_alloconly_create("index_mail", 16384);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* If uid == 0 but seq != 0, we came here from saving a (non-mbox)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina message. If that happens, don't bother checking if anything should
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina be cached since it was already checked. Also by now the transaction
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek may have already been rollbacked and seq point to a non-existing
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (message_parser_deinit(&mail->data.parser_ctx, &parts) < 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic void index_mail_reset(struct index_mail *mail)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic void check_envelope(struct index_mail *mail)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->data.access_part & PARSE_HDR) != 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* if "imap.envelope" is cached, that's all we need */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (mail_cache_field_exists(mail->trans->cache_view,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* don't waste time doing full checks for all required
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina headers. assume that if we have "hdr.message-id" cached,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina we don't need to parse the header. */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina cache_field_hdr = mail_cache_register_lookup(mail->mail.mail.box->cache,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina "hdr.message-id");
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_cache_field_exists(mail->trans->cache_view,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_set_seq(struct mail *_mail, uint32_t seq)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct mail_cache_view *cache_view = mail->trans->cache_view;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_lookup_uid(_mail->transaction->view, seq,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (mail_index_view_is_inconsistent(_mail->transaction->view)) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & (MAIL_FETCH_NUL_STATE |
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (void)index_mail_get_fixed_field(mail, MAIL_CACHE_FLAGS,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (data->cache_flags & MAIL_CACHE_FLAG_HAS_NULS) != 0;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (data->cache_flags & MAIL_CACHE_FLAG_HAS_NO_NULS) != 0;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* see if wanted_fields can tell us if we need to read/parse
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina unsigned int cache_field =
e9a2e7afbd09c23dd8748246e09831ed7b17d7c5Thomas Equeter if ((mail->wanted_fields & MAIL_FETCH_VIRTUAL_SIZE) != 0) {
e9a2e7afbd09c23dd8748246e09831ed7b17d7c5Thomas Equeter cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
e9a2e7afbd09c23dd8748246e09831ed7b17d7c5Thomas Equeter if (mail_cache_field_exists(cache_view, seq, cache_field) <= 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) != 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODY) != 0 &&
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) == 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* we need either imap.body or imap.bodystructure */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0 &&
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) == 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina unsigned int cache_field =
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_DATE) != 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina unsigned int cache_field =
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & (MAIL_FETCH_STREAM_HEADER |
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* open stream immediately to set expunged flag if
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina it's already lost */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_STREAM_HEADER) != 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if ((mail->wanted_fields & MAIL_FETCH_STREAM_BODY) != 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* open the stream only if we didn't get here from
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mailbox_save_init() */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina hdr = mail_index_get_header(_mail->box->view);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (_mail->uid != 0 && _mail->uid < hdr->next_uid)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina (void)mail_get_stream(_mail, NULL, NULL, &input);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinabool index_mail_set_uid(struct mail *_mail, uint32_t uid)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
788146c3e3a564f333f39a2fcffccf3012cc2679Jakub Hrozek if (mail_index_lookup_seq(_mail->box->view, uid, &seq)) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_set_uid_cache_updates(struct mail *_mail, bool set)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *mail = (struct index_mail *)_mail;
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina mail->data.no_caching = set || mail->data.forced_no_caching;
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina struct index_mail *mail = (struct index_mail *)_mail;
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina struct mailbox_header_lookup_ctx *headers_ctx =
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina (struct mailbox_header_lookup_ctx *)mail->wanted_headers;
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina if (array_is_created(&mail->header_match_lines))
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březinavoid index_mail_cache_parse_continue(struct mail *_mail)
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina struct index_mail *mail = (struct index_mail *)_mail;
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina while (message_parser_parse_next_block(mail->data.parser_ctx,
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina index_mail_parse_header(block.part, block.hdr, mail);
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březina imap_bodystructure_parse_header(mail->data_pool,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_cache_parse_deinit(struct mail *_mail, time_t received_date,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek struct index_mail *mail = (struct index_mail *)_mail;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* we're going to delete this mail anyway,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina don't bother trying to update cache file */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* This is needed with 0 byte mails to get hdr=NULL call done. */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* this save_date may not be exactly the same as what we get
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina in future, but then again neither mbox nor maildir
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina guarantees it anyway. */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic void index_mail_drop_recent_flag(struct mail *mail)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina hdr = mail_index_get_header(mail->transaction->view);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (hdr->first_recent_uid < first_recent_uid) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_update_header(mail->transaction->itrans,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina offsetof(struct mail_index_header, first_recent_uid),
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina &first_recent_uid, sizeof(first_recent_uid), FALSE);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
35f0f5ff9dac790f6c947190fcdc00d01ae9077cJakub Hrozek flags &= MAIL_FLAGS_NONRECENT | MAIL_INDEX_MAIL_FLAG_BACKEND;
0e238c259c066cf997aaa940d33d6bda96c15925Sumit Bose mail_index_update_flags(mail->transaction->itrans, mail->seq,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *imail = (struct index_mail *)mail;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (array_is_created(&imail->data.keyword_indexes))
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (array_is_created(&imail->data.keywords)) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* clear the keywords array so the next mail_get_keywords()
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina returns the updated keywords. don't free the array, because
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina then any existing mail_get_keywords() return values would
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina point to broken data. this won't leak memory because the
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina array is allocated from mail's memory pool. */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_update_keywords(mail->transaction->itrans, mail->seq,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_update_modseq(struct mail *mail, uint64_t min_modseq)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_update_modseq(mail->transaction->itrans, mail->seq,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_update_uid(struct mail *mail, uint32_t new_uid)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_update_uid(mail->transaction->itrans, mail->seq, new_uid);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (mail_get_special(mail, MAIL_FETCH_GUID, &value) < 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_expunge(mail->transaction->itrans, mail->seq);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mail_index_expunge_guid(mail->transaction->itrans,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavoid index_mail_set_cache_corrupted(struct mail *mail,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina struct index_mail *imail = (struct index_mail *)mail;
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina /* make sure we don't cache invalid values */
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina mail_cache_transaction_reset(imail->trans->cache_trans);
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina "Broken %s for mail UID %u",