static int
ns_mailbox_try_alloc(struct dsync_brain *brain, struct mail_namespace *ns,
		     const guid_128_t guid, struct mailbox **box_r,
		     const char **errstr_r, enum mail_error *error_r)
{
	enum mailbox_flags flags = 0;
	struct mailbox *box;
	enum mailbox_existence existence;
	int ret;

	if (brain->backup_send) {
		/* make sure mailbox isn't modified */
		flags |= MAILBOX_FLAG_READONLY;
	}

	box = mailbox_alloc_guid(ns->list, guid, flags);
	ret = mailbox_exists(box, FALSE, &existence);
	if (ret < 0) {
		*errstr_r = mailbox_get_last_error(box, error_r);
		mailbox_free(&box);
		return -1;
	}
	if (existence != MAILBOX_EXISTENCE_SELECT) {
		mailbox_free(&box);
		*errstr_r = existence == MAILBOX_EXISTENCE_NONE ?
			"Mailbox was already deleted" :
			"Mailbox is no longer selectable";
		return 0;
	}
	*box_r = box;
	return 1;
}
static int
ns_mailbox_try_alloc(struct mail_namespace *ns, const guid_128_t guid,
		     struct mailbox **box_r, const char **error_r)
{
	struct mailbox *box;
	enum mailbox_existence existence;
	enum mail_error err;
	int ret;

	box = mailbox_alloc_guid(ns->list, guid, 0);
	ret = mailbox_exists(box, FALSE, &existence);
	if (ret < 0) {
		*error_r = mailbox_get_last_error(box, &err);
		mailbox_free(&box);
		return -1;
	}
	if (existence != MAILBOX_EXISTENCE_SELECT) {
		mailbox_free(&box);
		*error_r = existence == MAILBOX_EXISTENCE_NONE ?
			"Mailbox was already deleted" :
			"Mailbox is no longer selectable";
		return 0;
	}
	*box_r = box;
	return 1;
}
static int dsync_mailbox_tree_add(struct dsync_mailbox_tree *tree,
				  const struct mailbox_info *info,
				  const guid_128_t box_guid,
				  enum mail_error *error_r)
{
	struct dsync_mailbox_node *node;
	struct mailbox *box;
	struct mailbox_metadata metadata;
	struct mailbox_status status;
	const char *errstr;
	enum mail_error error;
	int ret = 0;

	if ((info->flags & MAILBOX_NONEXISTENT) != 0)
		return 0;
	if ((info->flags & MAILBOX_NOSELECT) != 0) {
		return !guid_128_is_empty(box_guid) ? 0 :
			dsync_mailbox_tree_add_exists_node(tree, info, &node, error_r);
	}

	/* get GUID and UIDVALIDITY for selectable mailbox */
	box = mailbox_alloc(info->ns->list, info->vname, MAILBOX_FLAG_READONLY);
	if (dsync_mailbox_tree_get_selectable(box, &metadata, &status) < 0) {
		errstr = mailbox_get_last_internal_error(box, &error);
		switch (error) {
		case MAIL_ERROR_NOTFOUND:
			/* mailbox was just deleted? */
			break;
		case MAIL_ERROR_NOTPOSSIBLE:
			/* invalid mbox files? ignore */
			break;
		default:
			i_error("Failed to access mailbox %s: %s",
				info->vname, errstr);
			*error_r = error;
			ret = -1;
		}
		mailbox_free(&box);
		return ret;
	}
	mailbox_free(&box);

