doveadm-mail-flags.c revision a893aaa999856b1ba6e4541890016767aaa283c7
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include "lib.h"
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include "imap-util.h"
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include "mail-storage.h"
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include "doveadm-mailbox-list-iter.h"
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen#include "doveadm-mail-iter.h"
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen#include "doveadm-mail.h"
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen#include <stdio.h>
eb5ea3f4513ff2999892b8d904551f58b74f65f9Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenstruct flags_cmd_context {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct doveadm_mail_cmd_context ctx;
eb5ea3f4513ff2999892b8d904551f58b74f65f9Timo Sirainen enum modify_type modify_type;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen enum mail_flags flags;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen const char *const *keywords;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen};
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenstatic int
503a863a317acba125a4e46435694e35fad769e4Timo Sirainencmd_flags_run_box(struct flags_cmd_context *ctx,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen const struct mailbox_info *info)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen{
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct doveadm_mail_iter *iter;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct mailbox *box;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct mail *mail;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct mail_keywords *kw = NULL;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen 0, NULL, &iter) < 0)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen return -1;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen box = doveadm_mail_iter_get_mailbox(iter);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (ctx->keywords != NULL) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen i_error("Invalid keywords: %s",
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen mailbox_get_last_error(box, NULL));
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen (void)doveadm_mail_iter_deinit(&iter);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen return -1;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen }
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen }
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen mail_update_flags(mail, ctx->modify_type, ctx->flags);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (kw != NULL)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen mail_update_keywords(mail, ctx->modify_type, kw);
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen }
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (kw != NULL)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen mailbox_keywords_unref(&kw);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen return doveadm_mail_iter_deinit(&iter);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen}
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainenstatic int
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainencmd_flags_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen{
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen const enum mailbox_list_iter_flags iter_flags =
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct doveadm_mailbox_list_iter *iter;
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen const struct mailbox_info *info;
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen int ret = 0;
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args,
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen iter_flags);
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen if (cmd_flags_run_box(ctx, info) < 0)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen ret = -1;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen } T_END;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen ret = -1;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen return ret;
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen}
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen const char *const args[])
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen{
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen const char *const *tmp;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen enum mail_flags flag;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen ARRAY_TYPE(const_string) keywords;
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen if (args[0] == NULL || args[1] == NULL) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen switch (ctx->modify_type) {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen case MODIFY_ADD:
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen doveadm_mail_help_name("flags add");
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen case MODIFY_REMOVE:
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen doveadm_mail_help_name("flags remove");
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen case MODIFY_REPLACE:
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen doveadm_mail_help_name("flags replace");
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen }
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen i_unreached();
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen }
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen p_array_init(&keywords, _ctx->pool, 8);
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) {
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen const char *str = *tmp;
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen if (str[0] == '\\') {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen flag = imap_parse_system_flag(str);
c991d8c2c0d5d6c025e24fc00cb06dd61c42456dTimo Sirainen if (flag == 0)
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen i_fatal("Invalid system flag: %s", str);
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen ctx->flags |= flag;
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen } else {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen str = p_strdup(_ctx->pool, str);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen array_append(&keywords, &str, 1);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen }
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen }
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen array_append_zero(&keywords);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen ctx->keywords = array_idx(&keywords, 0);
605eca549c08af753e05c25937bcccd66079c321Timo Sirainen }
605eca549c08af753e05c25937bcccd66079c321Timo Sirainen
605eca549c08af753e05c25937bcccd66079c321Timo Sirainen _ctx->search_args = doveadm_mail_build_search_args(args+1);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen}
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic struct doveadm_mail_cmd_context *
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainencmd_flag_alloc(enum modify_type modify_type)
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen{
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen struct flags_cmd_context *ctx;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct flags_cmd_context);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen ctx->modify_type = modify_type;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen ctx->ctx.v.init = cmd_flags_init;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen ctx->ctx.v.run = cmd_flags_run;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen return &ctx->ctx;
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen}
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_add_alloc(void)
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen{
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen return cmd_flag_alloc(MODIFY_ADD);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen}
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_remove_alloc(void)
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen{
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen return cmd_flag_alloc(MODIFY_REMOVE);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen}
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_replace_alloc(void)
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen{
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen return cmd_flag_alloc(MODIFY_REPLACE);
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen}
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_add_ver2 = {
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen .name = "flags add",
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen .mail_cmd = cmd_flags_add_alloc,
355fe8b5d02904df39e793f66da5432d86649d4aTimo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
355fe8b5d02904df39e793f66da5432d86649d4aTimo SirainenDOVEADM_CMD_PARAMS_START
605eca549c08af753e05c25937bcccd66079c321Timo SirainenDOVEADM_CMD_MAIL_COMMON
605eca549c08af753e05c25937bcccd66079c321Timo SirainenDOVEADM_CMD_PARAM('\0', "flags", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
6646bd844c85d5b27451199d8868b6d2357cd293Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
6646bd844c85d5b27451199d8868b6d2357cd293Timo SirainenDOVEADM_CMD_PARAMS_END
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen};
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_remove_ver2 = {
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen .name = "flags remove",
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen .mail_cmd = cmd_flags_remove_alloc,
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
6646bd844c85d5b27451199d8868b6d2357cd293Timo SirainenDOVEADM_CMD_PARAMS_START
6646bd844c85d5b27451199d8868b6d2357cd293Timo SirainenDOVEADM_CMD_MAIL_COMMON
e20e638805c4bd54e039891a3e92760b1dfa189aTimo SirainenDOVEADM_CMD_PARAM('\0', "flags", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
e20e638805c4bd54e039891a3e92760b1dfa189aTimo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
6646bd844c85d5b27451199d8868b6d2357cd293Timo SirainenDOVEADM_CMD_PARAMS_END
6646bd844c85d5b27451199d8868b6d2357cd293Timo Sirainen};
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen
503a863a317acba125a4e46435694e35fad769e4Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_replace_ver2 = {
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen .name = "flags replace",
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen .mail_cmd = cmd_flags_replace_alloc,
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
503a863a317acba125a4e46435694e35fad769e4Timo SirainenDOVEADM_CMD_PARAMS_START
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo SirainenDOVEADM_CMD_MAIL_COMMON
503a863a317acba125a4e46435694e35fad769e4Timo SirainenDOVEADM_CMD_PARAM('\0', "flags", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
8d80659e504ffb34bb0c6a633184fece35751b18Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
e8ecd8f24ffc612f5d0be10f7931ac619f1eab88Timo SirainenDOVEADM_CMD_PARAMS_END
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen};
503a863a317acba125a4e46435694e35fad769e4Timo Sirainen