pop3c-sync.c revision d546cddd14aa72823a1104e371527ae0a8a99e00
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
e05a4c4136fec723f019bee8383103080203f127Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "bsearch-insert-pos.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "strnum.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "index-mail.h"
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen#include "pop3c-client.h"
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen#include "pop3c-storage.h"
e05a4c4136fec723f019bee8383103080203f127Timo Sirainen#include "pop3c-sync.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct pop3c_sync_msg {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t seq;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen const char *uidl;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen};
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo SirainenARRAY_DEFINE_TYPE(pop3c_sync_msg, struct pop3c_sync_msg);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenint pop3c_sync_get_uidls(struct pop3c_mailbox *mbox)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen{
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen ARRAY_TYPE(const_string) uidls;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct istream *input;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen const char *error, *cline;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen char *line, *p;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen unsigned int seq, line_seq;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (mbox->msg_uidls != NULL)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return 0;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if ((pop3c_client_get_capabilities(mbox->client) &
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen POP3C_CAPABILITY_UIDL) == 0) {
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen mail_storage_set_error(mbox->box.storage,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen MAIL_ERROR_NOTPOSSIBLE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "UIDLs not supported by server");
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return -1;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (pop3c_client_cmd_stream(mbox->client, "UIDL\r\n",
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &input, &error) < 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mail_storage_set_critical(mbox->box.storage,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen "UIDL failed: %s", error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mbox->uidl_pool = pool_alloconly_create("POP3 UIDLs", 1024*32);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen p_array_init(&uidls, mbox->uidl_pool, 64); seq = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p = strchr(line, ' ');
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (p == NULL) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen mail_storage_set_critical(mbox->box.storage,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen "Invalid UIDL line: %s", line);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen break;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen *p++ = '\0';
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (str_to_uint(line, &line_seq) < 0 || line_seq != seq) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mail_storage_set_critical(mbox->box.storage,
01937f71b3ae0d5b30b813372f44a3e7e86c89dcTimo Sirainen "Unexpected UIDL seq: %s != %u", line, seq);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen break;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen cline = p_strdup(mbox->uidl_pool, p);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen array_append(&uidls, &cline, 1);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen i_stream_destroy(&input);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (line != NULL) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen pool_unref(&mbox->uidl_pool);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return -1;
a341c4cdbd4b93ba479f465ad3f569dc82f57312Timo Sirainen }
013e3b3942e9550fde619a0b3ce6bdd04edc4268Timo Sirainen if (seq == 0) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen /* make msg_uidls non-NULL */
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen array_append_zero(&uidls);
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen }
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen mbox->msg_uidls = array_idx(&uidls, 0);
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen mbox->msg_count = seq;
9293bf90039454f47e94e4ba3722a775cfa7d25cTimo Sirainen return 0;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenint pop3c_sync_get_sizes(struct pop3c_mailbox *mbox)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen{
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen struct istream *input;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen const char *error;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen char *line, *p;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen unsigned int seq, line_seq;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen i_assert(mbox->msg_sizes == NULL);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (mbox->msg_uidls == NULL) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (pop3c_sync_get_uidls(mbox) < 0)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return -1;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (mbox->msg_count == 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mbox->msg_sizes = i_new(uoff_t, 1);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return 0;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (pop3c_client_cmd_stream(mbox->client, "LIST\r\n",
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen &input, &error) < 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mail_storage_set_critical(mbox->box.storage,
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen "LIST failed: %s", error);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen return -1;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen }
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen mbox->msg_sizes = i_new(uoff_t, mbox->msg_count); seq = 0;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (++seq > mbox->msg_count) {
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen mail_storage_set_critical(mbox->box.storage,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen "Too much data in LIST: %s", line);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen break;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen p = strchr(line, ' ');
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (p == NULL) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen mail_storage_set_critical(mbox->box.storage,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen "Invalid LIST line: %s", line);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen break;
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen }
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen *p++ = '\0';
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen if (str_to_uint(line, &line_seq) < 0 || line_seq != seq) {
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen mail_storage_set_critical(mbox->box.storage,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen "Unexpected LIST seq: %s != %u", line, seq);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen break;
4d2211dac61c615c5bdfd501ea54d46c89d41b0fTimo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (str_to_uoff(p, &mbox->msg_sizes[seq-1]) < 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mail_storage_set_critical(mbox->box.storage,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "Invalid LIST size: %s", p);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen break;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_stream_destroy(&input);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (line != NULL) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_free_and_null(mbox->msg_sizes);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return -1;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen return 0;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenpop3c_get_local_msgs(pool_t pool, ARRAY_TYPE(pop3c_sync_msg) *local_msgs,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t messages_count,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_view *cache_view,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen unsigned int cache_idx)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen string_t *str = t_str_new(128);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct pop3c_sync_msg msg;
741d705983e10046f07ef372b760bcdd169b068aTimo Sirainen uint32_t seq;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen memset(&msg, 0, sizeof(msg));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (seq = 1; seq <= messages_count; seq++) {
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen str_truncate(str, 0);
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen if (mail_cache_lookup_field(cache_view, str, seq,
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen cache_idx) > 0)
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen msg.uidl = p_strdup(pool, str_c(str));
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen msg.seq = seq;
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen array_idx_set(local_msgs, seq-1, &msg);
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen }
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen}
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainenstatic void
pop3c_get_remote_msgs(ARRAY_TYPE(pop3c_sync_msg) *remote_msgs,
struct pop3c_mailbox *mbox)
{
struct pop3c_sync_msg *msg;
uint32_t seq;
for (seq = 1; seq <= mbox->msg_count; seq++) {
msg = array_append_space(remote_msgs);
msg->seq = seq;
msg->uidl = mbox->msg_uidls[seq-1];
}
}
static int pop3c_sync_msg_uidl_cmp(const struct pop3c_sync_msg *msg1,
const struct pop3c_sync_msg *msg2)
{
return null_strcmp(msg1->uidl, msg2->uidl);
}
static void
pop3c_sync_messages(struct pop3c_mailbox *mbox,
struct mail_index_view *sync_view,
struct mail_index_transaction *sync_trans,
struct mail_cache_view *cache_view)
{
struct index_mailbox_context *ibox =
INDEX_STORAGE_CONTEXT(&mbox->box);
const struct mail_index_header *hdr;
struct mail_cache_transaction_ctx *cache_trans;
ARRAY_TYPE(pop3c_sync_msg) local_msgs, remote_msgs;
const struct pop3c_sync_msg *lmsg, *rmsg;
uint32_t seq1, seq2, next_uid;
unsigned int lidx, ridx, lcount, rcount;
unsigned int cache_idx = ibox->cache_fields[MAIL_CACHE_POP3_UIDL].idx;
pool_t pool;
i_assert(mbox->msg_uids == NULL);
/* set our uidvalidity */
hdr = mail_index_get_header(sync_view);
if (hdr->uid_validity == 0) {
uint32_t uid_validity = ioloop_time;
mail_index_update_header(sync_trans,
offsetof(struct mail_index_header, uid_validity),
&uid_validity, sizeof(uid_validity), TRUE);
}
pool = pool_alloconly_create(MEMPOOL_GROWING"pop3c sync", 10240);
p_array_init(&local_msgs, pool, hdr->messages_count);
pop3c_get_local_msgs(pool, &local_msgs, hdr->messages_count,
cache_view, cache_idx);
p_array_init(&remote_msgs, pool, mbox->msg_count);
pop3c_get_remote_msgs(&remote_msgs, mbox);
/* sort the messages by UIDLs, because some servers reorder messages */
array_sort(&local_msgs, pop3c_sync_msg_uidl_cmp);
array_sort(&remote_msgs, pop3c_sync_msg_uidl_cmp);
/* skip over existing messages with matching UIDLs and expunge the ones
that no longer exist in remote. (+1 to avoid malloc(0) assert) */
mbox->msg_uids = i_new(uint32_t, mbox->msg_count + 1);
cache_trans = mail_cache_get_transaction(cache_view, sync_trans);
lmsg = array_get(&local_msgs, &lcount);
rmsg = array_get(&remote_msgs, &rcount);
next_uid = hdr->next_uid;
lidx = ridx = 0;
while (lidx < lcount || ridx < rcount) {
uint32_t lseq = lidx < lcount ? lmsg[lidx].seq : 0;
uint32_t rseq = ridx < rcount ? rmsg[ridx].seq : 0;
int ret;
if (lidx >= lcount)
ret = 1;
else if (ridx >= rcount || lmsg[lidx].uidl == NULL)
ret = -1;
else
ret = strcmp(lmsg[lidx].uidl, rmsg[ridx].uidl);
if (ret < 0) {
/* message expunged in remote, or we didn't have a
local message's UIDL in cache. */
mail_index_expunge(sync_trans, lseq);
lidx++;
} else if (ret > 0) {
/* new message in remote */
i_assert(mbox->msg_uids[rseq-1] == 0);
mbox->msg_uids[rseq-1] = next_uid;
mail_index_append(sync_trans, next_uid++, &lseq);
mail_cache_add(cache_trans, lseq, cache_idx,
rmsg[ridx].uidl,
strlen(rmsg[ridx].uidl)+1);
ridx++;
} else {
/* UIDL matched */
i_assert(mbox->msg_uids[rseq-1] == 0);
mail_index_lookup_uid(sync_view, lseq,
&mbox->msg_uids[rseq-1]);
lidx++;
ridx++;
}
}
/* mark the newly seen messages as recent */
if (mail_index_lookup_seq_range(sync_view, hdr->first_recent_uid,
hdr->next_uid, &seq1, &seq2))
mailbox_recent_flags_set_seqs(&mbox->box, sync_view, seq1, seq2);
pool_unref(&pool);
}
int pop3c_sync(struct pop3c_mailbox *mbox)
{
struct mail_index_sync_ctx *index_sync_ctx;
struct mail_index_view *sync_view, *trans_view;
struct mail_index_transaction *sync_trans;
struct mail_index_sync_rec sync_rec;
struct mail_cache_view *cache_view = NULL;
enum mail_index_sync_flags sync_flags;
unsigned int idx;
string_t *str;
const char *reply;
int ret;
bool deletions = FALSE;
if (pop3c_sync_get_uidls(mbox) < 0)
return -1;
sync_flags = index_storage_get_sync_flags(&mbox->box) |
MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
ret = mail_index_sync_begin(mbox->box.index, &index_sync_ctx,
&sync_view, &sync_trans, sync_flags);
if (ret <= 0) {
if (ret < 0)
mailbox_set_index_error(&mbox->box);
return ret;
}
if (mbox->msg_uids == NULL) {
trans_view = mail_index_transaction_open_updated_view(sync_trans);
cache_view = mail_cache_view_open(mbox->box.cache, trans_view);
pop3c_sync_messages(mbox, sync_view, sync_trans, cache_view);
}
/* mark expunges messages as deleted in this pop3 session,
if those exist */
str = t_str_new(32);
while (mail_index_sync_next(index_sync_ctx, &sync_rec)) {
if (sync_rec.type != MAIL_INDEX_SYNC_TYPE_EXPUNGE)
continue;
if (!bsearch_insert_pos(&sync_rec.uid1, mbox->msg_uids,
mbox->msg_count, sizeof(uint32_t),
uint32_cmp, &idx)) {
/* no such messages in this session */
continue;
}
for (; idx < mbox->msg_count; idx++) {
i_assert(mbox->msg_uids[idx] >= sync_rec.uid1);
if (mbox->msg_uids[idx] > sync_rec.uid2)
break;
str_truncate(str, 0);
str_printfa(str, "DELE %u\r\n", idx+1);
pop3c_client_cmd_line_async_nocb(mbox->client, str_c(str));
deletions = TRUE;
}
}
if (mail_index_sync_commit(&index_sync_ctx) < 0) {
mailbox_set_index_error(&mbox->box);
return -1;
}
if (cache_view != NULL) {
mail_cache_view_close(&cache_view);
mail_index_view_close(&trans_view);
}
if (deletions) {
if (pop3c_client_cmd_line(mbox->client, "QUIT\r\n",
&reply) < 0) {
mail_storage_set_error(mbox->box.storage,
MAIL_ERROR_TEMP, reply);
return -1;
}
}
return 0;
}
struct mailbox_sync_context *
pop3c_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
{
struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)box;
int ret = 0;
if (!box->opened) {
if (mailbox_open(box) < 0)
ret = -1;
} else {
if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
mbox->msg_uidls == NULL) {
/* FIXME: reconnect */
}
}
if (ret == 0)
ret = pop3c_sync(mbox);
return index_mailbox_sync_init(box, flags, ret < 0);
}