changeset 21811:aadb3940e4df

quota: Add quota_max_mail_size setting
author Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
date Wed, 22 Mar 2017 17:17:41 +0200
parents c6e5b4a3890a
children 8a1d6c2f9313
files 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
diffstat 7 files changed, 33 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/doc/example-config/conf.d/90-quota.conf	Thu Mar 23 10:16:30 2017 +0200
+++ b/doc/example-config/conf.d/90-quota.conf	Wed Mar 22 17:17:41 2017 +0200
@@ -22,6 +22,9 @@
   # 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
 }
 
 ##
--- a/src/plugins/quota/Makefile.am	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/Makefile.am	Wed Mar 22 17:17:41 2017 +0200
@@ -10,6 +10,7 @@
 	-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 \
--- a/src/plugins/quota/quota-private.h	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/quota-private.h	Wed Mar 22 17:17:41 2017 +0200
@@ -25,6 +25,7 @@
 	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;
--- a/src/plugins/quota/quota-status.c	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/quota-status.c	Wed Mar 22 17:17:41 2017 +0200
@@ -102,6 +102,7 @@
 			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,
--- a/src/plugins/quota/quota-storage.c	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/quota-storage.c	Wed Mar 22 17:17:41 2017 +0200
@@ -52,6 +52,9 @@
 {
 	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);
--- a/src/plugins/quota/quota.c	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/quota.c	Wed Mar 22 17:17:41 2017 +0200
@@ -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 @@
 		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 @@
 		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 @@
 		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 @@
 
 	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,
--- a/src/plugins/quota/quota.h	Thu Mar 23 10:16:30 2017 +0200
+++ b/src/plugins/quota/quota.h	Wed Mar 22 17:17:41 2017 +0200
@@ -33,6 +33,7 @@
 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,