]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Add quota_mailbox_message_count setting
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 18 Jun 2024 09:30:28 +0000 (12:30 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 25 Jun 2024 10:43:32 +0000 (10:43 +0000)
src/plugins/quota/quota-private.h
src/plugins/quota/quota-status.c
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c
src/plugins/quota/quota.h

index 6ba3b812bfb8eeff6ba65e58b0e02144f1993b72..5bf76a7d3a401e4a8635892524b7461e6bc7f8ef 100644 (file)
@@ -29,6 +29,7 @@ struct quota_settings {
                const char **error_r);
 
        uoff_t max_mail_size;
+       unsigned int max_messages_per_mailbox;
        const char *quota_exceeded_msg;
        bool debug:1;
        bool initialized:1;
index 9175e3599d674a659657197e9adc94750310037d..041f75d07955275f1b173b98d6956a2365a0e011 100644 (file)
@@ -191,6 +191,7 @@ static void client_handle_request(struct quota_client *client)
                                                "quota_status_toolarge");
                        /* fall through */
                case QUOTA_ALLOC_RESULT_OVER_QUOTA:
+               case QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT:
                        if (value == NULL)
                                value = mail_user_plugin_getenv(user,
                                                "quota_status_overquota");
index a1d08ee58050cea9172bec3f731557db113c066d..efead36ea3d7bdb7d6c62cc48c4e533ca516c696 100644 (file)
@@ -60,6 +60,7 @@ static void quota_set_storage_error(struct quota_transaction_context *qt,
                mail_storage_set_error(storage, MAIL_ERROR_LIMIT, errstr);
                break;
        case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
+       case QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT:
        case QUOTA_ALLOC_RESULT_OVER_QUOTA:
                mail_storage_set_error(storage, MAIL_ERROR_NOQUOTA, errstr);
                break;
index b33f6cae00ef2413e438bde76e91dfafe4852091..6cdaca08cc5ec31c875578511b6f33d02d5144fc 100644 (file)
@@ -287,6 +287,8 @@ const char *quota_alloc_result_errstr(enum quota_alloc_result res,
        case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
        case QUOTA_ALLOC_RESULT_OVER_QUOTA:
                return qt->quota->set->quota_exceeded_msg;
+       case QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT:
+               return "Too many messages in the mailbox";
        }
        i_unreached();
 }
@@ -324,6 +326,19 @@ int quota_user_read_settings(struct mail_user *user,
                }
        }
 
+       const char *max_box_count =
+               mail_user_plugin_getenv(user, "quota_mailbox_message_count");
+       if (max_box_count != NULL) {
+               const char *error;
+               if (str_parse_uint(max_box_count,
+                                  &quota_set->max_messages_per_mailbox,
+                                  &error) < 0) {
+                       *error_r = t_strdup_printf(
+                               "quota_mailbox_message_count: %s", error);
+                       return -1;
+               }
+       }
+
        p_array_init(&quota_set->root_sets, pool, 4);
        if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0)
                i_unreached();
@@ -937,6 +952,7 @@ int quota_transaction_set_limits(struct quota_transaction_context *ctx,
                                 enum quota_get_result *error_result_r,
                                 const char **error_r)
 {
+       const struct quota_settings *set = ctx->quota->set;
        struct quota_root *const *roots;
        const char *mailbox_name, *error;
        unsigned int i, count;
@@ -1033,6 +1049,22 @@ int quota_transaction_set_limits(struct quota_transaction_context *ctx,
                        }
                }
        }
+
+       if (set->max_messages_per_mailbox != 0) {
+               struct mailbox_status status;
+               mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
+               if (status.messages <= set->max_messages_per_mailbox) {
+                       diff = set->max_messages_per_mailbox - status.messages;
+                       if (ctx->count_ceil > diff)
+                               ctx->count_ceil = diff;
+               } else {
+                       /* over quota */
+                       ctx->count_ceil = 0;
+                       diff = status.messages - set->max_messages_per_mailbox;
+                       if (ctx->count_over < diff)
+                               ctx->count_over = diff;
+               }
+       }
        return 0;
 }
 
@@ -1419,6 +1451,14 @@ static enum quota_alloc_result quota_default_test_alloc(
        if (!quota_transaction_is_over(ctx, size))
                return QUOTA_ALLOC_RESULT_OK;
 
+       if (ctx->quota->set->max_messages_per_mailbox != 0) {
+               struct mailbox_status status;
+               mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
+               unsigned int new_count = status.messages + ctx->count_used;
+               if (new_count >= ctx->quota->set->max_messages_per_mailbox)
+                       return QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT;
+       }
+
        /* limit reached. */
        roots = array_get(&ctx->quota->roots, &count);
        for (i = 0; i < count; i++) {
index 8de2d8ef6f2d753def78d9e8e52c15f96f707e94..d669a2684882cc3673a5ab1b90d9d3e459bf638a 100644 (file)
@@ -47,6 +47,8 @@ enum quota_alloc_result {
        QUOTA_ALLOC_RESULT_OVER_QUOTA,
        /* Mail size is larger than even the maximum allowed quota. */
        QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT,
+       /* Maximum number of messages per mailbox was reached */
+       QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT,
        /* Blocked by ongoing background quota calculation. */
        QUOTA_ALLOC_RESULT_BACKGROUND_CALC,
 };