[Mimedefang] tie'd files
Tuc at T-B-O-H.NET
ml at t-b-o-h.net
Sun Aug 31 18:31:14 EDT 2008
>
> ->sync is only meant to write out changed local data, not to pick up
> changes in the external file.
>
I had hopes. :}
>
> The problem is: if there is an update, what usually happens is that a
> completely new .db file is placed on top of the old one. If you don't
> specifically untie and re-tie, your process will still have the old file
> open, with the original data in it.
>
> It's generally a bad idea to force BerkeleyDB files to do an in-place
> update while readers have the database open: since readers tend to cache
> certain parts of the database, this is almost guaranteed to blow up at
> some point.
>
> What we do is, before each email is checked (usually in filter begin),
> we check if the file that underlies the map has been changed. If it is,
> we untie and re-tie the map.
>
> I'll attach the code that we use for this. It's probably easy to use,
> but it's a bit obscured by the fact that the code that checks for a
> changed file, is separated from the actual tieing and untieing code, so
> it can be reused.
>
[ Great code deleted, thanks ]
Yea, I ended up doing something similar... The code is a little
crufty right now, but incase anyone wants it :
sub filter_initialize {
use DB_File;
use Fcntl;
tie %mailid, "DB_File", "/etc/mail/mailid.db", O_RDONLY;
$oldmailidtime = (stat('/etc/mail/mailid.db'))[9];
tie %variout, "DB_File", "/etc/mail/variout.db", O_RDONLY;
$oldvariouttime = (stat('/etc/mail/variout.db'))[9];
}
and then in the bottom of filter_end :
if ($Sender =~ /^<(.*)\@laptop.example.com>$/) {
$GUser = $1;
$head = $entity->head;
$From = $head->get('From', 0);
chomp($From);
$RRT = $head->get('Return-Receipt-To', 0);
if ($RRT) {
$XCRT = $head->get('X-Confirm-Reading-To', 0);
$DNT = $head->get('Disposition-Notification-To', 0);
}
$LookupRecipient = lc(@Recipients[0]);
$LookupRecipient =~ tr/<>//d;
$newvariouttime = (stat('/etc/mail/variout.db'))[9];
if ($newvariouttime > $oldvariouttime) {
untie %variout;
tie %variout, "DB_File", "/etc/mail/variout.db",
O_RDONLY;
$oldvariouttime = (stat('/etc/mail/variout.db'))[9];
}
$varilookup = $variout{$LookupRecipient};
if ($varilookup) {
$changeto = $varilookup;
} else {
$newmailidtime = (stat('/etc/mail/mailid.db'))[9];
if ($newmailidtime > $oldmailidtime) {
untie %mailid;
tie %mailid, "DB_File", "/etc/mail/mailid.db",
O_RDONLY;
$oldmailidtime =
(stat('/etc/mail/mailid.db'))[9];
}
$mailidlookup = $mailid{$GUser};
if ($mailidlookup) {
$changeto = $mailidlookup;
} else {
undef $changeto;
}
}
if ($changeto) {
$From =~
s/<.*\@laptop.example.com>/<$changeto>/;
action_change_header('From', $From);
if ($RRT) {
action_change_header(
'Return-Receipt-To',
'<' . $changeto . '>'
);
action_change_header(
'X-Confirm-Reading-To',
'<' . $changeto . '>'
);
action_change_header(
'Disposition-Notification-To',
'<' . $changeto . '>');
}
change_sender($changeto);
}
}
I know there is more I can do to tighten this up. Using the
sendmail $j macro is one instead of hardcoding "laptop.example.com".
So my mailid is something like :
foo foo at example.com
bar bar at example.com
foobar foo at corp.example.com
and variout is something like :
salesperson at company1.example.com company1 at example.com
billing at company2.example.com billing at example.com
mom at someisp.example.com yourwiddleson at example.com
So if the recipient is my mom, it changes the sender to
yourwiddleson at example.com . If I email someone like
dad at someisp.example.com it'll fall back to looking up my userid
in mailid (If I'm logged in as foo, it'd end up as foo at example.com)
My main thing is I usually try to use "unique" email addresses
for everyone I deal with, so when I start to get spam I can tell who
gave out my email address, and shut that one unique id down in the
/etc/mail/access file (And my messages aren't too polite too. ;) )
Thanks, Tuc
More information about the MIMEDefang
mailing list