]> 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)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 27 Mar 2017 09:57:38 +0000 (12:57 +0300)
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 cdc06c7bfbcecd15b2f352961ff69399bec29fee..329cf4719b3dc2514daf10a9f730676d55974e35 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 a9184c8a875b97d05c1c5832ea8404ce71ed1def..ba7ba3d943e34f25d8f6cde392f1ced50284716e 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;
        unsigned int debug:1;
        unsigned int initialized:1;
index 35d59dd92401d2eb2f7874919891b14a7abdaedf..b1438ac0a704f35b4ad48b5a4a8ba2b0930c8b8a 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 f19612062ec89c10061d0dec7fd6c7cd6426eaec..fe85f4ed295cb46a9de763ed251fd53426786a60 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 bcc8ea4fbeaad92946e1dd493681cc9aec6f978a..068185921b0d7fbe996e7ab90c6ca31d9873abd9 100644 (file)
@@ -13,6 +13,7 @@
 #include "mailbox-list-private.h"
 #include "quota-private.h"
 #include "quota-fs.h"
+#include "settings-parser.h"
 
 #include <sys/wait.h>
 
@@ -226,6 +227,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;
@@ -254,6 +258,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();
@@ -272,7 +288,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;
        }
@@ -1211,6 +1228,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,