Пример #1
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;
}
Пример #2
0
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;
}
int dsync_brain_mailbox_tree_sync_change(struct dsync_brain *brain,
			const struct dsync_mailbox_tree_sync_change *change,
			enum mail_error *error_r)
{
	struct mailbox *box = NULL, *destbox;
	const char *errstr, *func_name = NULL, *storage_name;
	enum mail_error error;
	int ret = -1;

	if (brain->backup_send) {
		i_assert(brain->no_backup_overwrite);
		return 0;
	}

	switch (change->type) {
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX:
		/* make sure we're deleting the correct mailbox */
		ret = dsync_brain_mailbox_alloc(brain, change->mailbox_guid,
						&box, &errstr, error_r);
		if (ret < 0) {
			i_error("Mailbox sync: Couldn't allocate mailbox GUID %s: %s",
				guid_128_to_string(change->mailbox_guid), errstr);
			return -1;
		}
		if (ret == 0) {
			if (brain->debug) {
				i_debug("brain %c: Change during sync: "
					"Mailbox GUID %s deletion conflict: %s",
					brain->master_brain ? 'M' : 'S',
					guid_128_to_string(change->mailbox_guid), errstr);
			}
			brain->changes_during_sync = TRUE;
			return 0;
		}
		break;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR:
		storage_name = mailbox_list_get_storage_name(change->ns->list,
							     change->full_name);
		if (mailbox_list_delete_dir(change->ns->list, storage_name) == 0)
			return 0;

		errstr = mailbox_list_get_last_error(change->ns->list, &error);
		if (error == MAIL_ERROR_NOTFOUND ||
		    error == MAIL_ERROR_EXISTS) {
			if (brain->debug) {
				i_debug("brain %c: Change during sync: "
					"Mailbox %s mailbox_list_delete_dir conflict: %s",
					brain->master_brain ? 'M' : 'S',
					change->full_name, errstr);
			}
			brain->changes_during_sync = TRUE;
			return 0;
		} else {
			i_error("Mailbox sync: mailbox_list_delete_dir failed: %s",
				errstr);
			*error_r = error;
			return -1;
		}
	default:
		box = mailbox_alloc(change->ns->list, change->full_name, 0);
		break;
	}
	switch (change->type) {
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_BOX:
		ret = sync_create_box(brain, box, change->mailbox_guid,
				      change->uid_validity, error_r);
		mailbox_free(&box);
		return ret;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_DIR:
		ret = mailbox_create(box, NULL, TRUE);
		if (ret < 0 &&
		    mailbox_get_last_mail_error(box) == MAIL_ERROR_EXISTS) {
			/* it doesn't matter if somebody else created this
			   directory or we automatically did while creating its
			   child mailbox. it's there now anyway and we don't
			   gain anything by treating this failure any
			   differently from success. */
			ret = 0;
		}
		func_name = "mailbox_create";
		break;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX:
		ret = mailbox_delete(box);
		func_name = "mailbox_delete";
		break;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR:
		i_unreached();
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_RENAME:
		destbox = mailbox_alloc(change->ns->list,
					change->rename_dest_name, 0);
		ret = mailbox_rename(box, destbox);
		func_name = "mailbox_rename";
		mailbox_free(&destbox);
		break;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_SUBSCRIBE:
		ret = mailbox_set_subscribed(box, TRUE);
		func_name = "mailbox_set_subscribed";
		break;
	case DSYNC_MAILBOX_TREE_SYNC_TYPE_UNSUBSCRIBE:
		ret = mailbox_set_subscribed(box, FALSE);
		func_name = "mailbox_set_subscribed";
		break;
	}
	if (ret < 0) {
		errstr = mailbox_get_last_error(box, &error);
		if (error == MAIL_ERROR_EXISTS ||
		    error == MAIL_ERROR_NOTFOUND) {
			/* mailbox was already created or was already deleted.
			   let the next sync figure out what to do */
			if (brain->debug) {
				i_debug("brain %c: Change during sync: "
					"Mailbox %s %s conflict: %s",
					brain->master_brain ? 'M' : 'S',
					mailbox_get_vname(box),
					func_name, errstr);
			}
			brain->changes_during_sync = TRUE;
			ret = 0;
		} else {
			i_error("Mailbox %s sync: %s failed: %s",
				mailbox_get_vname(box), func_name, errstr);
			*error_r = error;
		}
	}
	mailbox_free(&box);
	return ret;
}