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