]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
quota: Add quota_max_mail_size setting
authorMartti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
Wed, 22 Mar 2017 15:17:41 +0000 (17:17 +0200)
committerGitLab <gitlab@git.dovecot.net>
Thu, 23 Mar 2017 13:27:14 +0000 (15:27 +0200)
doc/example-config/conf.d/90-quota.conf
src/plugins/quota/Makefile.am
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 db1f718815d6cf8d93b574f2581c778139b48f62..40cde638b41bbdfe4e5dd955740ada674cb274c8 100644 (file)
@@ -22,6 +22,9 @@ plugin {
   # over quota, if the quota doesn't grow too high. Default is to allow as
   # long as quota will stay under 10% above the limit. Also allowed e.g. 10M.
   #quota_grace = 10%%
+
+  # Quota plugin can also limit the maximum accepted mail size.
+  #quota_max_mail_size = 100M
 }
 
 ##
index f5116348692aa15fcf22ef1b8e1ef1c0da74cd7f..0eb6d1a771049c354a30229de2418dc842baa059 100644 (file)
@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib-dict \
        -I$(top_srcdir)/src/lib-index \
        -I$(top_srcdir)/src/lib-mail \
+       -I$(top_srcdir)/src/lib-settings \
        -I$(top_srcdir)/src/lib-storage \
        -I$(top_srcdir)/src/lib-storage/index \
        -I$(top_srcdir)/src/lib-storage/index/maildir \
index 9e0eca4ff77321e568f7bc1d33e2f1f72225f54c..9de8d008ff53d2548656d49ff5812e695481ea7a 100644 (file)
@@ -25,6 +25,7 @@ struct quota_settings {
        enum quota_alloc_result (*test_alloc)(
                struct quota_transaction_context *ctx, uoff_t size);
 
+       uoff_t max_mail_size;
        const char *quota_exceeded_msg;
        bool debug:1;
        bool initialized:1;
index 9c1d3c255ecdbc42eab43e761f181392548cd5f3..9b1e101b3dd36318181ab6f3cdfefa414caad8bb 100644 (file)
@@ -102,6 +102,7 @@ static void client_handle_request(struct quota_client *client)
                        if (value == NULL)
                                value = "OK";
                        break;
+               case QUOTA_ALLOC_RESULT_OVER_MAXSIZE:
                /* even over maximum quota */
                case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
                        value = mail_user_plugin_getenv(user,
index 2b2a165493b5cfa6fcdedc2c857544d98ed5f544..0e3b9425e85a99d4e03c9f1c39d946bdaecfca37 100644 (file)
@@ -52,6 +52,9 @@ static void quota_set_storage_error(struct quota_transaction_context *qt,
 {
        const char *errstr = quota_alloc_result_errstr(res, qt);
        switch (res) {
+       case QUOTA_ALLOC_RESULT_OVER_MAXSIZE:
+               mail_storage_set_error(storage, MAIL_ERROR_LIMIT, errstr);
+               break;
        case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
        case QUOTA_ALLOC_RESULT_OVER_QUOTA:
                mail_storage_set_error(storage, MAIL_ERROR_NOQUOTA, errstr);
index 7247e2fbbebfc4ab17400ace65a2e017521e7675..b41ccfb610391db3523ca962ae72e97810c52ccf 100644 (file)
@@ -15,6 +15,7 @@
 #include "quota-fs.h"
 #include "llist.h"
 #include "program-client.h"
+#include "settings-parser.h"
 
 #include <sys/wait.h>
 
@@ -228,6 +229,9 @@ const char *quota_alloc_result_errstr(enum quota_alloc_result res,
                return "OK";
        case QUOTA_ALLOC_RESULT_TEMPFAIL:
                return "Internal quota calculation error";
+       case QUOTA_ALLOC_RESULT_OVER_MAXSIZE:
+               return "Mail size is larger than the maximum size allowed by "
+                      "server configuration";
        case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
        case QUOTA_ALLOC_RESULT_OVER_QUOTA:
                return qt->quota->set->quota_exceeded_msg;
@@ -256,6 +260,18 @@ int quota_user_read_settings(struct mail_user *user,
                quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
        quota_set->vsizes = mail_user_plugin_getenv(user, "quota_vsizes") != NULL;
 
+       const char *max_size = mail_user_plugin_getenv(user,
+                                                      "quota_max_mail_size");
+       if (max_size != NULL) {
+               const char *error = NULL;
+               if (settings_get_size(max_size, &quota_set->max_mail_size,
+                                       &error) < 0) {
+                       *error_r = t_strdup_printf("quota_max_mail_size: %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();
@@ -274,7 +290,8 @@ int quota_user_read_settings(struct mail_user *user,
                if (i_snprintf(root_name, sizeof(root_name), "quota%d", i) < 0)
                        i_unreached();
        }
-       if (array_count(&quota_set->root_sets) == 0) {
+       if (quota_set->max_mail_size == 0 &&
+           array_count(&quota_set->root_sets) == 0) {
                pool_unref(&pool);
                return 0;
        }
@@ -1216,6 +1233,11 @@ enum quota_alloc_result quota_test_alloc(struct quota_transaction_context *ctx,
 
        if (quota_transaction_set_limits(ctx) < 0)
                return QUOTA_ALLOC_RESULT_TEMPFAIL;
+
+       uoff_t max_size = ctx->quota->set->max_mail_size;
+       if (max_size > 0 && size > max_size)
+               return QUOTA_ALLOC_RESULT_OVER_MAXSIZE;
+
        if (ctx->no_quota_updates)
                return QUOTA_ALLOC_RESULT_OK;
        /* this is a virtual function mainly for trash plugin and similar,
index 6cc72df257b678991d20e66901b01f89ccc21fb5..293ccb41163ab96b0fb92332068089ef1dacbb6d 100644 (file)
@@ -33,6 +33,7 @@ enum quota_recalculate {
 enum quota_alloc_result {
        QUOTA_ALLOC_RESULT_OK,
        QUOTA_ALLOC_RESULT_TEMPFAIL,
+       QUOTA_ALLOC_RESULT_OVER_MAXSIZE,
        QUOTA_ALLOC_RESULT_OVER_QUOTA,
        /* Mail size is larger than even the maximum allowed quota. */
        QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT,