This is something Timo hacked up for me a few years ago and I realised should be on the list in case anyone else wants them.
The following patches will limit maildir folders to 4000 messages on Dovecot 2.0.* and 2.1.*
The Specfile patch is against the Cityfan Redhat EL5 SRPM but is likely to work on most build platforms
Changing the message limit requires a recompile. It's brutal and ugly but it prevents users overloading FSes that can't cope with huge numbers of files (EG: GFS2)
--- dovecot.spec-2.1.6 2012-05-23 11:39:11.000000000 +0100 +++ dovecot.spec-2.1.6-mssl 2012-05-24 18:46:37.000000000 +0100 @@ -32,7 +32,7 @@ # Remember to bump dovecot_release and sieve_release with every release %global dovecot_epoch 1 %global dovecot_version 2.1.6 -%global dovecot_release %{?prerel:0.}2.0%{?prerel:.%{prerel}}.cf.%{__distinit}%{__distvers} +%global dovecot_release %{?prerel:0.}2.0%{?prerel:.%{prerel}}.cf.MSSL.%{__distinit}%{__distvers} %global sieve_epoch 3 %global sieve_version 0.3.0 %global sieve_release 6.1.cf.%{__distinit}%{__distvers} @@ -134,6 +134,7 @@ Patch502: dovecot-2.0-mysqlconfig.patch Patch503: dovecot-2.1-pigeonhole-bzip2.patch Patch504: dovecot-2.1.rc6-fallocate64.patch +Patch505: ../../dovecot-mssl-2.1.6.mail-storage.c.DIFF BuildRequires: gcc-c++ BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel BuildRequires: openldap-devel, krb5-devel >= 1.3 @@ -282,6 +283,11 @@ # http://bugzilla.redhat.com/500487 %patch504 -p1 + +# add mssl maildir patch +%patch505 -F3 -p1 + + # PAM Configuration: # Default PAM configuration file uses password-auth common config; # revert to system-auth if password-auth is not available
--- dovecot-2.1.6/src/lib-storage/mail-storage.c.orig 2012-05-23 11:45:55.000000000 +0100 +++ dovecot-2.1.6/src/lib-storage/mail-storage.c 2012-05-23 12:11:28.000000000 +0100 @@ -22,12 +22,13 @@ #include "mailbox-guid-cache.h" #include <stdlib.h> #include <ctype.h> #define MAILBOX_DELETE_RETRY_SECS (60*5) +#define MAX_MSGS_PER_MAILBOX 4000 extern struct mail_search_register *mail_search_register_imap; extern struct mail_search_register *mail_search_register_human; struct mail_storage_module_register mail_storage_module_register = { 0 }; struct mail_module_register mail_module_register = { 0 }; @@ -1620,22 +1621,28 @@ ctx->dest_mail = mail; } int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input) { struct mailbox *box = (*ctx)->transaction->box; + struct mailbox_status status; int ret; if (mail_index_is_deleted(box->index)) { mailbox_set_deleted(box); return -1; } if (!(*ctx)->copying_via_save) (*ctx)->saving = TRUE; - if (box->v.save_begin == NULL) { + mailbox_get_status(box, STATUS_MESSAGES, &status); + if (status.messages >= MAX_MSGS_PER_MAILBOX) { + mail_storage_set_error(box->storage, MAIL_ERROR_NOSPACE, + "Mailbox full: Too many messages"); + ret = -1; + } else if (box->v.save_begin == NULL) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "Saving messages not supported"); ret = -1; } else { ret = box->v.save_begin(*ctx, input); } @@ -1685,23 +1692,31 @@ int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail) { struct mail_save_context *ctx = *_ctx; struct mailbox *box = ctx->transaction->box; struct mail_keywords *keywords = ctx->keywords; + struct mailbox_status status; int ret; *_ctx = NULL; if (mail_index_is_deleted(box->index)) { mailbox_set_deleted(box); mailbox_save_cancel(&ctx); return -1; } - ret = ctx->transaction->box->v.copy(ctx, mail); + mailbox_get_status(box, STATUS_MESSAGES, &status); + if (status.messages >= MAX_MSGS_PER_MAILBOX) { + mail_storage_set_error(box->storage, MAIL_ERROR_NOSPACE, + "Mailbox full: Too many messages"); + ret = -1; + } else { + ret = ctx->transaction->box->v.copy(ctx, mail); + } if (keywords != NULL) mailbox_keywords_unref(&keywords); return ret; } int mailbox_save_using_mail(struct mail_save_context **ctx, struct mail *mail)
--- dovecot-2.0.7/src/lib-storage/mail-storage.c.ORIG 2010-11-11 19:46:14.000000000 +0000 +++ dovecot-2.0.7/src/lib-storage/mail-storage.c 2010-11-11 19:46:19.000000000 +0000 @@ -15,20 +15,21 @@ #include "mail-storage-settings.h" #include "mail-namespace.h" #include "mail-search.h" #include "mail-search-register.h" #include "mailbox-search-result-private.h" #include <stdlib.h> #include <ctype.h> #define MAILBOX_DELETE_RETRY_SECS (60*5) +#define MAX_MSGS_PER_MAILBOX 4000 extern struct mail_search_register *mail_search_register_imap; extern struct mail_search_register *mail_search_register_human; struct mail_storage_module_register mail_storage_module_register = { 0 }; struct mail_module_register mail_module_register = { 0 }; struct mail_storage_mail_index_module mail_storage_mail_index_module = MODULE_CONTEXT_INIT(&mail_index_module_register); ARRAY_TYPE(mail_storage) mail_storage_classes; @@ -1365,28 +1366,34 @@ void mailbox_save_set_pop3_uidl(struct m void mailbox_save_set_dest_mail(struct mail_save_context *ctx, struct mail *mail) { ctx->dest_mail = mail; } int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input) { struct mailbox *box = (*ctx)->transaction->box; + struct mailbox_status status; int ret; if (mail_index_is_deleted(box->index)) { mailbox_set_deleted(box); return -1; } - if (box->v.save_begin == NULL) { + mailbox_get_status(box, STATUS_MESSAGES, &status); + if (status.messages >= MAX_MSGS_PER_MAILBOX) { + mail_storage_set_error(box->storage, MAIL_ERROR_NOSPACE, + "Mailbox full: Too many messages"); + ret = -1; + } else if (box->v.save_begin == NULL) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "Saving messages not supported"); ret = -1; } else { ret = box->v.save_begin(*ctx, input); } if (ret < 0) { mailbox_save_cancel(ctx); return -1; @@ -1423,31 +1430,39 @@ void mailbox_save_cancel(struct mail_sav ctx->transaction->box->v.save_cancel(ctx); if (keywords != NULL) mailbox_keywords_unref(box, &keywords); } int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail) { struct mail_save_context *ctx = *_ctx; struct mailbox *box = ctx->transaction->box; struct mail_keywords *keywords = ctx->keywords; + struct mailbox_status status; int ret; *_ctx = NULL; if (mail_index_is_deleted(box->index)) { mailbox_set_deleted(box); mailbox_save_cancel(_ctx); return -1; } - ret = ctx->transaction->box->v.copy(ctx, mail); + mailbox_get_status(box, STATUS_MESSAGES, &status); + if (status.messages >= MAX_MSGS_PER_MAILBOX) { + mail_storage_set_error(box->storage, MAIL_ERROR_NOSPACE, + "Mailbox full: Too many messages"); + ret = -1; + } else { + ret = ctx->transaction->box->v.copy(ctx, mail); + } if (keywords != NULL) mailbox_keywords_unref(box, &keywords); return ret; } bool mailbox_is_inconsistent(struct mailbox *box) { return box->mailbox_deleted || box->v.is_inconsistent(box); }