[Mimedefang] Compliance
Alan Premselaar
alien at 12inch.com
Fri Apr 15 03:09:19 EDT 2005
Josh Kelley wrote:
> alan premselaar wrote:
>
>> I'd be interested in at least looking at it. Currently I'm using
>> procmail for local delivery and its Quota handling is kludgey at best.
>> I'd really like to get something working within MD. Since the method
>> Jan uses calls the perl module for Quota directly, I don't think
>> setting setuid on the quota application will make any difference
>> (although I haven't looked at the Quota module code either)
>
>
> Here you go. A brief explanation: we're only really interested in
> checking quotas for students, since faculty/staff don't have quotas.
> Students use their student IDs for their usernames, with
> firstname.lastname set up as an email alias, so we have to check
> aliases. We test for numeric usernames to see if the account is a
> student (instead of testing something sensible like the account's gid -
> I don't know what I was thinking). Rather than checking current space
> usage against the message size, as Jan did, we just check to see if the
> user has already exceeded their soft quota and has exceeded their grace
> period (i.e., grace is 'none'). This means that the occasional
> over-the-quota bounce still gets generated (for messages that exceed the
> hard limit before the grace period expires, or for messages so big that
> they exceed the hard limit for users currently below the soft limit).
> This hasn't usually been a problem, but sometime I'll go back and add
> Jan's enhancements - thanks, Jan, for posting your code.
...snip...
Josh,
thanks. I took some of your code and Jan's code and hacked it all
together. I thought about putting in the alias checking as well except
that a) I use more than one alias database with sendmail and b) 99% of
my aliases map to more than one user so it's not likely that
'user1 at domain,user2 at domain,user3 at domain' is going to map to a UID to do
quota checking against. Even if i traversed the list of real users in
the alias, i'm still in a single recipient stage, so if one real_user in
the alias is over quota, it would cause the message to be rejected for
the alias, which I don't really want to do.
the code's only been written against and tested on RHEL ES3.0 linux.
anyways, I figured I'd share my code:
$MAILDIR = "/path/to/mail/directories";
$_QUOTA_CMD = "/path/to/setuid/quota/command";
sub filter_recipient {
my
($to,$from,$ip,$name,$first,$helo,$rcpt_mailer,$rcpt_host,$rcpt_addr) = @;
my $local = ($rcpt_mailer eq 'local');
my @qrval = &check_quota_info($rcpt_addr) if ($local);
return(@qrval) if ( $local && lc($qrval[0]) ne 'continue');
# my greylisting code goes here
# if this was the only testing done in filter_recipient you
# could easily just do this:
#
# return(&check_quota_info($rcpt_addr)) if ($rcpt_mailer eq 'local');
#
# and be done with it.
}
sub check_quota_info {
my ($to) = @_;
my $uid = getpwnam($to);
return('CONTINUE',"ok") if (!$uid); # possible alias
my $dev = Quota::getqcarg($MAILDIR);
my ($bc,$bs,$bh,$bt,$fc,$fs,$fh,$ft) = Quota_query($dev,$uid);
return('CONTINUE',"ok") if ((!defined $bh) || ($bh == 0));
## if usage >= limit then perm-fail
return('REJECT',"Quota exceeded.",'552','5.2.2') if ($bc >= $bh);
## fetch sendmail macros from commands file
read_commands_file() || return('TEMPFAIL',"Internal error.");
my $mailsize;
if (defined $SendmailMacros{msg_size}) {
## round up to the next 4k block
$mailsize = int(($SendmailMacros{msg_size} + 4095) / 4096) + 4;
} else {
$mailsize = 4;
}
## if the mail is larget than remaining space, tempfail
return('TEMPFAIL',"Quota exceeded, try again later",'452','4.2.2') if
($bc + $mailsize > $bh);
## else accept
return('CONTINUE',"ok");
}
sub Quota_query {
my ($device,$uid) = @_;
my $retval = ();
my ($mailquota) = grep { /^\s+$device/ } split('\n', `$_QUOTA_CMD $uid`);
# return if user has no defined quotas
return(@retval) if ($mailquota =~ /^Disk quotas .{1,30}: none/);
$mailquota =~ s/^\s+//;
@retval = split('\s{1,6}',$mailquota);
shift @retval; # remove device name from list
# strip out '*' characters
foreach my $val (@retval) {
$val =~ s/\*//g;
}
my ($homedir) = (getpwuid($uid))[7];
# pretend there's no hard limit for user if .forward file exists
$retval[2] = 0 if (-f "$homedir/.forward");
return(@retval);
}
I still have the procmail quota kludge setup, so i figure even if some
stuff sneaks past this code it'll still get a bounce with "mailbox full"
status, but this should help nearly illiminate unnecessary bounce
messages. (which i think is a good idea)
thanks again,
alan
More information about the MIMEDefang
mailing list