doveadm-mail-iter.c revision 0dab9cb35a976c49b28a11e28d5570f5191f1a7a
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "lib.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "mail-storage.h"
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include "mail-namespace.h"
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include "mail-search.h"
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include "doveadm-mail.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "doveadm-mail-iter.h"
f1fab7b8210af4ae94453265b607e2dab06789caStephen Gallagher
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagherstruct doveadm_mail_iter {
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct doveadm_mail_cmd_context *ctx;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mail_search_args *search_args;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mailbox *box;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mailbox_transaction_context *t;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mail_search_context *search_ctx;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher bool killed;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher};
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagherint doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
897060147ddea72ecc1e86c6b7b915ff1d462f71Stephen Gallagher const struct mailbox_info *info,
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher struct mail_search_args *search_args,
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher enum mail_fetch_field wanted_fields,
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher const char *const *wanted_headers,
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher bool readonly,
263e4574dacb4b7d2a18d5d42122bf3dce4c45b0Stephen Gallagher struct doveadm_mail_iter **iter_r)
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher{
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher struct doveadm_mail_iter *iter;
263e4574dacb4b7d2a18d5d42122bf3dce4c45b0Stephen Gallagher struct mailbox_header_lookup_ctx *headers_ctx;
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher const char *errstr;
263e4574dacb4b7d2a18d5d42122bf3dce4c45b0Stephen Gallagher enum mail_error error;
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher enum mailbox_flags readonly_flag =
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher readonly ? MAILBOX_FLAG_READONLY : 0;
e9ea1b4e59384cdfe3accdf31e5c579c3dad5591Stephen Gallagher
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher iter = i_new(struct doveadm_mail_iter, 1);
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher iter->ctx = ctx;
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher iter->box = mailbox_alloc(info->ns->list, info->vname,
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher MAILBOX_FLAG_IGNORE_ACLS | readonly_flag);
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher mailbox_set_reason(iter->box, ctx->cmd->name);
1df8e4158e752f1f010394d09e8a5e4f8201fd7eStephen Gallagher iter->search_args = search_args;
if (mailbox_sync(iter->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
errstr = mailbox_get_last_internal_error(iter->box, &error);
if (error == MAIL_ERROR_NOTFOUND) {
/* just ignore this mailbox */
*iter_r = iter;
return 0;
}
i_error("Syncing mailbox %s failed: %s", info->vname, errstr);
doveadm_mail_failed_mailbox(ctx, iter->box);
mailbox_free(&iter->box);
i_free(iter);
return -1;
}
headers_ctx = wanted_headers == NULL || wanted_headers[0] == NULL ?
NULL : mailbox_header_lookup_init(iter->box, wanted_headers);
mail_search_args_init(search_args, iter->box, FALSE, NULL);
iter->t = mailbox_transaction_begin(iter->box, 0, __func__);
iter->search_ctx = mailbox_search_init(iter->t, search_args, NULL,
wanted_fields, headers_ctx);
*iter_r = iter;
return 0;
}
static int
doveadm_mail_iter_deinit_transaction(struct doveadm_mail_iter *iter,
bool commit)
{
int ret = 0;
if (iter->search_ctx != NULL) {
if (mailbox_search_deinit(&iter->search_ctx) < 0) {
i_error("Searching mailbox %s failed: %s",
mailbox_get_vname(iter->box),
mailbox_get_last_internal_error(iter->box, NULL));
ret = -1;
}
}
if (iter->t == NULL)
;
else if (commit) {
if (mailbox_transaction_commit(&iter->t) < 0) {
i_error("Committing mailbox %s failed: %s",
mailbox_get_vname(iter->box),
mailbox_get_last_internal_error(iter->box, NULL));
ret = -1;
}
} else {
mailbox_transaction_rollback(&iter->t);
}
mail_search_args_deinit(iter->search_args);
return ret;
}
static int
doveadm_mail_iter_deinit_full(struct doveadm_mail_iter **_iter,
bool sync, bool commit, bool keep_box)
{
struct doveadm_mail_iter *iter = *_iter;
int ret;
*_iter = NULL;
ret = doveadm_mail_iter_deinit_transaction(iter, commit);
if (ret == 0 && sync) {
ret = mailbox_sync(iter->box, 0);
if (ret < 0) {
i_error("Mailbox %s: Mailbox sync failed: %s",
mailbox_get_vname(iter->box),
mailbox_get_last_internal_error(iter->box, NULL));
}
}
if (ret < 0)
doveadm_mail_failed_mailbox(iter->ctx, iter->box);
else if (iter->killed) {
iter->ctx->exit_code = EX_TEMPFAIL;
ret = -1;
}
if (!keep_box)
mailbox_free(&iter->box);
i_free(iter);
return ret;
}
int doveadm_mail_iter_deinit(struct doveadm_mail_iter **_iter)
{
return doveadm_mail_iter_deinit_full(_iter, FALSE, TRUE, FALSE);
}
int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **_iter)
{
return doveadm_mail_iter_deinit_full(_iter, TRUE, TRUE, FALSE);
}
int doveadm_mail_iter_deinit_keep_box(struct doveadm_mail_iter **iter,
struct mailbox **box_r)
{
*box_r = (*iter)->box;
return doveadm_mail_iter_deinit_full(iter, FALSE, TRUE, TRUE);
}
void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **_iter)
{
(void)doveadm_mail_iter_deinit_full(_iter, FALSE, FALSE, FALSE);
}
bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter,
struct mail **mail_r)
{
if (iter->search_ctx == NULL)
return FALSE;
if (doveadm_is_killed()) {
iter->killed = TRUE;
return FALSE;
}
return mailbox_search_next(iter->search_ctx, mail_r);
}
struct mailbox *doveadm_mail_iter_get_mailbox(struct doveadm_mail_iter *iter)
{
return iter->box;
}