	if (!guid_128_is_empty(box_guid) &&
	    !guid_128_equals(box_guid, metadata.guid)) {
		/* unwanted mailbox */
		return 0;
	}
	if (dsync_mailbox_tree_add_exists_node(tree, info, &node, error_r) < 0)
		return -1;
	memcpy(node->mailbox_guid, metadata.guid,
	       sizeof(node->mailbox_guid));
	node->uid_validity = status.uidvalidity;
	node->uid_next = status.uidnext;
	return 0;
}
static int
quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
		    const char *vname, uint64_t *bytes_r, uint64_t *count_r)
{
	struct quota_rule *rule;
	struct mailbox *box;
	struct mailbox_transaction_context *trans;
	struct mail_search_context *ctx;
	struct mail *mail;
	struct mail_search_args *search_args;
	enum mail_error error;
	uoff_t size;
	int ret = 0;

	rule = quota_root_rule_find(root->set, vname);
	if (rule != NULL && rule->ignore) {
		/* mailbox not included in quota */
		return 0;
	}

	box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY);
	if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
		error = mailbox_get_last_mail_error(box);
		mailbox_free(&box);
		if (error == MAIL_ERROR_TEMP)
			return -1;
		/* non-temporary error, e.g. ACLs denied access. */
		return 0;
	}

	trans = mailbox_transaction_begin(box, 0);

	search_args = mail_search_build_init();
	mail_search_build_add_all(search_args);
	ctx = mailbox_search_init(trans, search_args, NULL,
				  MAIL_FETCH_PHYSICAL_SIZE, NULL);
	mail_search_args_unref(&search_args);

	while (mailbox_search_next(ctx, &mail)) {
		if (mail_get_physical_size(mail, &size) == 0)
			*bytes_r += size;
		*count_r += 1;
	}
	if (mailbox_search_deinit(&ctx) < 0)
		ret = -1;

	if (ret < 0)
		mailbox_transaction_rollback(&trans);
	else
		(void)mailbox_transaction_commit(&trans);

	mailbox_free(&box);
	return ret;
}
static int
dest_mailbox_open_or_create(struct import_cmd_context *ctx,
			    struct mail_user *user,
			    const struct mailbox_info *info,
			    struct mailbox **box_r)
{
	struct mail_namespace *ns;
	struct mailbox *box;
	enum mail_error error;
	const char *name, *errstr;

	if (*ctx->dest_parent != '\0') {
		/* prefix destination mailbox name with given parent mailbox */
		ns = mail_namespace_find(user->namespaces, ctx->dest_parent);
	} else {
		ns = mail_namespace_find(user->namespaces, info->vname);
	}
	name = convert_vname_separators(info->vname,
					mail_namespace_get_sep(info->ns),
					mail_namespace_get_sep(ns));

	if (*ctx->dest_parent != '\0') {
		name = t_strdup_printf("%s%c%s", ctx->dest_parent,
				       mail_namespace_get_sep(ns), name);
	}

	box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_SAVEONLY);
	if (mailbox_create(box, NULL, FALSE) < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error != MAIL_ERROR_EXISTS) {
			i_error("Couldn't create mailbox %s: %s", name, errstr);
			doveadm_mail_failed_mailbox(&ctx->ctx, box);
			mailbox_free(&box);
			return -1;
		}
	}
	if (ctx->subscribe) {
		if (mailbox_set_subscribed(box, TRUE) < 0) {
			i_error("Couldn't subscribe to mailbox %s: %s",
				name, mailbox_get_last_error(box, NULL));
		}
	}
	if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
		i_error("Syncing mailbox %s failed: %s", name,
			mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_mailbox(&ctx->ctx, box);
		mailbox_free(&box);
		return -1;
	}
	*box_r = box;
	return 0;
}
static int
dest_mailbox_open_or_create(struct import_cmd_context *ctx,
			    struct mail_user *user, const char *name,
			    struct mailbox **box_r)
{
	struct mail_namespace *ns;
	struct mailbox *box;
	enum mail_error error;
	const char *errstr, *storage_name;

	if (*ctx->dest_parent != '\0') {
		/* prefix destination mailbox name with given parent mailbox */
		storage_name = ctx->dest_parent;
		ns = mail_namespace_find(user->namespaces, &storage_name);
		if (ns == NULL) {
			i_error("Can't find namespace for parent mailbox %s",
				ctx->dest_parent);
			return -1;
		}
		name = t_strdup_printf("%s%c%s", ctx->dest_parent,
				       ns->sep, name);
	}

	storage_name = name;
	ns = mail_namespace_find(user->namespaces, &storage_name);
	if (ns == NULL) {
		i_error("Can't find namespace for mailbox %s", name);
		return -1;
	}

