[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);
                $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",
                        $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",
                                $oldmailidtime =

                        $mailidlookup = $mailid{$GUser};

                        if ($mailidlookup) {
                                $changeto = $mailidlookup;
                        } else {
                                undef $changeto;

                if ($changeto) {
                        $From =~
                        action_change_header('From', $From);

                        if ($RRT) {
                                        '<' . $changeto . '>'
                                        '<' . $changeto . '>'
                                        '<' . $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