doveadm-mail.c revision 82130fea452f0bed0deb41405ccfedbf674e0e6c
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS (5*60*1000)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainenvoid doveadm_mail_failed_error(struct doveadm_mail_cmd_context *ctx,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* tempfail overrides all other exit codes, otherwise use whatever
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen error happened first */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid doveadm_mail_failed_storage(struct doveadm_mail_cmd_context *ctx,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid doveadm_mail_failed_mailbox(struct doveadm_mail_cmd_context *ctx,
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen doveadm_mail_failed_storage(ctx, mailbox_get_storage(box));
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainenvoid doveadm_mail_failed_list(struct doveadm_mail_cmd_context *ctx,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen storage = mail_namespace_get_default_storage(ns);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic void doveadm_mail_cmd_input_input(struct doveadm_mail_cmd_context *ctx)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_stream_skip(ctx->cmd_input, i_stream_get_data_size(ctx->cmd_input));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void doveadm_mail_cmd_input_timeout(struct doveadm_mail_cmd_context *ctx)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen input = i_stream_create_error_str(ETIMEDOUT, "Timed out in %u secs",
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen i_stream_set_name(input, i_stream_get_name(ctx->cmd_input));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic void doveadm_mail_cmd_input_read(struct doveadm_mail_cmd_context *ctx)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen to = timeout_add(DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* read the pending input from stream. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid doveadm_mail_get_input(struct doveadm_mail_cmd_context *ctx)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen inputs[0] = i_stream_create_dot(ctx->conn->input, FALSE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen inputs[0] = i_stream_create_fd(STDIN_FILENO, 1024*1024, FALSE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->cmd_input_fd = i_stream_get_fd(inputs[0]);
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen ctx->cmd_input = i_stream_create_seekable_path(inputs, 1024*256,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_stream_set_name(ctx->cmd_input, i_stream_get_name(inputs[0]));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainendoveadm_mailbox_find(struct mail_user *user, const char *mailbox)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_IGNORE_ACLS);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainendoveadm_mail_build_search_args(const char *const args[])
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen parser = mail_search_parser_init_cmdline(args);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (mail_search_build(mail_search_register_get_human(),
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainenstatic int cmd_force_resync_box(struct doveadm_mail_cmd_context *ctx,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen box = mailbox_alloc(info->ns->list, info->vname,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("Opening mailbox %s failed: %s", info->vname,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen } else if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen info->vname, mailbox_get_last_error(box, NULL));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic int cmd_force_resync_run(struct doveadm_mail_cmd_context *ctx,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const enum mail_namespace_type ns_mask = MAIL_NAMESPACE_TYPE_MASK_ALL;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen iter = mailbox_list_iter_init_namespaces(user->namespaces, ctx->args,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mailbox_list_get_last_error(user->namespaces->list, NULL));
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen doveadm_mail_failed_list(ctx, user->namespaces->list);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainencmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen const char *const args[])
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen const struct mail_storage_service_input *input,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen const char **error_r)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen i_set_failure_prefix("doveadm(%s): ", input->username);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen i_set_failure_prefix("doveadm(%s,%s): ", ip, input->username);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen /* see if we want to execute this command via (another)
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen doveadm server */
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen ret = doveadm_mail_server_user(ctx, input, error_r);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, input,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (ctx->v.prerun(ctx, ctx->cur_service_user, error_r) < 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen ret = mail_storage_service_next(ctx->storage_service,
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (ctx->v.run(ctx, ctx->cur_mail_user) < 0) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenint doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen const struct mail_storage_service_input *input,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char **error_r)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return doveadm_mail_next_user(ctx, input, error_r);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx, char *argv[],
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen lib_signals_set_handler(SIGINT, 0, sig_die, NULL);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen lib_signals_set_handler(SIGTERM, 0, sig_die, NULL);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_storage_service_all_init(ctx->storage_service);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen else if (ret == 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_warning("Killed with signal %d", killed_signo);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_error("Failed to iterate through some users");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *username_r = i_stream_read_next_line(ctx->users_list_input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (ctx->users_list_input->stream_errno != 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainendoveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd,
return ctx;
int ret, c;
if (doveadm_debug)
if (ret < 0)
else if (ret == 0)
const char *const **argv)
unsigned int len;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
const struct doveadm_mail_cmd *
const char *const **argv)
unsigned int cmd_name_len;
const char *const *orig_argv;
int orig_argc;
return cmd;
return cmd;
return NULL;
return FALSE;
return TRUE;
return cmd;
return NULL;
return TRUE;
return FALSE;
&cmd_save,
&cmd_copy,
&cmd_move,
void doveadm_mail_init(void)
&mod_set);
void doveadm_mail_deinit(void)