	box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_SAVEONLY |
			    MAILBOX_FLAG_KEEP_RECENT);
	if (mailbox_create(box, NULL, FALSE) < 0) {
		errstr = mail_storage_get_last_error(mailbox_get_storage(box),
						     &error);
		if (error != MAIL_ERROR_EXISTS) {
			i_error("Couldn't create mailbox %s: %s", name, errstr);
			mailbox_free(&box);
			return -1;
		}
	}
	if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
		i_error("Syncing mailbox %s failed: %s", name,
			mail_storage_get_last_error(mailbox_get_storage(box),
						    NULL));
		mailbox_free(&box);
		return -1;
	}
	*box_r = box;
	return 0;
}
Exemple #7
0
static void snarf_mailbox_free(struct mailbox *box)
{
	struct snarf_mailbox *sbox = SNARF_CONTEXT(box);

	mailbox_free(&sbox->snarf_box);
	sbox->module_ctx.super.free(box);
}
static bool cmd_getquotaroot(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
	struct mail_namespace *ns;
	struct mailbox *box;
	struct quota_root_iter *iter;
        struct quota_root *root;
	const char *mailbox, *storage_name, *name;
	string_t *quotaroot_reply, *quota_reply;

	/* <mailbox> */
	if (!client_read_string_args(cmd, 1, &mailbox))
		return FALSE;

	ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
	if (ns == NULL)
		return TRUE;

	if (quser == NULL) {
		client_send_tagline(cmd, "OK No quota.");
		return TRUE;
	}
	if (ns->owner != NULL && ns->owner != client->user &&
	    !client->user->admin) {
		client_send_tagline(cmd, "NO Not showing other users' quota.");
		return TRUE;
	}

	box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_READONLY |
			    MAILBOX_FLAG_KEEP_RECENT);

	/* build QUOTAROOT reply and QUOTA reply for all quota roots */
	quotaroot_reply = t_str_new(128);
	quota_reply = t_str_new(256);
	str_append(quotaroot_reply, "* QUOTAROOT ");
	imap_quote_append_string(quotaroot_reply, mailbox, FALSE);

	iter = quota_root_iter_init(box);
	while ((root = quota_root_iter_next(iter)) != NULL) {
		str_append_c(quotaroot_reply, ' ');
		name = imap_quota_root_get_name(client->user, ns->owner, root);
		imap_quote_append_string(quotaroot_reply, name, FALSE);

		quota_reply_write(quota_reply, client->user, ns->owner, root);
	}
	quota_root_iter_deinit(&iter);
	mailbox_free(&box);

	/* send replies */
	if (str_len(quota_reply) == 0)
		client_send_tagline(cmd, "OK No quota.");
	else {
		client_send_line(client, str_c(quotaroot_reply));
		o_stream_send(client->output, str_data(quota_reply),
			      str_len(quota_reply));
		client_send_tagline(cmd, "OK Getquotaroot completed.");
	}
	return TRUE;
}
Exemple #9
0
int fts_backend_reset_last_uids(struct fts_backend *backend)
{
    struct mailbox_list_iterate_context *iter;
    const struct mailbox_info *info;
    struct mailbox *box;
    int ret = 0;

    iter = mailbox_list_iter_init(backend->ns->list, "*",
                                  MAILBOX_LIST_ITER_SKIP_ALIASES |
                                  MAILBOX_LIST_ITER_NO_AUTO_BOXES);
    while ((info = mailbox_list_iter_next(iter)) != NULL) {
        if ((info->flags &
                (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) != 0)
            continue;

        box = mailbox_alloc(info->ns->list, info->vname, 0);
        if (mailbox_open(box) == 0) {
            if (fts_index_set_last_uid(box, 0) < 0)
                ret = -1;
        }
        mailbox_free(&box);
    }
    if (mailbox_list_iter_deinit(&iter) < 0)
        ret = -1;
    return ret;
}
Exemple #10
0
static void cmd_append_finish(struct cmd_append_context *ctx)
{
	if (ctx->save_parser != NULL)
		imap_parser_unref(&ctx->save_parser);

	i_assert(ctx->client->input_lock == ctx->cmd);

	if (ctx->client->io != NULL)
		io_remove(&ctx->client->io);
	/* we must put back the original flush callback before beginning to
	   sync (the command is still unfinished at that point) */
	o_stream_set_flush_callback(ctx->client->output,
				    client_output, ctx->client);

	if (ctx->litinput != NULL)
		i_stream_unref(&ctx->litinput);
	if (ctx->input != NULL)
		i_stream_unref(&ctx->input);
	if (ctx->save_ctx != NULL)
		mailbox_save_cancel(&ctx->save_ctx);
	if (ctx->t != NULL)
		mailbox_transaction_rollback(&ctx->t);
	if (ctx->box != ctx->cmd->client->mailbox && ctx->box != NULL)
		mailbox_free(&ctx->box);
}
Exemple #11
0
static bool
cmd_setmetadata_mailbox(struct imap_setmetadata_context *ctx,
                        const char *mailbox)
{
    struct client_command_context *cmd = ctx->cmd;
    struct client *client = cmd->client;
    struct mail_namespace *ns;

    ns = client_find_namespace(cmd, &mailbox);
    if (ns == NULL)
        return TRUE;

    if (client->mailbox != NULL && !client->mailbox_examined &&
            mailbox_equals(client->mailbox, ns, mailbox))
        ctx->box = client->mailbox;
    else {
        ctx->box = mailbox_alloc(ns->list, mailbox, 0);
        if (mailbox_open(ctx->box) < 0) {
            client_send_box_error(cmd, ctx->box);
            mailbox_free(&ctx->box);
            return TRUE;
        }
    }
    ctx->trans = imap_metadata_transaction_begin(ctx->box);
    return cmd_setmetadata_start(ctx);
}
static int
cmd_mailbox_metadata_list_run(struct doveadm_mail_cmd_context *_ctx,
			      struct mail_user *user)
{
	struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
	struct mail_namespace *ns;
	struct mailbox *box;
	int ret = 0;

	ret = cmd_mailbox_metadata_open_mailbox(ctx, user, "list attributes",
						&ns, &box);
	if (ret != 0)
		return ret;

	if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_PRIVATE) {
		if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_PRIVATE) < 0) {
			doveadm_mail_failed_mailbox(_ctx, box);
			ret = -1;
		}
	}
	if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_SHARED) {
		if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_SHARED) < 0) {
			doveadm_mail_failed_mailbox(_ctx, box);
			ret = -1;
		}
	}
	mailbox_free(&box);
	return ret;
}
static int
cmd_mailbox_metadata_get_run(struct doveadm_mail_cmd_context *_ctx,
			     struct mail_user *user)
{
	struct metadata_cmd_context *ctx = (struct metadata_cmd_context *)_ctx;
	struct mail_namespace *ns;
	struct mailbox *box;
	struct mail_attribute_value value;
	int ret;

