doveadm-mail.c revision 97437f768d1a3e6134fed1971202803fd250eef2
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_storage_get_last_error(ns->storage, NULL));
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen i_fatal("Can't find namespace for mailbox %s", mailbox);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen i_error("Opening mailbox %s failed: %s", orig_mailbox,
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen mail_storage_get_last_error(mailbox_get_storage(box),
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenint doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mailbox_find_and_open(user, mailbox, box_r) < 0)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_error("Syncing mailbox %s failed: %s", mailbox,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen mail_storage_get_last_error(mailbox_get_storage(*box_r),
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainendoveadm_mail_build_search_args(const char *const args[])
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen parser = mail_search_parser_init_cmdline(args);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_search_build(mail_search_register_get_human(),
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainenstatic void cmd_force_resync_run(struct doveadm_mail_cmd_context *_ctx,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenstatic void cmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const args[])
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->mailbox = p_strdup(ctx->ctx.pool, mailbox);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct force_resync_cmd_context);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const struct mail_storage_service_input *input,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char **error_r)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct mail_storage_service_user *service_user;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username));
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, input,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ret = mail_storage_service_next(ctx->storage_service, service_user,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_storage_service_user_free(&service_user);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen mail_storage_service_user_free(&service_user);
6825360d446542046757b06064282301c4c6b27cTimo Sirainendoveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen enum mail_storage_service_flags service_flags)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_fatal("USER environment is missing and -u option not used");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen else if (ret == 0)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_storage_service_deinit(&ctx->storage_service);
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen enum mail_storage_service_flags service_flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen unsigned int user_idx, user_count, interval, n;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen user_count = mail_storage_service_all_init(ctx->storage_service);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen for (interval = 10; n > 0 && interval < 1000; interval *= 10)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (ret == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_warning("Killed with signal %d", killed_signo);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Failed to iterate through some users");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainendoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen enum mail_storage_service_flags service_flags =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *getopt_args, *username, *wildcard_user;
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen p_array_init(&ctx->module_contexts, ctx->pool, 5);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen while ((c = getopt(argc, argv, getopt_args)) > 0) {
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainen if (argv[0] != NULL && cmd->usage_args == NULL) {
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen if (!ctx->iterate_all_users && wildcard_user == NULL) {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen doveadm_mail_single_user(ctx, username, service_flags);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen doveadm_mail_all_users(ctx, wildcard_user, service_flags);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainenvoid dm_printf(struct doveadm_mail_cmd_context *ctx, const char *format, ...)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen const char *str = t_strdup_vprintf(format, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen unsigned int len;
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen /* more args */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* see if it matches a multi-word command */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (doveadm_mail_try_run_multi_word(cmd, subcmd,
51b979b6414b940f04677a7e2d064be119345954Timo Sirainenvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* for now we'll just assume that cmd will be permanently in memory */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen str_printfa(out, "%s\t[-u <user>|-A]", cmd->name);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen fprintf(stderr, "doveadm %s [-u <user>|-A] %s\n", cmd->name,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen cmd->usage_args == NULL ? "" : cmd->usage_args);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid doveadm_mail_try_help_name(const char *cmd_name)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenbool doveadm_mail_has_subcommands(const char *cmd_name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid doveadm_mail_help_name(const char *cmd_name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Missing help for command %s", cmd_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_mail_cmd cmd_force_resync = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_force_resync_alloc, "force-resync", "<mailbox>"
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainenstatic struct doveadm_mail_cmd *mail_commands[] = {
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen unsigned int i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands); i++)
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen mod_set.version = master_service_get_version_string(master_service);
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen /* load all configured mail plugins */