doveadm-mail.c revision b8b085f7bc6f1c0367802a9f00062bbbd981690d
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. WarfieldARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield doveadm_mail_cmd_module_register = { 0 };
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
ec64264d78d4ed608553842ce9e1f07eeab2a032Veres Lajos pool = pool_alloconly_create("doveadm mail cmd", 1024);
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfieldcmd_purge_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield for (ns = user->namespaces; ns != NULL; ns = ns->next) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if (mail_storage_purge(ns->storage) < 0) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_error("Purging namespace '%s' failed: %s", ns->prefix,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_storage_get_last_error(ns->storage, NULL));
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmailbox_find_and_open(struct mail_user *user, const char *mailbox)
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graber i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber ns = mail_namespace_find(user->namespaces, &mailbox);
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber i_fatal("Can't find namespace for mailbox %s", mailbox);
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graber box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_fatal("Opening mailbox %s failed: %s", orig_mailbox,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_storage_get_last_error(mailbox_get_storage(box),
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield box = mailbox_find_and_open(user, mailbox);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_fatal("Syncing mailbox %s failed: %s", mailbox,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_storage_get_last_error(mailbox_get_storage(box),
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfielddoveadm_mail_build_search_args(const char *const args[])
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield parser = mail_search_parser_init_cmdline(args);
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (mail_search_build(mail_search_register_get_human(),
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void cmd_force_resync_run(struct doveadm_mail_cmd_context *_ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield (struct force_resync_cmd_context *)_ctx;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield box = mailbox_find_and_open(user, ctx->mailbox);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) < 0) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield i_fatal("Forcing a resync on mailbox %s failed: %s",
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_storage_get_last_error(storage, NULL));
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void cmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char *const args[])
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield (struct force_resync_cmd_context *)_ctx;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->mailbox = p_strdup(ctx->ctx.pool, mailbox);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx = doveadm_mail_cmd_alloc(struct force_resync_cmd_context);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->ctx.v.init = cmd_force_resync_init;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_storage_service_input *input,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_storage_service_user *service_user;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username));
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield ret = mail_storage_service_lookup(ctx->storage_service, input,
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield *error_r = t_strdup_printf("User lookup failed: %s",
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield ret = mail_storage_service_next(ctx->storage_service, service_user,
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield mail_storage_service_user_free(&service_user);
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield mail_storage_service_user_free(&service_user);
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfielddoveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield enum mail_storage_service_flags service_flags)
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield struct mail_storage_service_input input;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield i_fatal("USER environment is missing and -u option not used");
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield ctx->storage_service = mail_storage_service_init(master_service, NULL,
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield ret = doveadm_mail_next_user(ctx, &input, &error);
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield else if (ret == 0)
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield mail_storage_service_deinit(&ctx->storage_service);
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfieldstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfielddoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield enum mail_storage_service_flags service_flags)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_storage_service_input input;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int user_idx, user_count, interval, n;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->storage_service = mail_storage_service_init(master_service, NULL,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield user_count = mail_storage_service_all_init(ctx->storage_service);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (interval = 10; n > 0 && interval < 1000; interval *= 10)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!wildcard_match_icase(user, wildcard_user))
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = doveadm_mail_next_user(ctx, &input, &error);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield else if (ret == 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_info("User no longer exists, skipping");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield printf("\r%d / %d", user_idx, user_count);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_warning("Killed with signal %d", killed_signo);
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes i_error("Failed to iterate through some users");
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes mail_storage_service_deinit(&ctx->storage_service);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return mail_storage_service_all_next(ctx->storage_service, username_r);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield enum mail_storage_service_flags service_flags =
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield const char *getopt_args, *username, *wildcard_user;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield ctx->v.init = doveadm_mail_cmd_init_noop;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield ctx->v.deinit = doveadm_mail_cmd_deinit_noop;
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes p_array_init(&ctx->module_contexts, ctx->pool, 5);
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield while ((c = getopt(argc, argv, getopt_args)) > 0) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (argv[0] != NULL && cmd->usage_args == NULL) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_fatal("doveadm %s: Unknown parameter: %s",
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!ctx->iterate_all_users && wildcard_user == NULL) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield doveadm_mail_single_user(ctx, username, service_flags);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield doveadm_mail_all_users(ctx, wildcard_user, service_flags);
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfieldvoid dm_printf(struct doveadm_mail_cmd_context *ctx, const char *format, ...)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char *str = t_strdup_vprintf(format, args);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield printf("%s: ", ctx->cur_mail_user->username);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfielddoveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char *cmdname, int argc, char *argv[])
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* more args */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield array_foreach(&doveadm_mail_cmds, cmd) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* see if it matches a multi-word command */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char *subcmd = cmd->name + cmd_name_len + 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (doveadm_mail_try_run_multi_word(cmd, subcmd,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* for now we'll just assume that cmd will be permanently in memory */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield array_append(&doveadm_mail_cmds, cmd, 1);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield array_foreach(&doveadm_mail_cmds, cmd) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield str_printfa(out, "%s\t[-u <user>|-A]", cmd->name);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield str_printfa(out, " %s", cmd->usage_args);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield fprintf(stderr, "doveadm %s [-u <user>|-A] %s\n", cmd->name,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield cmd->usage_args == NULL ? "" : cmd->usage_args);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid doveadm_mail_try_help_name(const char *cmd_name)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield array_foreach(&doveadm_mail_cmds, cmd) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldbool doveadm_mail_has_subcommands(const char *cmd_name)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield array_foreach(&doveadm_mail_cmds, cmd) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (strncmp(cmd->name, cmd_name, len) == 0 &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid doveadm_mail_help_name(const char *cmd_name)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_fatal("Missing help for command %s", cmd_name);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic struct doveadm_mail_cmd cmd_force_resync = {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield cmd_force_resync_alloc, "force-resync", "<mailbox>"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic struct doveadm_mail_cmd cmd_purge = {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic struct doveadm_mail_cmd *mail_commands[] = {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct module_dir_load_settings mod_set;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < N_ELEMENTS(mail_commands); i++)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield doveadm_mail_register_cmd(mail_commands[i]);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mod_set.version = master_service_get_version_string(master_service);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* load all configured mail plugins */