	ret = cmd_mailbox_metadata_open_mailbox(ctx, user, "get attribute",
						&ns, &box);
	if (ret != 0)
		return ret;

	ret = mailbox_attribute_get_stream(box, ctx->key_type, ctx->key, &value);
	if (ret < 0) {
		i_error("Failed to get attribute: %s",
			mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_mailbox(_ctx, box);
	} else if (ret == 0) {
		/* not found, print as empty */
		doveadm_print("");
	} else if (value.value_stream != NULL) {
		doveadm_print_istream(value.value_stream);
	} else {
		doveadm_print(value.value);
	}

	mailbox_free(&box);
	return ret;
}
Exemple #14
0
static int
lmtp_rcpt_to_is_over_quota(struct client *client,
			   const struct mail_recipient *rcpt)
{
	struct mail_user *user;
	struct mail_namespace *ns;
	struct mailbox *box;
	struct mailbox_status status;
	const char *errstr;
	enum mail_error error;
	int ret;

	if (!client->lmtp_set->lmtp_rcpt_check_quota)
		return 0;

	ret = mail_storage_service_next(storage_service,
					rcpt->service_user, &user);
	if (ret < 0)
		return -1;

	ns = mail_namespace_find_inbox(user->namespaces);
	box = mailbox_alloc(ns->list, "INBOX", 0);
	ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status);
	if (ret < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error == MAIL_ERROR_NOSPACE) {
			client_send_line(client, "552 5.2.2 <%s> %s",
					 rcpt->address, errstr);
			ret = 1;
		}
	}
	mailbox_free(&box);
	mail_user_unref(&user);
	return ret;
}
static int
cmd_import_box(struct import_cmd_context *ctx, struct mail_user *dest_user,
	       const struct mailbox_info *info,
	       struct mail_search_args *search_args)
{
	struct doveadm_mail_iter *iter;
	struct mailbox_transaction_context *trans;
	struct mailbox *box;
	struct mail *mail;
	int ret = 0;

	if (doveadm_mail_iter_init(info, search_args, &trans, &iter) < 0)
		return -1;

	mail = mail_alloc(trans, 0, NULL);
	if (doveadm_mail_iter_next(iter, mail)) {
		/* at least one mail matches in this mailbox */
		if (dest_mailbox_open_or_create(ctx, dest_user, info->name,
						&box) == 0) {
			if (cmd_import_box_contents(iter, mail, box) < 0)
				ret = -1;
			mailbox_free(&box);
		}
	}
	mail_free(&mail);
	if (doveadm_mail_iter_deinit_sync(&iter) < 0)
		ret = -1;
	return ret;
}
Exemple #16
0
static int
cmd_acl_mailbox_open(struct doveadm_mail_cmd_context *ctx,
		     struct mail_user *user, const char *mailbox,
		     struct mailbox **box_r)
{
	struct acl_user *auser = ACL_USER_CONTEXT(user);
	struct mail_namespace *ns;
	struct mailbox *box;

	if (auser == NULL) {
		i_error("ACL not enabled for %s", user->username);
		doveadm_mail_failed_error(ctx, MAIL_ERROR_NOTFOUND);
		return -1;
	}

