doveadm-mail-copymove.c revision a18da4410dcd47ab8d9b40c09a76a54fa55b9c86
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mail-storage.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mail-namespace.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "doveadm-print.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "doveadm-mailbox-list-iter.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "doveadm-mail-iter.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "doveadm-mail.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include <stdio.h>
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct copy_cmd_context {
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct doveadm_mail_cmd_context ctx;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen const char *source_username;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct mail_storage_service_user *source_service_user;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen struct mail_user *source_user;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen const char *destname;
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen bool move;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainencmd_copy_box(struct copy_cmd_context *ctx, struct mailbox *destbox,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_info *info)
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct doveadm_mail_iter *iter;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_transaction_context *desttrans;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_save_context *save_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail *mail;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int ret = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args, 0,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen NULL, &iter) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen /* use a separately committed transaction for each mailbox.
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen this guarantees that mails aren't expunged without actually having
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen been copied. */
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen desttrans = mailbox_transaction_begin(destbox,
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen MAILBOX_TRANSACTION_FLAG_EXTERNAL);
de4d9f77d6378a416c9963963eac5ac18b75ec0bTimo Sirainen
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
de486b59018016977015ef42e6071155b60e82e1Timo Sirainen save_ctx = mailbox_save_alloc(desttrans);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mailbox_save_copy_flags(save_ctx, mail);
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen if (mailbox_copy(&save_ctx, mail) == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ctx->move)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_expunge(mail);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen } else {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_error("Copying message UID %u from '%s' failed: %s",
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen mail->uid, info->vname,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen mailbox_get_last_error(destbox, NULL));
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen ret = -1;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mailbox_transaction_commit(&desttrans) < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_error("Committing %s mails failed: %s",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ctx->move ? "moved" : "copied",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_get_last_error(destbox, NULL));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* rollback expunges */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_mail_iter_deinit_rollback(&iter);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ret = -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (doveadm_mail_iter_deinit_sync(&iter) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ret = -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainencmd_copy_alloc_source_user(struct copy_cmd_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct mail_storage_service_input input;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen const char *error;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen input = ctx->ctx.storage_service_input;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen input.username = ctx->source_username;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &ctx->source_service_user,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &ctx->source_user,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &error) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_fatal("Couldn't lookup user %s: %s", input.username, error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainencmd_copy_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct copy_cmd_context *ctx = (struct copy_cmd_context *)_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct doveadm_mailbox_list_iter *iter;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct mail_user *src_user;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct mail_namespace *ns;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct mailbox *destbox;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const struct mailbox_info *info;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen int ret = 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (ctx->source_username != NULL && ctx->source_user == NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen cmd_copy_alloc_source_user(ctx);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ns = mail_namespace_find(user->namespaces, ctx->destname);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen destbox = mailbox_alloc(ns->list, ctx->destname, MAILBOX_FLAG_SAVEONLY);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (mailbox_open(destbox) < 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_error("Can't open mailbox '%s': %s", ctx->destname,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_get_last_error(destbox, NULL));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_free(&destbox);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen src_user = ctx->source_user != NULL ? ctx->source_user : user;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen iter = doveadm_mailbox_list_iter_init(_ctx, src_user, _ctx->search_args,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen iter_flags);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (cmd_copy_box(ctx, destbox, info) < 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } T_END;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_sync(destbox, 0) < 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_error("Syncing mailbox '%s' failed: %s", ctx->destname,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen mailbox_get_last_error(destbox, NULL));
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_free(&destbox);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return ret;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenstatic void cmd_copy_init(struct doveadm_mail_cmd_context *_ctx,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *const args[])
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct copy_cmd_context *ctx = (struct copy_cmd_context *)_ctx;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const char *destname = args[0], *cmdname = ctx->move ? "move" : "copy";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (destname == NULL || args[1] == NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_mail_help_name(cmdname);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen args++;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (args[0] != NULL && args[1] != NULL &&
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen strcasecmp(args[0], "user") == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((_ctx->service_flags &
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_fatal("Use -u parameter to specify destination user");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen ctx->source_username = p_strdup(_ctx->pool, args[1]);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen args += 2;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen ctx->destname = p_strdup(ctx->ctx.pool, destname);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen _ctx->search_args = doveadm_mail_build_search_args(args);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (ctx->move)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen expunge_search_args_check(ctx->ctx.search_args, cmdname);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstatic void cmd_copy_deinit(struct doveadm_mail_cmd_context *_ctx)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct copy_cmd_context *ctx = (struct copy_cmd_context *)_ctx;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ctx->source_user != NULL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_service_user_free(&ctx->source_service_user);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mail_user_unref(&ctx->source_user);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_copy_alloc(void)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct copy_cmd_context *ctx;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct copy_cmd_context);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->ctx.v.init = cmd_copy_init;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->ctx.v.deinit = cmd_copy_deinit;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->ctx.v.run = cmd_copy_run;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return &ctx->ctx;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_move_alloc(void)
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk{
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk struct copy_cmd_context *ctx;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk ctx = (struct copy_cmd_context *)cmd_copy_alloc();
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk ctx->move = TRUE;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk return &ctx->ctx;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk}
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_copy_ver2 = {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen .name = "copy",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen .mail_cmd = cmd_copy_alloc,
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<destination> [user <source user>] <search query>",
1701e3f91107051b1704721bf1dc1e32491faaf9Timo SirainenDOVEADM_CMD_PARAMS_START
1701e3f91107051b1704721bf1dc1e32491faaf9Timo SirainenDOVEADM_CMD_MAIL_COMMON
1701e3f91107051b1704721bf1dc1e32491faaf9Timo SirainenDOVEADM_CMD_PARAM('\0', "destination-mailbox", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo SirainenDOVEADM_CMD_PARAM('\0', "source-type", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAM('\0', "source-user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
adb6413686e52e00dded4932babcc08ff041876bTimo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
adb6413686e52e00dded4932babcc08ff041876bTimo SirainenDOVEADM_CMD_PARAMS_END
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen};
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_move_ver2 = {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen .name = "move",
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen .mail_cmd = cmd_move_alloc,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<destination> [user <source user>] <search query>",
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAMS_START
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_MAIL_COMMON
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAM('\0', "destination-mailbox", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAM('\0', "source-type", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAM('\0', "source-user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo SirainenDOVEADM_CMD_PARAMS_END
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen};
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen