imap-fetch.c revision efe78d3ba24fc866af1c79b9223dc0809ba26cad
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "\"text\" \"plain\" NIL NIL NIL \"7bit\" 0 0"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic ARRAY(struct imap_fetch_handler) fetch_handlers;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic int imap_fetch_handler_cmp(const struct imap_fetch_handler *h1,
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenvoid imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen array_append(&fetch_handlers, handlers, count);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen array_sort(&fetch_handlers, imap_fetch_handler_cmp);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenimap_fetch_handler_bsearch(const char *name, const struct imap_fetch_handler *h)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenbool imap_fetch_init_handler(struct imap_fetch_init_context *init_ctx)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const char *lookup_name, *p;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen for (p = init_ctx->name; i_isalnum(*p) || *p == '-'; p++) ;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lookup_name = t_strdup_until(init_ctx->name, p);
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen handler = array_bsearch(&fetch_handlers, lookup_name,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen init_ctx->error = t_strdup_printf("Unknown parameter: %s",
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainenvoid imap_fetch_init_nofail_handler(struct imap_fetch_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen bool (*init)(struct imap_fetch_init_context *))
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainenint imap_fetch_att_list_parse(struct client *client, pool_t pool,
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch const char **error_r)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen const char *str;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen init_ctx.fetch_ctx = imap_fetch_alloc(client, pool);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen while (imap_arg_get_atom(init_ctx.args, &str)) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen *error_r = t_strconcat("Invalid fetch-att list: ",
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen *error_r = "fetch-att list contains non-atoms.";
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenimap_fetch_alloc(struct client *client, pool_t pool)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = p_new(pool, struct imap_fetch_context, 1);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainenvoid imap_fetch_add_handler(struct imap_fetch_init_context *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* partially because of broken clients, but also partially because
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen it potentially can make client implementations faster, we have a
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen buffered parameter which basically means that the handler promises
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen to write the output in fetch_ctx->state.cur_str. The cur_str is then
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen sent to client before calling any non-buffered handlers.
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen We try to keep the handler registration order the same as the
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen client requested them. This is especially useful to get UID
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen returned first, which some clients rely on..
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen const struct imap_fetch_context_handler *ctx_handler;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* don't allow duplicate handlers */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen array_foreach(&ctx->fetch_ctx->handlers, ctx_handler) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen h.buffered = (flags & IMAP_FETCH_HANDLER_FLAG_BUFFERED) != 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen h.want_deinit = (flags & IMAP_FETCH_HANDLER_FLAG_WANT_DEINIT) != 0;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen array_append(&ctx->fetch_ctx->handlers, &h, 1);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen ctx->fetch_ctx->buffered_handlers_count, &h, 1);
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen const struct imap_fetch_qresync_args *qresync_args,
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen unsigned int i, count;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen seqs = array_get(qresync_args->qresync_sample_seqset, &count);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen uids = array_idx(qresync_args->qresync_sample_uidset, 0);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_assert(array_count(qresync_args->qresync_sample_uidset) == count);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_get_open_status(box, STATUS_MESSAGES, &status);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* FIXME: we could do removals from the middle as well */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < count && seqs[i] <= status.messages; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen seq_range_array_remove_range(expunged_uids, 1, uids[i-1]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct imap_fetch_qresync_args *qresync_args,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen uid_filter = array_get(uid_filter_arr, &count);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* search UIDs only in given range */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen search_args->args = p_new(search_args->pool, struct mail_search_arg, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_array_init(&search_args->args->value.seqset, count);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen array_append_array(&search_args->args->value.seqset, uid_filter_arr);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen search_ctx = mailbox_search_init(trans, search_args, NULL, 0, NULL);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen while (mailbox_search_next(search_ctx, &mail)) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen else if (++i < count)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* next_uid .. mail->uid-1 are expunged */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (++i < count)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen seq_range_array_add_range(expunged_uids, next_uid,
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen for (; i < count; i++) {
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen seq_range_array_add_range(expunged_uids, uid_filter[i].seq1,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mailbox_get_open_status(box, STATUS_UIDNEXT, &status);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen seq_range_array_remove_range(expunged_uids, status.uidnext,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret == 0 && qresync_args->qresync_sample_seqset != NULL &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_is_created(qresync_args->qresync_sample_seqset))
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen expunges_drop_known(box, qresync_args, trans, expunged_uids);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenint imap_fetch_send_vanished(struct client *client, struct mailbox *box,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const struct imap_fetch_qresync_args *qresync_args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_search_arg *uidarg = search_args->args;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mail_search_arg *modseqarg = uidarg->next;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_array_init(&expunged_uids_range, array_count(uid_filter));
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (!mailbox_get_expunged_uids(box, modseq, uid_filter, &expunged_uids_range)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* return all expunged UIDs */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (get_expunges_fallback(box, qresync_args, uid_filter,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen imap_write_seq_range(str, &expunged_uids_range);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen o_stream_nsend(client->output, str_data(str), str_len(str));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void imap_fetch_init(struct imap_fetch_context *ctx)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (ctx->flags_update_seen && !ctx->flags_have_handler) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen imap_fetch_init_nofail_handler(ctx, imap_fetch_flags_init);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen (MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenvoid imap_fetch_begin(struct imap_fetch_context *ctx, struct mailbox *box,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers = NULL;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen const char *const *headers;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen wanted_headers = mailbox_header_lookup_init(box, headers);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->state.trans = mailbox_transaction_begin(box,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mailbox_search_init(ctx->state.trans, search_args, NULL,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen ctx->state.cur_str = str_new(default_pool, 8192);
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainenstatic int imap_fetch_flush_buffer(struct imap_fetch_context *ctx)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const unsigned char *data;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* there's an extra space at the end if we added any fetch items
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (o_stream_send(ctx->client->output, data, len) < 0)
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainenstatic int imap_fetch_send_nil_reply(struct imap_fetch_context *ctx)
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen const struct imap_fetch_context_handler *handler;
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen handler = array_idx(&ctx->handlers, ctx->state.cur_handler);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int imap_fetch_more_int(struct imap_fetch_context *ctx, bool cancel)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct imap_fetch_context_handler *handlers;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen unsigned int count;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* not an error, just lost it. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen for (; state->cur_handler < count; state->cur_handler++) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* first non-buffered handler.
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen flush the buffer. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* not an error, just lost it. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* no non-buffered handlers */
1503ac7619d97193d6690292b5f9523552c5d6ceTimo Sirainenint imap_fetch_more(struct imap_fetch_context *ctx,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(ctx->client->output_cmd_lock == NULL ||
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* nothing can be sent until FETCH is finished */
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen if (cmd->cancel && ctx->client->output_cmd_lock != NULL) {
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen /* canceling didn't really work. we must not output
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainen anything anymore. */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen client_disconnect(ctx->client, "Failed to cancel FETCH");
3c652e7a569c2623d22b4ab30279aebddce4d396Timo Sirainenint imap_fetch_more_no_lock_update(struct imap_fetch_context *ctx)
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen "NOTIFY failed in the middle of FETCH reply");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint imap_fetch_end(struct imap_fetch_context *ctx)
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen /* we've flushed an empty "FETCH (" reply so
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen far. we can't take it back, but RFC 3501
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doesn't allow returning empty "FETCH ()"
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen either, so just add the current message's
20dca965f48c1d7600a268d380c0b5fb5f1011d5Timo Sirainen UID there. */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (mailbox_search_deinit(&state->search_ctx) < 0)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* even if something failed, we want to commit changes to
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch cache, as well as possible \Seen flag changes for FETCH
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen replies we returned so far. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox_transaction_commit(&state->trans) < 0)
c56500d4363beba4ffa954069ab30f4401849156Timo Sirainenvoid imap_fetch_free(struct imap_fetch_context **_ctx)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen const struct imap_fetch_context_handler *handler;
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen handler->handler(ctx, NULL, handler->context);
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainenstatic int fetch_body(struct imap_fetch_context *ctx, struct mail *mail,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (mail_get_special(mail, MAIL_FETCH_IMAP_BODY, &body) < 0)
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen if (o_stream_send(ctx->client->output, "BODY (", 6) < 0 ||
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen o_stream_send_str(ctx->client->output, body) < 0 ||
303e375b7e76278f4ec541f49af0476d3e4ee710Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool fetch_body_init(struct imap_fetch_init_context *ctx)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen imap_fetch_add_handler(ctx, 0, "("BODY_NIL_REPLY")",
1388b590dbd85245b591346f860bc1319953318aTimo Sirainenstatic int fetch_bodystructure(struct imap_fetch_context *ctx,
12797080b552a3c1727b73b61cc7427bec0c7472Timo Sirainen if (mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE,
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (o_stream_send(ctx->client->output, "BODYSTRUCTURE (", 15) < 0 ||
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen o_stream_send_str(ctx->client->output, bodystructure) < 0 ||
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainenstatic bool fetch_bodystructure_init(struct imap_fetch_init_context *ctx)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen imap_fetch_add_handler(ctx, 0, "("BODY_NIL_REPLY" NIL NIL NIL NIL)",
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_IMAP_ENVELOPE, &envelope) < 0)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0 ||
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen o_stream_send_str(ctx->client->output, envelope) < 0 ||
0992011130e9d0a498ca860ddbe4028398a530c5Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic bool fetch_envelope_init(struct imap_fetch_init_context *ctx)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen imap_fetch_add_handler(ctx, 0, ENVELOPE_NIL_REPLY,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *const *keywords;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0 &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* Add \Seen flag */
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
3c932c0a21349f23dd38c50c12b3a24717dfbc28Timo Sirainen } else if (ctx->flags_show_only_seen_changes) {
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
1cb065514fcfe00b684ee274239e3f0390c7fc47Timo Sirainen imap_write_flags(ctx->state.cur_str, flags, keywords);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenbool imap_fetch_flags_init(struct imap_fetch_init_context *ctx)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_FLAGS;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic int fetch_internaldate(struct imap_fetch_context *ctx, struct mail *mail,
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen str_printfa(ctx->state.cur_str, "INTERNALDATE \"%s\" ",
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainenstatic bool fetch_internaldate_init(struct imap_fetch_init_context *ctx)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "\"01-Jan-1970 00:00:00 +0000\"",
1388b590dbd85245b591346f860bc1319953318aTimo Sirainenstatic int fetch_modseq(struct imap_fetch_context *ctx, struct mail *mail,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->client->highest_fetch_modseq < modseq)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen str_printfa(ctx->state.cur_str, "MODSEQ (%llu) ",
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen (unsigned long long)modseq);
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainenbool imap_fetch_modseq_init(struct imap_fetch_init_context *ctx)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen if (ctx->fetch_ctx->client->nonpermanent_modseqs) {
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ctx->error = "FETCH MODSEQ can't be used with non-permanent modseqs";
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (void)client_enable(ctx->fetch_ctx->client, MAILBOX_FEATURE_CONDSTORE);
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainenstatic int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail,
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen str_printfa(ctx->state.cur_str, "UID %u ", mail->uid);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenbool imap_fetch_uid_init(struct imap_fetch_init_context *ctx)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainenstatic int fetch_guid(struct imap_fetch_context *ctx, struct mail *mail,
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_GUID, &value) < 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_append_astring(ctx->state.cur_str, value);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenstatic bool fetch_guid_init(struct imap_fetch_init_context *ctx)
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_GUID;
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic int fetch_x_mailbox(struct imap_fetch_context *ctx, struct mail *mail,
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen if (mail_get_special(mail, MAIL_FETCH_MAILBOX_NAME, &name) < 0)
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen i_panic("FETCH: Mailbox name not UTF-8: %s", name);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen imap_append_astring(ctx->state.cur_str, str_c(mutf7_name));
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic bool fetch_x_mailbox_init(struct imap_fetch_init_context *ctx)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic int fetch_x_real_uid(struct imap_fetch_context *ctx, struct mail *mail,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (mail_get_backend_mail(mail, &real_mail) < 0)
49fd8c950e3da2ed32506e617a4b1480a07f874fTimo Sirainen str_printfa(ctx->state.cur_str, "X-REAL-UID %u ", real_mail->uid);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic bool fetch_x_real_uid_init(struct imap_fetch_init_context *ctx)
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenstatic int fetch_x_savedate(struct imap_fetch_context *ctx, struct mail *mail,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen str_printfa(ctx->state.cur_str, "X-SAVEDATE \"%s\" ",
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainenstatic bool fetch_x_savedate_init(struct imap_fetch_init_context *ctx)
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen ctx->fetch_ctx->fetch_data |= MAIL_FETCH_SAVE_DATE;
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen "\"01-Jan-1970 00:00:00 +0000\"",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic const struct imap_fetch_handler
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen { "BODYSTRUCTURE", fetch_bodystructure_init },