	ns = mail_namespace_find(user->namespaces, mailbox);
	box = mailbox_alloc(ns->list, mailbox,
			    MAILBOX_FLAG_READONLY | MAILBOX_FLAG_IGNORE_ACLS);
	if (mailbox_open(box) < 0) {
		i_error("Can't open mailbox %s: %s", mailbox,
			mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_mailbox(ctx, box);
		mailbox_free(&box);
		return -1;
	}
	*box_r = box;
	return 0;
}
static int
cmd_import_box(struct import_cmd_context *ctx, struct mail_user *dest_user,
	       const struct mailbox_info *info,
	       struct mail_search_args *search_args)
{
	struct doveadm_mail_iter *iter;
	struct mailbox *box;
	struct mail *mail;
	int ret = 0;

	if (doveadm_mail_iter_init(&ctx->ctx, info, search_args, 0, NULL,
				   &iter) < 0)
		return -1;

	if (doveadm_mail_iter_next(iter, &mail)) {
		/* at least one mail matches in this mailbox */
		if (dest_mailbox_open_or_create(ctx, dest_user, info->vname,
						&box) < 0)
			ret = -1;
		else {
			if (cmd_import_box_contents(iter, mail, box) < 0) {
				doveadm_mail_failed_mailbox(&ctx->ctx, mail->box);
				ret = -1;
			}
			mailbox_free(&box);
		}
	}
	if (doveadm_mail_iter_deinit_sync(&iter) < 0)
		ret = -1;
	return ret;
}
Exemple #18
0
static int
cmd_acl_mailbox_open(struct mail_user *user, const char *mailbox,
		     struct mailbox **box_r)
{
	struct acl_user *auser = ACL_USER_CONTEXT(user);
	struct mail_namespace *ns;
	struct mailbox *box;
	const char *storage_name;

	if (auser == NULL) {
		i_error("ACL not enabled for %s", user->username);
		return -1;
	}

	storage_name = mailbox;
	ns = mail_namespace_find(user->namespaces, &storage_name);
	if (ns == NULL) {
		i_error("No namespace found for mailbox %s", mailbox);
		return -1;
	}
	box = mailbox_alloc(ns->list, storage_name,
			    MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT |
			    MAILBOX_FLAG_IGNORE_ACLS);
	if (mailbox_open(box) < 0) {
		i_error("Can't open mailbox %s: %s", mailbox,
			mail_storage_get_last_error(box->storage, NULL));
		mailbox_free(&box);
		return -1;
	}
	*box_r = box;
	return 0;
}
Exemple #19
0
void dsync_brain_sync_mailbox_deinit(struct dsync_brain *brain)
{
	i_assert(brain->box != NULL);

	array_append(&brain->remote_mailbox_states, &brain->mailbox_state, 1);
	if (brain->box_exporter != NULL) {
		const char *error;

		i_assert(brain->failed ||
			 brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_CHANGED);
		(void)dsync_mailbox_export_deinit(&brain->box_exporter, &error);
	}
	if (brain->box_importer != NULL) {
		uint32_t last_common_uid;
		uint64_t last_common_modseq, last_common_pvt_modseq;
		bool changes_during_sync;

		i_assert(brain->failed);
		(void)dsync_mailbox_import_deinit(&brain->box_importer,
						  FALSE,
						  &last_common_uid,
						  &last_common_modseq,
						  &last_common_pvt_modseq,
						  &changes_during_sync);
	}
	if (brain->log_scan != NULL)
		dsync_transaction_log_scan_deinit(&brain->log_scan);
	mailbox_free(&brain->box);

	brain->state = brain->pre_box_state;
}
static int
cmd_copy_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
{
	struct copy_cmd_context *ctx = (struct copy_cmd_context *)_ctx;
	const enum mailbox_list_iter_flags iter_flags =
		MAILBOX_LIST_ITER_NO_AUTO_BOXES |
		MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
	struct doveadm_mailbox_list_iter *iter;
	struct mail_user *src_user;
	struct mail_namespace *ns;
	struct mailbox *destbox;
	const struct mailbox_info *info;
	int ret = 0;

	if (ctx->source_username != NULL && ctx->source_user == NULL)
		cmd_copy_alloc_source_user(ctx);

	ns = mail_namespace_find(user->namespaces, ctx->destname);
	destbox = mailbox_alloc(ns->list, ctx->destname, MAILBOX_FLAG_SAVEONLY);
	if (mailbox_open(destbox) < 0) {
		i_error("Can't open mailbox '%s': %s", ctx->destname,
			mailbox_get_last_error(destbox, NULL));
		doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
		mailbox_free(&destbox);
		return -1;
	}

	src_user = ctx->source_user != NULL ? ctx->source_user : user;
	iter = doveadm_mailbox_list_iter_init(_ctx, src_user, _ctx->search_args,
					      iter_flags);
	while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
		if (cmd_copy_box(ctx, destbox, info) < 0)
			ret = -1;
	} T_END;
	if (doveadm_mailbox_list_iter_deinit(&iter) < 0)
		ret = -1;

