Nathan Ollerenshaw wrote:
> Guys,
>
> right now I have a lot of messages sitting in queues, being deferred
> for local delivery because the mailbox they are trying to delivery to
> is over quota.
>
> Is there any way to check to see if the message is over quota before
> its 250 OK'd, and fail it? I don't want to generate a bounce if
> possible.
>
> I'm guessing not because if its being delivered to multiple addresses
> you don't want to fail it for all of them if just one will fail due to
> quota. Maybe there is a better way.
It's ugly (yes, I'd like a builtin in Exim too!) but all sorts of evil
things are possible with Exim. Here's mine (any critiques welcome):
# This relies on data stored in a "maildirdize" file in the user's area
# so it won't have much effect on a 2mx - we need to store quota/usage
# info in the DB for that. At RCPT time it works with a SIZE=
# smtp command, trusting it. Then at DATA time we check again having
# real info, and in the case there was no maildirsize file we generate
# a bounce immediately on delivery failure.
acl_chk_quota:
# ok if within quota
accept condition = ${if <= {$acl_c8}{$acl_c7} {yes}{no}}
defer message = quota exceeded
set acl_m9 = ${lookup pgsql{ select set_user_param_int( \
$acl_m4, 'over_quota', 1 )}\
{dummy}fail}
quota_db_flag:
accept condition = ${if = \
{${lookup pgsql{ SELECT user_param_int($acl_m4, 'over_quota')}{$value}}} \
{1} {no}{yes}}
defer message = quota exceeded
rcpt_chk_quota:
# OK if no local deliveries
require set acl_c7 = 1000M
set acl_c5 = 0
accept condition = ${if match {$acl_c9}{/(,|\$)} {no}{yes}}
# Get the deliver directory and append "maildirsize"
require set acl_c8 = ${sg {$acl_c9} {([^/],)*(.*/(,|\$))} \
{\$2maildirsize}}
# If the size file is not present either it's never been created or
# we're on a 2MX. Check the DB for an over-quota flag.
accept condition = ${if !exists{$acl_c8} {yes}{no}}
acl = quota_db_flag
# read the size file
require set acl_c8 = ${readfile{$acl_c8}{!}}
# empty first line means infinite quota
accept condition = ${if match {$acl_c8}{^\\s*(!.*)?\$} {yes}{no}}
set acl_c7 = 0
# quota: first line, first number
require set acl_c7 = ${sg {$acl_c8} {^(\\s*)(\\d+).*\$} {\$2}}
# zero means infinite quota
accept condition = ${if = {$acl_c7}{0} {yes}{no}}
# drop the first line
warn set acl_c8 = ${sg {$acl_c8}{^[^!]*!(.*)\$} {\$1}}
# convert 2nd number & linebreak into addition, on each line
set acl_c8 = ${sg {$acl_c8}{\\s*(-?\\d+)[^!]*!?} {\$1 +}}
# evaluate the sum (and leave around for the data-time check)
set acl_c5 = ${eval:$acl_c8 +0}
# add this message (10k default if no SIZE=)
set acl_c8 = ${eval:$acl_c5 + ${if < {$message_size}{0} \
{10K} {$message_size}}}
# ok if within quota
accept acl = acl_chk_quota
data_chk_quota:
accept condition = ${if > {$rcpt_count}{1} {yes}{no} }
accept condition = ${if match {$acl_c9}{/(,|\$)} {no}{yes}}
accept condition = ${if = {$acl_c7}{0} {yes}{no}}
require set acl_c8 = ${eval:$acl_c5+$message_size}
accept acl = acl_chk_quota
- Jeremy