[Dovecot] [PATCH] quota-status: allow different action for messages that are too large (over maximum quota)

Ulrich Zehl ulrich-dovecot at topfen.net
Thu Aug 1 19:27:24 EEST 2013


This proposed patch to quota-status allows the administrator to return
different actions for messages that (a) cannot currently fit in the quota
(because there's not enough free space) and (b) are over the maximum quota
limit (and could not even be delivered if the mailbox was empty).

Configuration works like this:

plugin {
  quota_status_overquota = DEFER_IF_PERMIT 4.2.2 Mailbox full
  quota_status_toolarge  = REJECT 5.2.3 Message length exceeds administrative limit
}

The patch is backwards compatible: If quota_status_toolarge is not set,
quota_status_overquota is returned. No changes are necessary in setups
where the new feature is not desired.

The reason I developed this patch is: In my environment, I have mostly POP3
mailboxes, where condition (a) changes frequently (usually after each
login), but condition (b) will almost never change (users do not get
additional mailbox space often). Thus, I'd like to avoid bouncing mails
that could be delivered half an hour later.

This patch works for 2.2 and 2.1. (This assumes you have already applied
the trivial patch I sent earlier; otherwise patch(1) will report some
fuzz.)

What do you think of this?

Ulrich


--- a/src/plugins/quota/quota-status.c	2013-08-01 18:05:24.000000000 +0200
+++ b/src/plugins/quota/quota-status.c	2013-08-01 18:03:30.000000000 +0200
@@ -46,13 +46,12 @@
 }
 
 static int
-quota_check(struct mail_user *user, uoff_t mail_size, const char **error_r)
+quota_check(struct mail_user *user, uoff_t mail_size, const char **error_r, bool *too_large)
 {
 	struct quota_user *quser = QUOTA_USER_CONTEXT(user);
 	struct mail_namespace *ns;
 	struct mailbox *box;
 	struct quota_transaction_context *ctx;
-	bool too_large;
 	int ret;
 
 	if (quser == NULL) {
@@ -64,7 +63,7 @@
 	box = mailbox_alloc(ns->list, "INBOX", 0);
 
 	ctx = quota_transaction_begin(box);
-	ret = quota_test_alloc(ctx, I_MAX(1, mail_size), &too_large);
+	ret = quota_test_alloc(ctx, I_MAX(1, mail_size), too_large);
 	quota_transaction_rollback(&ctx);
 
 	mailbox_free(&box);
@@ -82,6 +81,7 @@
 	struct mail_storage_service_user *service_user;
 	struct mail_user *user;
 	const char *value = NULL, *error;
+	bool too_large;
 	int ret;
 
 	if (client->recipient == NULL) {
@@ -98,14 +98,21 @@
 	if (ret == 0) {
 		value = nouser_reply;
 	} else if (ret > 0) {
-		if ((ret = quota_check(user, client->size, &error)) > 0) {
+		if ((ret = quota_check(user, client->size, &error, &too_large)) > 0) {
 			/* under quota */
 			value = mail_user_plugin_getenv(user, "quota_status_success");
 			if (value == NULL)
 				value = "OK";
 		} else if (ret == 0) {
-			/* over quota */
-			value = mail_user_plugin_getenv(user, "quota_status_overquota");
+			if (too_large == TRUE) {
+				/* even over maximum quota */
+				value = mail_user_plugin_getenv(user, "quota_status_toolarge");
+				if (value == NULL) /* backwards compatibility */
+					value = mail_user_plugin_getenv(user, "quota_status_overquota");
+			} else {
+				/* over quota */
+				value = mail_user_plugin_getenv(user, "quota_status_overquota");
+			}
 			if (value == NULL)
 				value = t_strdup_printf("554 5.2.2 %s", error);
 		}


More information about the dovecot mailing list