	if (mailbox_sync(destbox, 0) < 0) {
		i_error("Syncing mailbox '%s' failed: %s", ctx->destname,
			mailbox_get_last_error(destbox, NULL));
		doveadm_mail_failed_mailbox(&ctx->ctx, destbox);
		ret = -1;
	}
	mailbox_free(&destbox);
	return ret;
}
Exemple #21
0
int imap_msgpart_url_open_mailbox(struct imap_msgpart_url *mpurl,
				  struct mailbox **box_r, enum mail_error *error_code_r,
				  const char **error_r)
{
	struct mailbox_status box_status;
	enum mailbox_flags flags = MAILBOX_FLAG_READONLY;
	struct mail_namespace *ns;
	struct mailbox *box;

	if (mpurl->box != NULL) {
		*box_r = mpurl->box;
		*error_code_r = MAIL_ERROR_NONE;
		return 1;
	}

	/* find mailbox namespace */
	ns = mail_namespace_find(mpurl->user->namespaces, mpurl->mailbox);

	/* open mailbox */
	if (mpurl->selected_box != NULL &&
	    mailbox_equals(mpurl->selected_box, ns, mpurl->mailbox))
		box = mpurl->selected_box;
	else
		box = mailbox_alloc(ns->list, mpurl->mailbox, flags);
	if (mailbox_open(box) < 0) {
		*error_r = mail_storage_get_last_error(mailbox_get_storage(box),
						       error_code_r);
		if (box != mpurl->selected_box)
			mailbox_free(&box);
		return *error_code_r == MAIL_ERROR_TEMP ? -1 : 0;
	}

	/* verify UIDVALIDITY */
	mailbox_get_open_status(box, STATUS_UIDVALIDITY, &box_status);
	if (mpurl->uidvalidity > 0 &&
	    box_status.uidvalidity != mpurl->uidvalidity) {
		*error_r = "Invalid UIDVALIDITY";
		*error_code_r = MAIL_ERROR_EXPUNGED;
		if (box != mpurl->selected_box)
			mailbox_free(&box);
		return 0;
	}
	mpurl->box = box;
	*box_r = box;
	return 1;
}
Exemple #22
0
bool cmd_create(struct client_command_context *cmd)
{
	enum mailbox_name_status status;
	struct mail_namespace *ns;
	const char *mailbox, *storage_name;
	struct mailbox *box;
	bool directory;
	size_t len;

	/* <mailbox> */
	if (!client_read_string_args(cmd, 1, &mailbox))
		return FALSE;

	ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
	if (ns == NULL)
		return TRUE;

	len = strlen(mailbox);
	if (len == 0 || mailbox[len-1] != ns->sep)
		directory = FALSE;
	else if (*storage_name == '\0') {
		client_send_tagline(cmd, "NO ["IMAP_RESP_CODE_ALREADYEXISTS
				    "] Namespace already exists.");
		return TRUE;
	} else {
		/* name ends with hierarchy separator - client is just
		   informing us that it wants to create children under this
		   mailbox. */
                directory = TRUE;
		storage_name = t_strndup(storage_name, strlen(storage_name)-1);
		mailbox = t_strndup(mailbox, len-1);
	}

	ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
	if (ns == NULL)
		return TRUE;
	switch (status) {
	case MAILBOX_NAME_VALID:
		break;
	case MAILBOX_NAME_EXISTS_DIR:
		if (!directory)
			break;
		/* fall through */
	case MAILBOX_NAME_EXISTS_MAILBOX:
	case MAILBOX_NAME_INVALID:
	case MAILBOX_NAME_NOINFERIORS:
		client_fail_mailbox_name_status(cmd, mailbox, NULL, status);
		return TRUE;
	}

	box = mailbox_alloc(ns->list, storage_name, 0);
	if (mailbox_create(box, NULL, directory) < 0)
		client_send_storage_error(cmd, mailbox_get_storage(box));
	else
		client_send_tagline(cmd, "OK Create completed.");
	mailbox_free(&box);
	return TRUE;
}
Exemple #23
0
static void
mailbox_list_index_update_info(struct mailbox_list_index_iterate_context *ctx)
{
	struct mailbox_list_index_node *node = ctx->next_node;
	struct mailbox *box;

	p_clear(ctx->info_pool);

	str_truncate(ctx->path, ctx->parent_len);
	/* the root directory may have an empty name. in that case we'll still
	   want to insert the separator, so check for non-NULL parent rather
	   than non-empty path. */
	if (node->parent != NULL) {
		str_append_c(ctx->path,
			     mailbox_list_get_hierarchy_sep(ctx->ctx.list));
	}
	str_append(ctx->path, node->name);

	ctx->info.vname = mailbox_list_get_vname(ctx->ctx.list, str_c(ctx->path));
	ctx->info.flags = node->children != NULL ?
		MAILBOX_CHILDREN : MAILBOX_NOCHILDREN;
	if (strcmp(ctx->info.vname, "INBOX") != 0) {
		/* non-INBOX */
		ctx->info.vname = p_strdup(ctx->info_pool, ctx->info.vname);
	} else if (!ctx->prefix_inbox_list) {
		/* listing INBOX itself */
		ctx->info.vname = "INBOX";
		if (mail_namespace_is_inbox_noinferiors(ctx->info.ns)) {
			ctx->info.flags &= ~(MAILBOX_CHILDREN|MAILBOX_NOCHILDREN);
			ctx->info.flags |= MAILBOX_NOINFERIORS;
		}
	} else {
		/* listing INBOX/INBOX */
		ctx->info.vname = p_strconcat(ctx->info_pool,
			ctx->ctx.list->ns->prefix, "INBOX", NULL);
		ctx->info.flags |= MAILBOX_NONEXISTENT;
	}
	if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0)
		ctx->info.flags |= MAILBOX_NONEXISTENT;
	else if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0)
		ctx->info.flags |= MAILBOX_NOSELECT;
	if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOINFERIORS) != 0)
		ctx->info.flags |= MAILBOX_NOINFERIORS;

	if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
			       MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) {
		mailbox_list_set_subscription_flags(ctx->ctx.list,
						    ctx->info.vname,
						    &ctx->info.flags);
	}

	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) {
		box = mailbox_alloc(ctx->ctx.list, ctx->info.vname, 0);
		mailbox_list_index_status_set_info_flags(box, node->uid,
							 &ctx->info.flags);
		mailbox_free(&box);
	}
}
Exemple #24
0
static int
cmd_expunge_box(struct doveadm_mail_cmd_context *_ctx,
		const struct mailbox_info *info,
		struct mail_search_args *search_args)
{
	struct expunge_cmd_context *ctx = (struct expunge_cmd_context *)_ctx;
	struct doveadm_mail_iter *iter;
	struct mailbox *box;
	struct mail *mail;
	enum mail_error error;
	int ret = 0;

