quarantine release might lose mail?
Frank Cusack
fcusack at fcusack.com
Tue Dec 15 23:00:01 GMT 2009
On December 15, 2009 10:52:46 AM -0500 Frank Cusack <fcusack at fcusack.com>
wrote:
> Especially not, as in this case, where the fix is trivial and especially
> not when the problem and solution is known. I will post my qrelease
> program later today.
Here it is. One thing I learned is that the queue file name includes
a timestamp, so the chance of a collision is much, much less than I'd
originally guessed. Very very close to zero, I would expect. But
the fix is trivial and guarantees correctness. Maybe this can make
it onto the wiki page.
#!/bin/zsh
# qrelease - release a mail from the mailscanner quarantine for postfix
# The mailscanner quarantine directory and the postfix queue directory must
# be on the same filesystem.
# See also
#
http://wiki.mailscanner.info/doku.php?id=documentation:configuration:mta:postfix:how_to:release_quarantined_mail
#
# warn needs to prefix with progname, not function name
unsetopt FUNCTION_ARGZERO
warn()
{
echo $0: $* >&2
}
die()
{
warn $*
exit 1
}
if [ $# -ne 1 ]
then
echo "Usage: $0 QUARANTINE" >&2
exit 1
fi
[ -d "$1" ] || die "Directory $1 does not exist"
qd=$1
pd=$(postconf -h queue_directory)/incoming
perl -e "exit 1 if (stat '$qd/.')[0] != (stat '$pd/.')[0]" ||
die "$qd and $pd are not the same filesystem"
# die on any errors not explicitly caught
set -e
qf=${qd##*/} # basename
qf=${qf%.*} # prefix
[ -f $qd/$qf ] || die "Queue File $qd/$qf does not exist"
# The queue file name has a microseconds timestamp portion and an inum
portion.
# The inum portion guarantees a unique name in the filesystem (required
# to prevent loss of data across the multiple queues).
# The time portion avoids recycling the queue id's quickly, so that an
# individual email can more easily be traced.
#
# Note that the queue filename in the quarantine is incorrect as it
maintains
# the original queue filename, but is a COPY of the original queue file (ie,
# the inum portion is wrong). Because of the timestamp portion, it is
highly
# unlikely to collide but it is possible. The chance of collision depends
on
# the resolution of the system clock and the rate of inode reuse. We
correct
# it because having an ABSOLUTE guarantee is nice and also it's trivial.
# We preserve the timestamp portion.
ts=$(printf %.5s $qf)
# make a copy first
cp $qd/$qf $qd/$ts.rename
# rename the queue file to match inum
pf=$ts$(printf %X $(ls -i $qd/$ts.rename | awk '{print $1}'))
mv $qd/$ts.rename $qd/$pf
# move to postfix queue dir
mv -i $qd/$pf $pd/$pf </dev/null || die "Filename collision!"
chown postfix $pd/$pf
chmod 0700 $pd/$pf && logger -p mail.info -t qrelease "$qf requeued as $pf"
exit 0
More information about the MailScanner
mailing list