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; }
int client_enable(struct client *client, enum mailbox_feature features) { struct mailbox_status status; int ret; if ((client->enabled_features & features) == features) return 0; client->enabled_features |= features; if (client->mailbox == NULL) return 0; ret = mailbox_enable(client->mailbox, features); if ((features & MAILBOX_FEATURE_CONDSTORE) != 0 && ret == 0) { /* CONDSTORE being enabled while mailbox is selected. Notify client of the latest HIGHESTMODSEQ. */ ret = mailbox_get_status(client->mailbox, STATUS_HIGHESTMODSEQ, &status); if (ret == 0) { client_send_line(client, t_strdup_printf( "* OK [HIGHESTMODSEQ %llu] Highest", (unsigned long long)status.highest_modseq)); } } if (ret < 0) { client_send_untagged_storage_error(client, mailbox_get_storage(client->mailbox)); } return ret; }
static int index_mailbox_precache(struct master_connection *conn, struct mailbox *box) { struct mail_storage *storage = mailbox_get_storage(box); const char *username = mail_storage_get_user(storage)->username; const char *box_vname = mailbox_get_vname(box); struct mailbox_status status; struct mailbox_transaction_context *trans; struct mail_search_args *search_args; struct mail_search_context *ctx; struct mail *mail; struct mailbox_metadata metadata; uint32_t seq; char percentage_str[2+1+1]; unsigned int counter = 0, max, percentage, percentage_sent = 0; int ret = 0; if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS, &metadata) < 0 || mailbox_get_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ, &status) < 0) return -1; seq = status.last_cached_seq + 1; trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC); search_args = mail_search_build_init(); mail_search_build_add_seqset(search_args, seq, status.messages); ctx = mailbox_search_init(trans, search_args, NULL, metadata.precache_fields, NULL); mail_search_args_unref(&search_args); max = status.messages - seq + 1; while (mailbox_search_next(ctx, &mail)) { mail_precache(mail); if (++counter % 100 == 0) { percentage = counter*100 / max; if (percentage != percentage_sent && percentage < 100) { percentage_sent = percentage; if (i_snprintf(percentage_str, sizeof(percentage_str), "%u\n", percentage) < 0) i_unreached(); (void)write_full(conn->fd, percentage_str, strlen(percentage_str)); } indexer_worker_refresh_proctitle(username, box_vname, counter, max); } } if (mailbox_search_deinit(&ctx) < 0) ret = -1; if (mailbox_transaction_commit(&trans) < 0) ret = -1; if (ret == 0) { i_info("Indexed %u messages in %s", counter, mailbox_get_vname(box)); } return ret; }
static int dsync_mailbox_tree_get_selectable(struct mailbox *box, struct mailbox_metadata *metadata_r, struct mailbox_status *status_r) { /* try the fast path */ if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, metadata_r) < 0) return -1; if (mailbox_get_status(box, STATUS_UIDVALIDITY | STATUS_UIDNEXT, status_r) < 0) return -1; i_assert(!guid_128_is_empty(metadata_r->guid)); if (status_r->uidvalidity != 0) return 0; /* no UIDVALIDITY assigned yet. syncing a mailbox should add it. */ if (mailbox_sync(box, 0) < 0) return -1; if (mailbox_get_status(box, STATUS_UIDVALIDITY | STATUS_UIDNEXT, status_r) < 0) return -1; i_assert(status_r->uidvalidity != 0); return 0; }
static int dsync_box_get(struct mailbox *box, struct dsync_mailbox *dsync_box_r) { const enum mailbox_status_items status_items = STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_FIRST_RECENT_UID | STATUS_HIGHESTMODSEQ | STATUS_HIGHESTPVTMODSEQ; const enum mailbox_metadata_items metadata_items = MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID; struct mailbox_status status; struct mailbox_metadata metadata; const char *errstr; enum mail_error error; /* get metadata first, since it may autocreate the mailbox */ if (mailbox_get_metadata(box, metadata_items, &metadata) < 0 || mailbox_get_status(box, status_items, &status) < 0) { errstr = mailbox_get_last_error(box, &error); if (error == MAIL_ERROR_NOTFOUND || error == MAIL_ERROR_NOTPOSSIBLE) { /* Mailbox isn't selectable, try the next one. We should have already caught \Noselect mailboxes, but check them anyway here. The NOTPOSSIBLE check is mainly for invalid mbox files. */ return 0; } i_error("Failed to access mailbox %s: %s", mailbox_get_vname(box), errstr); return -1; } i_assert(status.uidvalidity != 0 || status.messages == 0); memset(dsync_box_r, 0, sizeof(*dsync_box_r)); memcpy(dsync_box_r->mailbox_guid, metadata.guid, sizeof(dsync_box_r->mailbox_guid)); dsync_box_r->uid_validity = status.uidvalidity; dsync_box_r->uid_next = status.uidnext; dsync_box_r->messages_count = status.messages; dsync_box_r->first_recent_uid = status.first_recent_uid; dsync_box_r->highest_modseq = status.highest_modseq; dsync_box_r->highest_pvt_modseq = status.highest_pvt_modseq; dsync_box_r->cache_fields = *metadata.cache_fields; dsync_box_r->have_guids = status.have_guids; dsync_box_r->have_save_guids = status.have_save_guids; dsync_box_r->have_only_guid128 = status.have_only_guid128; return 1; }
static int quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns, const char *vname, uint64_t *bytes, uint64_t *count) { struct quota_rule *rule; struct mailbox *box; struct mailbox_metadata metadata; struct mailbox_status status; enum mail_error error; const char *errstr; int ret; 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 ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NOQUOTA) != 0) { /* quota doesn't exist for this mailbox/storage */ ret = 0; } else if (mailbox_get_metadata(box, root->quota->set->vsizes ? MAILBOX_METADATA_VIRTUAL_SIZE : MAILBOX_METADATA_PHYSICAL_SIZE, &metadata) < 0 || mailbox_get_status(box, STATUS_MESSAGES, &status) < 0) { errstr = mailbox_get_last_error(box, &error); if (error == MAIL_ERROR_TEMP) { i_error("quota: Couldn't get size of mailbox %s: %s", vname, errstr); ret = -1; } else { /* non-temporary error, e.g. ACLs denied access. */ ret = 0; } } else { ret = 1; *bytes += root->quota->set->vsizes ? metadata.virtual_size : metadata.physical_size; *count += status.messages; } mailbox_free(&box); return ret; }
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; }
int imap_status_get(struct client_command_context *cmd, struct mail_namespace *ns, const char *mailbox, const struct imap_status_items *items, struct imap_status_result *result_r) { struct client *client = cmd->client; struct mailbox *box; const char *errstr; int ret = 0; if (client->mailbox != NULL && mailbox_equals(client->mailbox, ns, mailbox)) { /* this mailbox is selected */ box = client->mailbox; } else { /* open the mailbox */ box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY); mailbox_set_reason(box, "STATUS"); if (client->enabled_features != 0) (void)mailbox_enable(box, client->enabled_features); } if ((items->status & STATUS_HIGHESTMODSEQ) != 0) (void)client_enable(client, MAILBOX_FEATURE_CONDSTORE); ret = mailbox_get_status(box, items->status, &result_r->status); if (items->metadata != 0 && ret == 0) { ret = mailbox_get_metadata(box, items->metadata, &result_r->metadata); } if (ret < 0) { errstr = mailbox_get_last_error(box, &result_r->error); result_r->errstr = imap_get_error_string(cmd, errstr, result_r->error); } if (box != client->mailbox) mailbox_free(&box); return ret; }
static int index_mailbox_precache(struct master_connection *conn, struct mailbox *box) { struct mail_storage *storage = mailbox_get_storage(box); const char *username = mail_storage_get_user(storage)->username; const char *box_vname = mailbox_get_vname(box); struct mailbox_status status; struct mailbox_transaction_context *trans; struct mail_search_args *search_args; struct mail_search_context *ctx; struct mail *mail; struct mailbox_metadata metadata; uint32_t seq, first_uid = 0, last_uid = 0; char percentage_str[2+1+1]; unsigned int counter = 0, max, percentage, percentage_sent = 0; int ret = 0; if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS, &metadata) < 0) { i_error("Mailbox %s: Precache-fields lookup failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); return -1; } if (mailbox_get_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ, &status) < 0) { i_error("Mailbox %s: Status lookup failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); return -1; } seq = status.last_cached_seq + 1; trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC, "indexing"); search_args = mail_search_build_init(); mail_search_build_add_seqset(search_args, seq, status.messages); ctx = mailbox_search_init(trans, search_args, NULL, metadata.precache_fields, NULL); mail_search_args_unref(&search_args); max = status.messages + 1 - seq; while (mailbox_search_next(ctx, &mail)) { if (first_uid == 0) first_uid = mail->uid; last_uid = mail->uid; mail_precache(mail); if (++counter % 100 == 0) { percentage = counter*100 / max; if (percentage != percentage_sent && percentage < 100) { percentage_sent = percentage; if (i_snprintf(percentage_str, sizeof(percentage_str), "%u\n", percentage) < 0) i_unreached(); (void)write_full(conn->fd, percentage_str, strlen(percentage_str)); } indexer_worker_refresh_proctitle(username, box_vname, counter, max); } } if (mailbox_search_deinit(&ctx) < 0) { i_error("Mailbox %s: Mail search failed: %s", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL)); ret = -1; } const char *uids = first_uid == 0 ? "" : t_strdup_printf(" (UIDs %u..%u)", first_uid, last_uid); if (mailbox_transaction_commit(&trans) < 0) { i_error("Mailbox %s: Transaction commit failed: %s" " (attempted to index %u messages%s)", mailbox_get_vname(box), mailbox_get_last_internal_error(box, NULL), counter, uids); ret = -1; } else { i_info("Indexed %u messages in %s%s", counter, mailbox_get_vname(box), uids); } return ret; }