	if (doveadm_mail_iter_init(_ctx, info, search_args, 0, NULL, FALSE,
				   &iter) < 0)
		return -1;

	while (doveadm_mail_iter_next(iter, &mail)) {
		if (doveadm_debug) {
			i_debug("expunge: box=%s uid=%u",
				info->vname, mail->uid);
		}
		mail_expunge(mail);
	}

	if (doveadm_mail_iter_deinit_keep_box(&iter, &box) < 0)
		ret = -1;
	else if (mailbox_sync(box, 0) < 0) {
		i_error("Syncing mailbox '%s' failed: %s",
			mailbox_get_vname(box),
			mailbox_get_last_internal_error(box, NULL));
		doveadm_mail_failed_mailbox(_ctx, box);
		ret = -1;
	}

	if (ctx->delete_empty_mailbox && ret == 0) {
		if (mailbox_delete_empty(box) < 0) {
			error = mailbox_get_last_mail_error(box);
			if (error != MAIL_ERROR_EXISTS) {
				i_error("Deleting mailbox '%s' failed: %s",
					mailbox_get_vname(box),
					mailbox_get_last_internal_error(box, NULL));
				doveadm_mail_failed_mailbox(_ctx, box);
				ret = -1;
			}
		} else {
			if (mailbox_set_subscribed(box, FALSE) < 0) {
				i_error("Unsubscribing mailbox '%s' failed: %s",
					mailbox_get_vname(box),
					mailbox_get_last_internal_error(box, NULL));
				doveadm_mail_failed_mailbox(_ctx, box);
				ret = -1;
			}
		}
	}
	mailbox_free(&box);
	return ret;
}
void mail_raw_close(struct mail_raw **mailr)
{
	mail_free(&(*mailr)->mail);
	mailbox_transaction_rollback(&(*mailr)->trans);
	mailbox_free(&(*mailr)->box);

	i_free(*mailr);
	*mailr = NULL;
}
Exemple #26
0
static void cmd_setmetadata_deinit(struct imap_setmetadata_context *ctx)
{
	ctx->cmd->client->input_lock = NULL;
	imap_parser_unref(&ctx->parser);
	if (ctx->trans != NULL)
		imap_metadata_transaction_rollback(&ctx->trans);
	if (ctx->box != NULL && ctx->box != ctx->cmd->client->mailbox)
		mailbox_free(&ctx->box);
	i_free(ctx->entry_name);
}
Exemple #27
0
void mailbox_guid_cache_refresh(struct mailbox_list *list)
{
	struct mailbox_list_iterate_context *ctx;
	const struct mailbox_info *info;
	struct mailbox *box;
	struct mailbox_metadata metadata;
	struct mailbox_guid_cache_rec *rec;
	uint8_t *guid_p;

	if (!hash_table_is_created(list->guid_cache)) {
		list->guid_cache_pool =
			pool_alloconly_create("guid cache", 1024*16);
		hash_table_create(&list->guid_cache, list->guid_cache_pool, 0,
				  guid_128_hash, guid_128_cmp);
	} else {
		hash_table_clear(list->guid_cache, TRUE);
		p_clear(list->guid_cache_pool);
	}
	list->guid_cache_invalidated = FALSE;
	list->guid_cache_updated = FALSE;
	list->guid_cache_errors = FALSE;

	ctx = mailbox_list_iter_init(list, "*",
				     MAILBOX_LIST_ITER_SKIP_ALIASES |
				     MAILBOX_LIST_ITER_NO_AUTO_BOXES);
	while ((info = mailbox_list_iter_next(ctx)) != NULL) {
		if ((info->flags &
		     (MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) != 0)
			continue;

		box = mailbox_alloc(list, info->vname, 0);
		if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
					 &metadata) < 0) {
			i_error("Couldn't get mailbox %s GUID: %s",
				info->vname, mailbox_get_last_internal_error(box, NULL));
			list->guid_cache_errors = TRUE;
		} else if ((rec = hash_table_lookup(list->guid_cache,
				(const uint8_t *)metadata.guid)) != NULL) {
			i_warning("Mailbox %s has duplicate GUID with %s: %s",
				  info->vname, rec->vname,
				  guid_128_to_string(metadata.guid));
		} else {
			rec = p_new(list->guid_cache_pool,
				    struct mailbox_guid_cache_rec, 1);
			memcpy(rec->guid, metadata.guid, sizeof(rec->guid));
			rec->vname = p_strdup(list->guid_cache_pool, info->vname);
			guid_p = rec->guid;
			hash_table_insert(list->guid_cache, guid_p, rec);
		}
		mailbox_free(&box);
	}
	if (mailbox_list_iter_deinit(&ctx) < 0)
		list->guid_cache_errors = TRUE;
}
static bool
dsync_is_valid_name(struct mail_namespace *ns, const char *vname)
{
	struct mailbox *box;
	bool ret;

	box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY);
	ret = mailbox_verify_create_name(box) == 0;
	mailbox_free(&box);
	return ret;
}
Exemple #29
0
static int
ns_mailbox_try_alloc(struct mail_namespace *ns, const guid_128_t guid,
		     struct mailbox **box_r)
{
	struct mailbox *box;
	enum mailbox_existence existence;
	int ret;

	box = mailbox_alloc_guid(ns->list, guid, 0);
	ret = mailbox_exists(box, FALSE, &existence);
	if (ret < 0) {
		mailbox_free(&box);
		return -1;
	}
	if (existence != MAILBOX_EXISTENCE_SELECT) {
		mailbox_free(&box);
		return 0;
	}
	*box_r = box;
	return 1;
}
static int
status_mailbox(struct status_cmd_context *ctx, const struct mailbox_info *info)
{
	struct mailbox *box;
	struct mailbox_status status;
	struct mailbox_metadata metadata;

	box = doveadm_mailbox_find(ctx->ctx.cur_mail_user, info->vname);
	if (mailbox_get_status(box, ctx->status_items, &status) < 0 ||
	    mailbox_get_metadata(box, ctx->metadata_items, &metadata) < 0) {
		doveadm_mail_failed_mailbox(&ctx->ctx, box);
		mailbox_free(&box);
		return -1;
	}
	if (!ctx->total_sum)
		status_output(ctx, box, &status, &metadata);
	else
		status_sum(ctx, &status, &metadata);
	mailbox_free(&box);
	return 0;
}