imapc-mail-fetch.c revision 8e1dbcb9b249c37d00b420705777b103ffa6145d
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2011-2013 Dovecot authors, see the included COPYING file */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenimapc_mail_prefetch_callback(const struct imapc_command_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (struct imapc_mailbox *)mail->imail.mail.mail.box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i, count;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fetch_mails = array_get(&mbox->fetch_mails, &count);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 0; i < count; i++) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_copy_error_from_reply(mbox->storage, MAIL_ERROR_PARAMS,
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainen } else if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED) {
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainen /* The disconnection message was already logged */
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainen mail_storage_set_internal_error(&mbox->storage->storage);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
e809db9220c804b16d4d74782433a1075da12274Timo Sirainen "imapc: Mail prefetch failed: %s", reply->text_full);
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen imapc_client_stop(mbox->storage->client->client);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenimapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *mail = (struct imapc_mail *)_mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (_mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* drop any fields that we may already be fetching currently */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen /* if we already know that the mail is expunged,
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen don't try to FETCH it */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen if (!mail_index_lookup_seq(view, _mail->uid, &seq) ||
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen /* opened as save-only. we'll need to fetch the mail,
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen so actually SELECT/EXAMINE the mailbox */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_printfa(str, "UID FETCH %u (", _mail->uid);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen cmd = imapc_client_mailbox_cmd(mbox->client_box,
f87844c400cf9741abad57d9815121d0738a738fTimo Sirainen imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenstatic void imapc_mail_cache_get(struct imapc_mail *mail,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *mail = (struct imapc_mail *)_mail;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen imapc_mail_cache_get(mail, &mbox->prev_mail_cache);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0 &&
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen if ((data->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE) != 0 &&
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if ((data->wanted_fields & MAIL_FETCH_GUID) != 0 &&
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen data->guid == NULL && mbox->guid_fetch_field_name != NULL)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (data->stream == NULL && data->access_part != 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((data->access_part & (READ_BODY | PARSE_BODY)) != 0)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenimapc_mail_have_fields(struct imapc_mail *imail, enum mail_fetch_field fields)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (imail->imail.data.received_date == (time_t)-1)
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen if ((fields & MAIL_FETCH_PHYSICAL_SIZE) != 0) {
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen if (imail->imail.data.physical_size == (uoff_t)-1)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen fields &= ~(MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenint imapc_mail_fetch(struct mail *_mail, enum mail_fetch_field fields)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *imail = (struct imapc_mail *)_mail;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen "Message GUID not available in this server");
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen /* we'll continue waiting until we've got all the fields we wanted,
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen or until all FETCH replies have been received (i.e. some FETCHes
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen while (!imapc_mail_have_fields(imail, fields) && imail->fetch_count > 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic bool imapc_find_lfile_arg(const struct imapc_untagged_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i, count;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 0; i < reply->file_args_count; i++) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imapc_arg_file *farg = &reply->file_args[i];
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imap_arg_get_list_full(arg->parent, &list, &count) &&
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen farg->list_idx < count && &list[farg->list_idx] == arg) {
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainenstatic void imapc_stream_filter(struct istream **input)
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen static const char *imapc_hide_headers[] = {
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen /* Added by MS Exchange 2010 when \Flagged flag is set.
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen This violates IMAP guarantee of messages being immutable. */
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen "X-Message-Flag"
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen filter_input = i_stream_create_header_filter(*input,
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen imapc_hide_headers, N_ELEMENTS(imapc_hide_headers),
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainenvoid imapc_mail_init_stream(struct imapc_mail *mail, bool have_body)
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen t_strdup_printf("imapc mail uid=%u", _mail->uid));
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen index_mail_set_read_buffer_size(_mail, imail->data.stream);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen ret = i_stream_get_size(imail->data.stream, TRUE, &size);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* we'll assume that the remote server is working properly and
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen sending CRLF linefeeds */
7c3f90095b4168d89a268ac1ec820c5925d48fd3Timo Sirainen imail->data.stream_has_only_header = !have_body;
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen if (index_mail_init_stream(imail, NULL, NULL, &input) < 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* maybe the existing stream has no body. replace it. */
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen imail->data.stream = i_stream_create_fd(fd, 0, FALSE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->body = buffer_create_dynamic(default_pool,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen buffer_append(mail->body, value, arg->str_len);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imail->data.stream = i_stream_create_from_data(mail->body->data,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenvoid imapc_mail_fetch_update(struct imapc_mail *mail,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (struct imapc_mailbox *)mail->imail.mail.mail.box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 0; args[i].type != IMAP_ARG_EOL; i += 2) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_fetch_stream(mail, reply, &args[i+1], TRUE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (strcasecmp(key, "BODY[HEADER]") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_fetch_stream(mail, reply, &args[i+1], FALSE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (strcasecmp(key, "INTERNALDATE") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (imap_arg_get_astring(&args[i+1], &value) &&
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen } else if (strcasecmp(key, "RFC822.SIZE") == 0) {
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen } else if (strcasecmp(key, "X-GM-MSGID") == 0 ||
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if (imap_arg_get_astring(&args[i+1], &value)) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* this is only a FETCH FLAGS update for the wanted mail */