Re: [Exim] checking quota before accepting the message

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Exim User's Mailing List
Ημερομηνία:  
Προς: Nathan Ollerenshaw
Υ/ο: Exim User's Mailing List
Αντικείμενο: Re: [Exim] checking quota before accepting the message
[ On Saturday, August 7, 2004 at 10:22:35 (+0900), Nathan Ollerenshaw wrote: ]
> Subject: [Exim] checking quota before accepting the message
>
> 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 run the following little script from cron on a short interval (as
short as possible) to regularly re-generate an alias table that routes
the over-quota mailbox addresses to a custom failure address so that
they get rejected at SMTP time instead of having to bounce or defer
them.

I'm pretty sure Exim offers a similar way to "fail" an address (i.e. at
the time the RCPT TO: command is sent to it).

Note this is specific to Cyrus IMAP, but it should be very easy to adapt
to any other quota system. It may be more necessary with Cyrus though
because it's not easy or inexpensive to query Cyrus in any other way to
find out the quota usage on every delivery -- that would be insane! ;-)

#! /bin/sh
#
#    mkcyrusoqlist - update the Cyrus Over-Quota list
#
# This script should be run periodically as root from cron (as often
# as you can afford to run it -- Cyrus "quota" is a bit heavy).


umask 022
PATH="/sbin:/bin:/usr/sbin:/usr/bin"; export PATH

argv0=$(basename $0)

# don't use any world-writable directory here!!!
#
# /var/run alone would be OK, but a private directory is better
#
MYTMPDIR="/var/run/$argv0"
if [ ! -d ${MYTMPDIR} ] ; then
    if mkdir ${MYTMPDIR} ; then
        chmod 700 ${MYTMPDIR}
    else
        echo "$argv0: ${MYTMPDIR} may exist as a file!" 1>&2
        exit 1
    fi
fi


if cd $MYTMPDIR ; then
    : # OK
else
    echo "$argv0:  ERROR:  Oops!  What's up with ${MYTMPDIR}!" 1>&2
    exit 1
fi


CYRUS_USER="cyrus"
CYRUS_BIN="/usr/cyrus/bin"

# WARNING: this script could fail to interlock properly if it can be
# invoked simultaneously with more than one name! Don't do that!
#
PIDFILE=${MYTMPDIR}/${argv0}.pid

if [ -s ${PIDFILE} ] ; then
    if kill -0 `cat ${PIDFILE}` > /dev/null 2>&1 ; then
        : # still running... error reported below...
    else
        # system probably rebooted while checkerr was running...
        rm ${PIDFILE}
        rmdir ${LOCKDIR}
    fi
fi


if [ -e ${LOCKDIR} ] ; then
    echo "It appears there's already an instance of ${argv0} running..." 1>&2
    exit 1
fi


if mkdir ${LOCKDIR} ; then
    : # got it!
else
    echo "$argv0:  ERROR:  Oops, just missed grabbing ${LOCKDIR}!" 1>&2
    exit 1
fi


echo $$ > ${PIDFILE}

rm -f /etc/mail/cyrus_over_quota.tmp
cat <<__EOF__ > /etc/mail/cyrus_over_quota.tmp
#
#    #     #                                                   ###
#    #  #  #    ##    #####   #    #     #    #    #   ####    ###
#    #  #  #   #  #   #    #  ##   #     #    ##   #  #    #   ###
#    #  #  #  #    #  #    #  # #  #     #    # #  #  #         #
#    #  #  #  ######  #####   #  # #     #    #  # #  #  ###
#    #  #  #  #    #  #   #   #   ##     #    #   ##  #    #   ###
#     ## ##   #    #  #    #  #    #     #    #    #   ####    ###
#
# This file is automatcialy maintained by '$argv0'
#
# Last updated: $(date)
#
__EOF__


# the current implementation only selects mailboxes over 99%
# utilization, generates regular expressions that should match every
# sub-mailbox of the over-quota mailbox root, and aliases them to
# ":fail:"  so that they are permanently rejected (i.e. it is assumed
# the default user_with_mbox director is being used).
#
# It might be wise to use >98% instead of >99%.
#
# It might sometimes be desirable to use :defer: for temporary
# rejection, especially if you do not set lmtp_overquota_perm_failure
# to "yes" in your Cyrus imapd.conf, though you really should always
# trigger an immediate and permanent reject for over-quota failures so
# that the sender will know right away what's going on.
#
su -m "${CYRUS_USER}" -c ${CYRUS_BIN}/quota | awk '
    $2 > 99 {
        # unixhierarchysep: no
        sub(/^user\./, "", $4);
        # unixhierarchysep: yes
        sub(/^user\//, "", $4);
        printf("\"%s([-+].*)?\": :fail:\"This mailbox has exceeded its allotted storage quota.\"\n", $4);
    }' >> /etc/mail/cyrus_over_quota.tmp


exitvalue=$?

if [ $exitvalue -ne 0 ]; then
    echo "$argv0:  ERROR:  Problems creating /etc/mail/cyrus_over_quota.tmp" 1>&2
else
    mv /etc/mail/cyrus_over_quota.tmp /etc/mail/cyrus_over_quota.list
fi


rm -f ${PIDFILE}

exit $exitvalue


--
                        Greg A. Woods


+1 416 218-0098                  VE3TCP            RoboHack <woods@???>
Planix, Inc. <woods@???>          Secrets of the Weird <woods@???>