doveadm-mail-flags.c revision 00b10a9ca50bca190e72a19aa6571ea612701d82
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "imap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm-mailbox-list-iter.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm-mail-iter.h"
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen#include "doveadm-mail.h"
08b30498acefc69e223baf7eda6429be98cc3a10Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainenstruct flags_cmd_context {
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen struct doveadm_mail_cmd_context ctx;
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen enum modify_type modify_type;
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen enum mail_flags flags;
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen const char *const *keywords;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainencmd_flags_run_box(struct flags_cmd_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mailbox_info *info)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct doveadm_mail_iter *iter;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox *box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail *mail;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_keywords *kw = NULL;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args, FALSE,
d371507847d62ba311b4bcc23d18f45c3d0f1a38Timo Sirainen 0, NULL, &iter) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen box = doveadm_mail_iter_get_mailbox(iter);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ctx->keywords != NULL) {
2d3aac5be07b96f72cf0551fac35ac74a4f07770Timo Sirainen if (mailbox_keywords_create(box, ctx->keywords, &kw) < 0) {
2d3aac5be07b96f72cf0551fac35ac74a4f07770Timo Sirainen i_error("Invalid keywords: %s",
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen mailbox_get_last_error(box, NULL));
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen (void)doveadm_mail_iter_deinit(&iter);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ctx->ctx.exit_code = DOVEADM_EX_NOTPOSSIBLE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen }
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen while (doveadm_mail_iter_next(iter, &mail)) {
a205d315b0978985ba77d871f44e4a98273612e6Timo Sirainen mail_update_flags(mail, ctx->modify_type, ctx->flags);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (kw != NULL)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_update_keywords(mail, ctx->modify_type, kw);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (kw != NULL)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen mailbox_keywords_unref(&kw);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return doveadm_mail_iter_deinit_sync(&iter);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainenstatic int
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainencmd_flags_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
a6a2b38d806f3ab3198160e39240a8200775e525Timo Sirainen{
fb2e0bbb7737f3223b16aa41e4b40fb0cd5f288fTimo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_BOXES |
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen struct doveadm_mailbox_list_iter *iter;
12d34ab79772e0748a1daef30fa749dfe3036608Timo Sirainen const struct mailbox_info *info;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen int ret = 0;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen iter_flags);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (cmd_flags_run_box(ctx, info) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ret = -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } T_END;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ret = -1;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return ret;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen const char *const args[])
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen const char *const *tmp;
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen enum mail_flags flag;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ARRAY_TYPE(const_string) keywords;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (args[0] == NULL || args[1] == NULL) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen switch (ctx->modify_type) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen case MODIFY_ADD:
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen doveadm_mail_help_name("flags add");
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen case MODIFY_REMOVE:
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen doveadm_mail_help_name("flags remove");
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen case MODIFY_REPLACE:
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen doveadm_mail_help_name("flags replace");
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen i_unreached();
e5759add4dc24b96606dccc4a989838e260f2a12Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen p_array_init(&keywords, _ctx->pool, 8);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen const char *str = *tmp;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (str[0] == '\\') {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen flag = imap_parse_system_flag(str);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (flag == 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen i_fatal("Invalid system flag: %s", str);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->flags |= flag;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen } else {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen str = p_strdup(_ctx->pool, str);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen array_append(&keywords, &str, 1);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen array_append_zero(&keywords);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ctx->keywords = array_idx(&keywords, 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen _ctx->search_args = doveadm_mail_build_search_args(args+1);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic struct doveadm_mail_cmd_context *
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainencmd_flag_alloc(enum modify_type modify_type)
821984ecb6c90696f35c32a8dc4c8a60f9e98f99Timo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct flags_cmd_context *ctx;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct flags_cmd_context);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ctx->modify_type = modify_type;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ctx->ctx.v.init = cmd_flags_init;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->ctx.v.run = cmd_flags_run;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return &ctx->ctx;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_add_alloc(void)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return cmd_flag_alloc(MODIFY_ADD);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_remove_alloc(void)
197ad81605dc0f6d2ebc9ad99994db5ca6d76699Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return cmd_flag_alloc(MODIFY_REMOVE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_flags_replace_alloc(void)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return cmd_flag_alloc(MODIFY_REPLACE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_add_ver2 = {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .name = "flags add",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .mail_cmd = cmd_flags_add_alloc,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAMS_START
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_MAIL_COMMON
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAMS_END
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen};
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_remove_ver2 = {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .name = "flags remove",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .mail_cmd = cmd_flags_remove_alloc,
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAMS_START
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_MAIL_COMMON
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAMS_END
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen};
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstruct doveadm_cmd_ver2 doveadm_cmd_flags_replace_ver2 = {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen .name = "flags replace",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen .mail_cmd = cmd_flags_replace_alloc,
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<flags> <search query>",
5363a534097c170ef9cccbdde5ca802f581f5eb7Timo SirainenDOVEADM_CMD_PARAMS_START
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_MAIL_COMMON
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flag", CMD_PARAM_ARRAY, 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "flagstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL|CMD_PARAM_FLAG_DO_NOT_EXPOSE)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAM('\0', "query", CMD_PARAM_ARRAY, CMD_PARAM_FLAG_POSITIONAL)
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenDOVEADM_CMD_PARAMS_END
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen};
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen