mail-storage.c revision fe9459ab43300c912dc4b16b8872411337f3a25f
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenextern struct mail_search_register *mail_search_register_imap;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenextern struct mail_search_register *mail_search_register_human;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_search_register_deinit(&mail_search_register_human);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_search_register_deinit(&mail_search_register_imap);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* append it after the list, so the autodetection order is correct */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int i, count;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen classes = array_get(&mail_storage_classes, &count);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (i = 0; i < count; i++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int i, count;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen classes = array_get(&mail_storage_classes, &count);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (i = 0; i < count; i++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int i, count;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen classes = array_get(&mail_storage_classes, &count);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (i = 0; i < count; i++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *p;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* no autodetection if the storage driver is given. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen enum mail_storage_flags flags, const char **error_r)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* no mail_location, autodetect */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* explicit autodetection with "auto" driver. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* handle the same as with driver=NULL */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen storage_class = mail_user_get_storage_class(ns->user, driver);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* no root directory given. is this allowed? */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* autodetection should take care of this */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen /* root not required for this storage */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* root not required for this layout */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen "Mail storage autodetection failed with home=%s", home);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen } else if (strncmp(ns->set->location, "auto:", 5) == 0) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen "Autodetection failed for %s (home=%s)",
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen "Ambiguous mail location setting, "
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen "don't know what to do with it: %s "
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen "(try prefixing it with mbox: or maildir:)",
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenmail_storage_verify_root(const char *root_dir, bool autocreate,
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen const char **error_r)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen } else if (!autocreate) {
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen "Root mail directory doesn't exist: %s", root_dir);
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainen /* doesn't exist */
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenmail_storage_create_root(struct mailbox_list *list,
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen enum mail_storage_flags flags, const char **error_r)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen /* storage doesn't use directories (e.g. shared root) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* we don't need to verify, but since debugging is
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen enabled, check and log if the root doesn't exist */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (mail_storage_verify_root(root_dir, FALSE, &error) < 0) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen i_debug("Namespace %s: Creating storage despite: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen autocreate = (flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_storage_verify_root(root_dir, autocreate, error_r);
aa62d8779ce53900c2f09bf2ff6fa790bc9f6a89Timo Sirainen ret = mailbox_list_try_mkdir_root(list, root_dir,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainenmail_storage_match_class(struct mail_storage *storage,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (strcmp(storage->name, storage_class->name) != 0)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen strcmp(storage->unique_root_dir, set->root_dir) != 0)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen /* allow multiple independent shared namespaces */
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen struct mail_storage *storage = user->storages;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen for (; storage != NULL; storage = storage->next) {
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen if (mail_storage_match_class(storage, storage_class, set))
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenint mail_storage_create_full(struct mail_namespace *ns, const char *driver,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen const char *data, enum mail_storage_flags flags,
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen const char **error_r)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen struct mail_storage *storage_class, *storage = NULL;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen const char *p;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen header MD5 sums stored even if we're not running POP3
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen right now. */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* autodetect */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* internal shared namespace */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen mail_storage_set_autodetection(&data, &driver);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (mailbox_list_settings_parse(ns->user, data, &list_set,
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* first storage for namespace */
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen if (mail_storage_is_mailbox_file(storage_class))
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_LIST_DELETES) != 0)
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen /* using an existing storage */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
b3bb775c6b735a7f6021dea799601fbfdb656e58Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen enum mail_storage_flags flags, const char **error_r)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return mail_storage_create_full(ns, driver, ns->set->location,
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen /* set *_storage=NULL only after calling destroy() callback.
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen for example mdbox wants to access ns->storage */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_panic("Trying to deinit storage without freeing mailbox %s",
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen i_panic("Trying to deinit storage before freeing its objects");
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen if (array_is_created(&storage->error_stack)) {
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen i_assert(array_count(&storage->error_stack) == 0);
9a099a65160987349f441c82ab0e38f32b747adbTimo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage)
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen const char *str;
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen const char *fmt, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* critical errors may contain sensitive data, so let user
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen see only "Internal error" with a timestamp to make it
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen easier to look from log files the actual error message. */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen const char *str;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen str = mail_storage_get_last_error(src, &error);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen const char *str;
43955c82f9f52c969c777b3da00bc170183dfdf2Timo Sirainen str = mailbox_list_get_last_error(list, &error);
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen mail_storage_set_internal_error(box->storage);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenmail_storage_get_settings(struct mail_storage *storage)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
7c449f545b10daa47027552f98d916a9805da662Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* We get here only in error situations, so we have to return some
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen error. If storage->error is NONE, it means we forgot to set it at
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo Sirainen some point.. */
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen return storage->error_string != NULL ? storage->error_string :
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen "BUG: Unknown internal error";
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen /* This shouldn't happen.. */
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainenconst char *mailbox_get_last_error(struct mailbox *box,
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainen return mail_storage_get_last_error(box->storage, error_r);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenenum mail_error mailbox_get_last_mail_error(struct mailbox *box)
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen mail_storage_get_last_error(box->storage, &error);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid mail_storage_last_error_push(struct mail_storage *storage)
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen err = array_append_space(&storage->error_stack);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen err->error_string = i_strdup(storage->error_string);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_storage_last_error_pop(struct mail_storage *storage)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen unsigned int count = array_count(&storage->error_stack);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen array_delete(&storage->error_stack, count-1, 1);
7c65a07e04f28f2a881d83989f85f9ad0e87a7b4Timo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen /* debugging is enabled - admin may be debugging a
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen (permission) problem, so return FALSE to get the caller to
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen log the full error message. */
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainen mail_storage_set_error(storage, error, error_string);
7895c4845da515b0aa9bb156674a1fca40803f44Timo Sirainenmailbox_settings_find(struct mail_namespace *ns, const char *vname)
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen /* namespace prefix itself */
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen /* make sure INBOX shows up in uppercase everywhere. do this
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainen regardless of whether we're in inbox=yes namespace, because
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen clients expect INBOX to be case insensitive regardless of
8d889b6d842e96ecbe7b6493920bbb6df8e0ed30Timo Sirainen server's internal configuration. */
0ed9ccd0047f75df54a49bc117ca301eb398e447Timo Sirainen else if (vname[5] != mail_namespace_get_sep(list->ns))
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen /* not INBOX prefix */ ;
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
7d7f4648f72b8c70928e04514b0d93dad0ba6fd5Timo Sirainen "Invalid server configuration: "
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen "Namespace prefix=%s must be uppercase INBOX",
3a854fc26bcccb0398f0a9a6fa72db1a4ab8f0b8Timo Sirainen vname = t_strconcat("INBOX", vname + 5, NULL);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen /* do a delayed failure at mailbox_open() */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen storage = mail_namespace_get_default_storage(list->ns);
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen errstr = mailbox_list_get_last_error(new_list, &open_error);
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen box->set = mailbox_settings_find(new_list->ns, vname);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen mail_storage_set_error(storage, open_error, errstr);
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen DLLIST_PREPEND(&box->storage->mailboxes, box);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainenstruct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen /* GUID mismatch, refresh cache and try again */
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen /* successfully opened the correct mailbox */
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen "Couldn't verify mailbox GUID: %s",
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen vname = t_strdup_printf("(error in mailbox with GUID=%s)",
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainenstatic bool mailbox_is_autocreated(struct mailbox *box)
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainenstatic int mailbox_autocreate(struct mailbox *box)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen "Failed to autocreate mailbox %s: %s",
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen "Failed to autosubscribe to mailbox %s: %s",
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen box->vname, mailbox_get_last_error(box, NULL));
305465bb1a4c5d90c4b4e2c2790eb05fa4ebc41eTimo Sirainenstatic int mailbox_autocreate_and_reopen(struct mailbox *box)
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen !box->storage->user->inbox_open_error_logged) {
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen box->storage->user->inbox_open_error_logged = TRUE;
73c76fa7340a107229c530196d026aadeae979c7Timo Sirainen "Opening INBOX failed: %s",
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainenmailbox_name_verify_separators(const char *vname, char sep,
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen const char **error_r)
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen unsigned int i;
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen /* Make sure the vname is correct: non-empty, doesn't begin or end
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen with separator and no adjacent separators */
38df0cacce475112991e60d796f8f2105c616f01Timo Sirainen *error_r = "Has adjacent hierarchy separators";
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen if (prev_sep && i > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mailbox_verify_name(struct mailbox *box)
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen /* this is INBOX - don't bother with further checks */
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(box->list);
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen /* vname is either "namespace/box" or "namespace" */
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen if (strncmp(vname, ns->prefix, ns->prefix_len-1) != 0 ||
65d6ca3fb5450b81df0190d9e9aa62c00fed5116Timo Sirainen vname[ns->prefix_len-1] != ns->prefix[ns->prefix_len-1])) {
4d938f46f4f956ecb802c30ca771922f5539a660Timo Sirainen /* User input shouldn't normally be able to get us in
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen here. The main reason this isn't an assert is to
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen allow any input at all to mailbox_verify_*_name()
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen without crashing. */
ba3d9eeb0bec6ed8465d68fa2480ad085559b580Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen "Missing namespace prefix '%s'",
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen /* "namespace/" isn't a valid mailbox name. */
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen "Invalid mailbox name");
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen if (ns_sep != list_sep && box->list->set.escape_char == '\0' &&
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen "Character not allowed in mailbox name: '%c'", list_sep));
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen !box->storage->set->mail_full_filesystem_access) {
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen "Invalid mailbox name: Begins with hierarchy separator");
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen if (!mailbox_name_verify_separators(vname, ns_sep, &error) ||
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen !mailbox_list_is_valid_name(box->list, box->name, &error)) {
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen t_strdup_printf("Invalid mailbox name: %s", error));
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainenstatic int mailbox_verify_existing_name(struct mailbox *box)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Make sure box->_path is set, so mailbox_get_path() works from
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen now on. Note that this may also fail with some backends if the
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen mailbox doesn't exist. */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (box->storage->error != MAIL_ERROR_NOTFOUND ||
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen /* if this is an autocreated mailbox, create it now */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool mailbox_name_has_control_chars(const char *name)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen const char *p;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if ((unsigned char)*p < ' ')
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenvoid mailbox_skip_create_name_restrictions(struct mailbox *box, bool set)
d22301419109ed4a38351715e6760011421dadecTimo Sirainenint mailbox_verify_create_name(struct mailbox *box)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* mailbox_alloc() already checks that vname is valid UTF8,
82c70897a2d0e6144ecc56ca8e0eb9fff768f2c5Timo Sirainen so we don't need to verify that.
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen check vname instead of storage name, because vname is what is
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen visible to users, while storage name may be a fixed length GUID. */
c2cb5e469cd11759da22d82083d4fbb564d06dfaTimo Sirainen if (mailbox_name_has_control_chars(box->vname)) {
4d938f46f4f956ecb802c30ca771922f5539a660Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen "Control characters not allowed in new mailbox names");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen "Mailbox name too long");
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen /* check individual component names, too */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen const char sep = mailbox_list_get_hierarchy_sep(box->list);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen while((name = strchr(old_name, sep)) != NULL) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen "Mailbox name too long");
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen if (strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen "Mailbox name too long");
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* if prefix has multiple hierarchies, match
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen any of the hierarchies */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (strncmp(ns->prefix, name, name_len) == 0 &&
a3d22d3cb0e5436128ca7287cedc921f1789b2c8Timo Sirainen ns->prefix[name_len] == mail_namespace_get_sep(ns))
case MAIL_ERROR_NOTFOUND:
int ret;
case MAIL_ERROR_NOTFOUND:
MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
T_BEGIN {
} T_END;
} T_END;
if (ret < 0) {
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
const char *index_dir;
int ret;
&index_dir);
if (ret <= 0)
int ret;
return ret;
const char *name1;
return FALSE;
return TRUE;
bool directory)
int ret;
if (ret == 0)
return ret;
int ret;
return ret;
int ret;
if (ret < 0)
if (del)
if (ret < 0)
int ret;
return ret;
int ret;
return ret;
const char **error_r)
return TRUE;
return FALSE;
return FALSE;
return TRUE;
const char **error_r)
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret = 0;
return ret;
struct mail_namespace *
return FALSE;
i_unreached();
struct mailbox_sync_context *
T_BEGIN {
} T_END;
return ctx;
const char *errormsg;
int ret;
if (ret == 0)
return ret;
struct mail_search_context *
int ret;
return ret;
bool tryagain;
if (!tryagain)
return FALSE;
return TRUE;
return FALSE;
return TRUE;
int ret;
if (ret < 0)
return ret;
struct mailbox_transaction_context *
return trans;
int ret;
return ret;
int ret;
T_BEGIN {
} T_END;
return ret;
struct mailbox *
return t->box;
struct mail_save_context *
T_BEGIN {
} T_END;
return ctx;
const char *const *keywords_list;
const char *envelope)
unsigned int order)
int ret;
} else T_BEGIN {
} T_END;
if (ret < 0) {
int ret;
T_BEGIN {
} T_END;
return ret;
int ret;
T_BEGIN {
} T_END;
if (pvt_flags != 0)
t->save_count++;
return ret;
T_BEGIN {
} T_END;
struct mailbox_transaction_context *
int ret;
T_BEGIN {
} T_END;
if (ret == 0) {
if (pvt_flags != 0)
t->save_count++;
return ret;
int ret;
return ret;
const char **path_r)
int ret;
if (ret < 0) {
return ret;
int *fd_r)
int fd;
const char *root_dir;
int ret;
return ret;
&mail_dir) < 0)
unsigned int secs)
#ifndef MMAP_CONFLICTS_WRITE
return index_flags;
unsigned int secs;
const char *error;