doveadm-mail.c revision 218153e0aa44a115a2dacab8510fb8de7e1cb78e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(ns->storage, NULL));
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("Can't find namespace for mailbox %s", mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Opening mailbox %s failed: %s", orig_mailbox,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(mailbox_get_storage(box),
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenint doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (mailbox_find_and_open(user, mailbox, box_r) < 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen i_error("Syncing mailbox %s failed: %s", mailbox,
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen mail_storage_get_last_error(mailbox_get_storage(*box_r),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainendoveadm_mail_build_search_args(const char *const args[])
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser = mail_search_parser_init_cmdline(args);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen if (mail_search_build(mail_search_register_get_human(),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void cmd_force_resync_run(struct doveadm_mail_cmd_context *_ctx,
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void cmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen const char *const args[])
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->mailbox = p_strdup(ctx->ctx.pool, mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct force_resync_cmd_context);
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen const struct mail_storage_service_input *input,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen const char **error_r)
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen struct mail_storage_service_user *service_user;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username));
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, input,
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_settings->doveadm_worker_count > 0 && !doveadm_server) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* execute this command via doveadm server */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = doveadm_mail_server_user(ctx, service_user, error_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_service_user_free(&service_user);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mail_storage_service_next(ctx->storage_service, service_user,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_service_user_free(&service_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_service_user_free(&service_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_storage_service_flags service_flags)
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen i_fatal("USER environment is missing and -u option not used");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen else if (ret == 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx, char *argv[],
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_storage_service_flags service_flags)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen unsigned int user_idx, user_count, interval, n;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user_count = mail_storage_service_all_init(ctx->storage_service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (interval = 10; n > 0 && interval < 1000; interval *= 10)
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen else if (ret == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_warning("Killed with signal %d", killed_signo);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Failed to iterate through some users");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainendoveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen p_array_init(&ctx->module_contexts, ctx->pool, 5);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_storage_service_flags service_flags =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *getopt_args, *username, *wildcard_user;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen getopt_args = t_strconcat("AS:u:", ctx->getopt_args, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while ((c = getopt(argc, argv, getopt_args)) > 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_settings->doveadm_socket_path = optarg;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (doveadm_settings->doveadm_worker_count == 0)
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (argv[0] != NULL && cmd->usage_args == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen !ctx->iterate_all_users && wildcard_user == NULL;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen if (doveadm_print_is_initialized() && !ctx->iterate_single_user) {
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen doveadm_mail_single_user(ctx, argv, username, service_flags);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen doveadm_mail_all_users(ctx, argv, wildcard_user, service_flags);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int len;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* more args */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen /* see if it matches a multi-word command */
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_mail_try_run_multi_word(cmd, subcmd,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen /* for now we'll just assume that cmd will be permanently in memory */
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainenconst struct doveadm_mail_cmd *doveadm_mail_cmd_find(const char *cmd_name)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen str_printfa(out, "%s\t[-u <user>|-A] [-S <socket_path>]",
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen fprintf(stderr, "doveadm %s [-u <user>|-A] [-S <socket_path>] %s\n",
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen cmd->name, cmd->usage_args == NULL ? "" : cmd->usage_args);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid doveadm_mail_try_help_name(const char *cmd_name)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenbool doveadm_mail_has_subcommands(const char *cmd_name)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainenvoid doveadm_mail_help_name(const char *cmd_name)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("Missing help for command %s", cmd_name);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainenstatic struct doveadm_mail_cmd cmd_force_resync = {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen cmd_force_resync_alloc, "force-resync", "<mailbox>"
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainenstatic struct doveadm_mail_cmd *mail_commands[] = {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands); i++)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mod_set.version = master_service_get_version_string(master_service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* load all configured mail plugins */