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); }