imapc-mail-fetch.c revision e809db9220c804b16d4d74782433a1075da12274
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "lib.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "str.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "istream.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "imap-arg.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "imap-date.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "imapc-client.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "imapc-mail.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "imapc-storage.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenimapc_mail_prefetch_callback(const struct imapc_command_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen void *context)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *mail = context;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mailbox *mbox =
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (struct imapc_mailbox *)mail->imail.mail.mail.box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_assert(mail->fetch_count > 0);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (--mail->fetch_count == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *const *fetch_mails;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i, count;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fetch_mails = array_get(&mbox->fetch_mails, &count);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 0; i < count; i++) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (fetch_mails[i] == mail) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen array_delete(&mbox->fetch_mails, i, 1);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen break;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_assert(i != count);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->fetching_fields = 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (reply->state == IMAPC_COMMAND_STATE_OK)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else if (reply->state == IMAPC_COMMAND_STATE_NO) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_copy_error_from_reply(mbox->storage, MAIL_ERROR_PARAMS,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen reply);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
e809db9220c804b16d4d74782433a1075da12274Timo Sirainen "imapc: Mail prefetch failed: %s", reply->text_full);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_client_stop(mbox->storage->client);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic int
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenimapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *mail = (struct imapc_mail *)_mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen struct mail_index_view *view;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen string_t *str;
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen uint32_t seq;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (_mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return -1;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* drop any fields that we may already be fetching currently */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fields &= ~mail->fetching_fields;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (fields == 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen /* if we already know that the mail is expunged,
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen don't try to FETCH it */
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen view = mbox->delayed_sync_view != NULL ?
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen mbox->delayed_sync_view : mbox->box.view;
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen if (!mail_index_lookup_seq(view, _mail->uid, &seq) ||
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen mail_index_is_expunged(view, seq)) {
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen mail_set_expunged(_mail);
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen return -1;
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen }
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((fields & MAIL_FETCH_STREAM_BODY) != 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fields |= MAIL_FETCH_STREAM_HEADER;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str = t_str_new(64);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_printfa(str, "UID FETCH %u (", _mail->uid);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_append(str, "INTERNALDATE ");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((fields & MAIL_FETCH_STREAM_BODY) != 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_append(str, "BODY.PEEK[] ");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else if ((fields & MAIL_FETCH_STREAM_HEADER) != 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_append(str, "BODY.PEEK[HEADER] ");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_truncate(str, str_len(str)-1);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen str_append_c(str, ')');
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen pool_ref(mail->imail.mail.pool);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->fetching_fields |= fields;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (mail->fetch_count++ == 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen array_append(&mbox->fetch_mails, &mail, 1);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
86520ddddf88bce4bb27b3c6e3e5a2375d7b2bdbTimo Sirainen imapc_client_mailbox_cmdf(mbox->client_box,
86520ddddf88bce4bb27b3c6e3e5a2375d7b2bdbTimo Sirainen imapc_mail_prefetch_callback,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail, "%1s", str_c(str));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->imail.data.prefetch_sent = TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenbool imapc_mail_prefetch(struct mail *_mail)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *mail = (struct imapc_mail *)_mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen enum mail_fetch_field fields = 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((mail->imail.wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0 &&
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen data->received_date == (time_t)-1)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fields |= MAIL_FETCH_RECEIVED_DATE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (data->stream == NULL && data->access_part != 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((data->access_part & (READ_BODY | PARSE_BODY)) != 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fields |= MAIL_FETCH_STREAM_BODY;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen fields |= MAIL_FETCH_STREAM_HEADER;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (fields != 0) T_BEGIN {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (void)imapc_mail_send_fetch(_mail, fields);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } T_END;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return !mail->imail.data.prefetch_sent;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenstatic bool
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenimapc_mail_have_fields(struct imapc_mail *imail, enum mail_fetch_field fields)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen{
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (imail->imail.data.received_date == (time_t)-1)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen return FALSE;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen fields &= ~MAIL_FETCH_RECEIVED_DATE;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen }
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if ((fields & (MAIL_FETCH_STREAM_HEADER |
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen MAIL_FETCH_STREAM_BODY)) != 0) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (imail->imail.data.stream == NULL)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen return FALSE;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen fields &= ~(MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY);
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen }
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen i_assert(fields == 0);
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen return TRUE;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen}
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenint imapc_mail_fetch(struct mail *_mail, enum mail_fetch_field fields)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mail *imail = (struct imapc_mail *)_mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_storage *storage =
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (struct imapc_storage *)_mail->box->storage;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen int ret;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen T_BEGIN {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ret = imapc_mail_send_fetch(_mail, fields);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } T_END;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (ret < 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return -1;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
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 failed) */
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen while (!imapc_mail_have_fields(imail, fields) && imail->fetch_count > 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_client_run(storage->client);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic bool imapc_find_lfile_arg(const struct imapc_untagged_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imap_arg *arg, int *fd_r)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imap_arg *list;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i, count;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
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
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (farg->parent_arg == arg->parent &&
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imap_arg_get_list_full(arg->parent, &list, &count) &&
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen farg->list_idx < count && &list[farg->list_idx] == arg) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen *fd_r = farg->fd;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return FALSE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenimapc_fetch_stream(struct imapc_mail *mail,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imapc_untagged_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imap_arg *arg, bool body)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct index_mail *imail = &mail->imail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mail *_mail = &imail->mail.mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct istream *input;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen uoff_t size;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *value;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen int fd, ret;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (imail->data.stream != NULL) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!body)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* maybe the existing stream has no body. replace it. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&imail->data.stream);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (arg->type == IMAP_ARG_LITERAL_SIZE) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!imapc_find_lfile_arg(reply, arg, &fd))
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if ((fd = dup(fd)) == -1) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_error("dup() failed: %m");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imail->data.stream = i_stream_create_fd(fd, 0, TRUE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!imap_arg_get_nstring(arg, &value))
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (value == NULL) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail_set_expunged(_mail);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (mail->body == NULL) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->body = buffer_create_dynamic(default_pool,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen arg->str_len + 1);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen buffer_set_used_size(mail->body, 0);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen buffer_append(mail->body, value, arg->str_len);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imail->data.stream = i_stream_create_from_data(mail->body->data,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->body->used);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_set_name(imail->data.stream,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen t_strdup_printf("imapc mail uid=%u", _mail->uid));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen index_mail_set_read_buffer_size(_mail, imail->data.stream);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (imail->mail.v.istream_opened != NULL) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (imail->mail.v.istream_opened(_mail,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen &imail->data.stream) < 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&imail->data.stream);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (body) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ret = i_stream_get_size(imail->data.stream, TRUE, &size);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (ret < 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&imail->data.stream);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_assert(ret != 0);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imail->data.physical_size = size;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* we'll assume that the remote server is working properly and
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen sending CRLF linefeeds */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imail->data.virtual_size = size;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (index_mail_init_stream(imail, NULL, NULL, &input) < 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&imail->data.stream);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenvoid imapc_mail_fetch_update(struct imapc_mail *mail,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imapc_untagged_reply *reply,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imap_arg *args)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imapc_mailbox *mbox =
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen (struct imapc_mailbox *)mail->imail.mail.mail.box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *key, *value;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen unsigned int i;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen time_t t;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen int tz;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen bool match = FALSE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 0; args[i].type != IMAP_ARG_EOL; i += 2) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!imap_arg_get_atom(&args[i], &key) ||
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen args[i+1].type == IMAP_ARG_EOL)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen break;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (strcasecmp(key, "BODY[]") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_fetch_stream(mail, reply, &args[i+1], TRUE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen match = TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (strcasecmp(key, "BODY[HEADER]") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_fetch_stream(mail, reply, &args[i+1], FALSE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen match = TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (strcasecmp(key, "INTERNALDATE") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (imap_arg_get_astring(&args[i+1], &value) &&
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imap_parse_datetime(value, &t, &tz))
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mail->imail.data.received_date = t;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen match = TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!match) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* this is only a FETCH FLAGS update for the wanted mail */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen imapc_client_stop(mbox->storage->client);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}