static int cmd_import_box_contents(struct doveadm_mail_iter *iter, struct mail *src_mail, struct mailbox *dest_box) { struct mail_storage *dest_storage = mailbox_get_storage(dest_box); struct mail_save_context *save_ctx; struct mailbox_transaction_context *dest_trans; const char *mailbox = mailbox_get_vname(dest_box); int ret = 0; dest_trans = mailbox_transaction_begin(dest_box, MAILBOX_TRANSACTION_FLAG_EXTERNAL); do { if (doveadm_debug) { i_debug("import: box=%s uid=%u", mailbox, src_mail->uid); } save_ctx = mailbox_save_alloc(dest_trans); if (mailbox_copy(&save_ctx, src_mail) < 0) { i_error("Copying box=%s uid=%u failed: %s", mailbox, src_mail->uid, mail_storage_get_last_error(dest_storage, NULL)); ret = -1; } } while (doveadm_mail_iter_next(iter, src_mail)); if (mailbox_transaction_commit(&dest_trans) < 0) { i_error("Committing copied mails to %s failed: %s", mailbox, mail_storage_get_last_error(dest_storage, NULL)); ret = -1; } return ret; }
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; }
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; }
void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src) { const char *name, *str; enum mail_error error; name = get_user_visible_mailbox_name(src); str = mail_storage_get_last_error(src->storage, &error); str = t_strdup_printf("%s (for backend mailbox %s)", str, name); mail_storage_set_error(dest->storage, error, str); }
static int ns_purge(struct doveadm_mail_cmd_context *ctx, struct mail_namespace *ns, struct mail_storage *storage) { if (mail_storage_purge(storage) < 0) { i_error("Purging namespace '%s' failed: %s", ns->prefix, mail_storage_get_last_error(storage, NULL)); doveadm_mail_failed_storage(ctx, storage); return -1; } return 0; }
static void mail_copy_set_failed(struct mail_save_context *ctx, struct mail *mail, const char *func) { const char *errstr; enum mail_error error; if (ctx->transaction->box->storage == mail->box->storage) return; errstr = mail_storage_get_last_error(mail->box->storage, &error); mail_storage_set_error(ctx->transaction->box->storage, error, t_strdup_printf("%s (%s)", errstr, func)); }
void client_send_untagged_storage_error(struct client *client, struct mail_storage *storage) { const char *error_string; enum mail_error error; error_string = mail_storage_get_last_error(storage, &error); client_send_line(client, t_strconcat("* NO ", error_string, NULL)); if (client->mailbox != NULL && mailbox_is_inconsistent(client->mailbox)) { /* we can't do forced CLOSE, so have to disconnect */ client_disconnect_with_error(client, "IMAP session state is inconsistent, please relogin."); } }
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; }
void client_send_storage_error(struct client_command_context *cmd, struct mail_storage *storage) { const char *error_string; enum mail_error error; error_string = mail_storage_get_last_error(storage, &error); client_send_tagline(cmd, imap_get_error_string(cmd, error_string, error)); if (cmd->client->mailbox != NULL && mailbox_is_inconsistent(cmd->client->mailbox)) { /* we can't do forced CLOSE, so have to disconnect */ client_disconnect_with_error(cmd->client, "IMAP session state is inconsistent, please relogin."); } }
static int snarf(struct mailbox *srcbox, struct mailbox *destbox) { struct mail_search_args *search_args; struct mail_search_context *search_ctx; struct mailbox_transaction_context *src_trans, *dest_trans; struct mail_save_context *save_ctx; struct mail *mail; enum mail_error error; int ret; /* make sure the destination mailbox has been opened */ if (mailbox_open(destbox) < 0) return -1; if (mailbox_sync(srcbox, MAILBOX_SYNC_FLAG_FULL_READ) < 0) return -1; src_trans = mailbox_transaction_begin(srcbox, 0); dest_trans = mailbox_transaction_begin(destbox, MAILBOX_TRANSACTION_FLAG_EXTERNAL); search_args = mail_search_build_init(); mail_search_build_add_all(search_args); search_ctx = mailbox_search_init(src_trans, search_args, NULL); mail_search_args_unref(&search_args); ret = 0; mail = mail_alloc(src_trans, MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY, NULL); while (mailbox_search_next(search_ctx, mail)) { if (mail->expunged) continue; save_ctx = mailbox_save_alloc(dest_trans); if (mailbox_copy(&save_ctx, mail) < 0 && !mail->expunged) { (void)mail_storage_get_last_error(destbox->storage, &error); /* if we failed because of out of disk space, just move those messages we managed to move so far. */ if (error != MAIL_ERROR_NOSPACE) ret = -1; break; } mail_expunge(mail); } mail_free(&mail); if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; /* commit the copied messages to the destination mailbox. if we crash between that and between expunging the messages from the source mailbox, we're left with duplicates. */ if (ret < 0) mailbox_transaction_rollback(&dest_trans); else if (mailbox_transaction_commit(&dest_trans) < 0) ret = -1; if (ret < 0) mailbox_transaction_rollback(&src_trans); else { if (mailbox_transaction_commit(&src_trans) < 0) ret = -1; } if (ret == 0) { if (mailbox_sync(srcbox, 0) < 0) ret = -1; } return ret; }