pavement

Postfix, maintaining relay destinations

From FreeBSDwiki
Revision as of 15:40, 6 October 2009 by Jimbo (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
#!/usr/bin/perl

########################################################
###
### update-postfix.pl
###
### purpose:  automatically maintain a list of "secret"
###           destination MTAs for Postfix to relay mail
###           to.
###
### usage:    run without arguments to check for
###           changes and update if necessary, or run
###           with --force to rebuild transport and
###           recipient tables and rehash them for
###           postfix even if no changes have been made.
###
### method:   if the md5sum for any relevant file in
###           $dir does not match $dir/$file.md5,
###           update $dir/$file.md5, process all
###           relevant files into new postfix recipient
###           and transport tables, and re-hash those
###           tables for postfix.
###
### requires: for each destination MTA, place a
###           file in $dir named that server's IP
###           address, optionally with a port number
###           appended to it, in the form
###           $dir/192.168.0.10 or $dir/192.168.0.10-587
###
###           Each file must contain a list of all valid
###           addresses to be relayed to the MTA at that,
###           address, one address per line, in the form
###           user@domain.  Catchall addresses may be
###           used by omitting the username, and
###           merely specifying @domain on that line.
###
###           Any line which contains an @ will be
###           processed as an email address.  Any line
###           which does not contain an @ will be
###           ignored completely.
###
### bugs:     requires IP address as relay target,
###           so cannot do round-robin delivery and
###           will not notice MX record changes.
###
########################################################


### config variables
#
$dir = '/usr/home/postfixfiles/';
$recipientsfile = '/usr/local/etc/postfix/recipients';
$transportfile = '/usr/local/etc/postfix/transport';
$postmapprogram = '/usr/local/sbin/postmap';
$md5sumprogram = '/sbin/md5 -q';
$logger = '/usr/bin/logger -p mail.notice';
$identity = 'update-postfix';




### begin operation
#
opendir(DIR,$dir);
@files = readdir(DIR);
closedir(DIR);

my $needsupdate = 0;
$logger .= " $identity\: ";

if ($ARGV[0] eq '--force') { $needsupdate = 1; }

foreach $file (@files) {
        if ($file =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(-\d{1,4})?$/) {
                my $path = $dir.$file;
                my $md5path = $path.'.md5';
                my $newmd5 = `$md5sumprogram $path`;
                my $oldmd5;

                if (-e $md5path) {
                        open(FH,$md5path) or die "Can't open $md5path: $!";
                        $oldmd5 = <FH>;
                        close FH;
                }

                if ($oldmd5 ne $newmd5) {
                        open(FH,">$md5path") or die "Can't open $md5path: $!";
                        print FH $newmd5;
                        close FH;
                        $message = "$file changed since last check";
                        print "$message\n";
                        print `$logger $message`;
                        $needsupdate = 1;
                }
        }
}

if ($needsupdate == 0) {
        $message = "No data changed in $dir - update not needed.";
        print "$message\n";
        print `$logger $message`;
} else {
        $message = "Updating Postfix configuration...\n";
        if ($ARGV[0] eq '--force') {
                $message = "UPDATE FORCED: " . $message;
        }
        print "$message\n";
        print `$logger $message`;

        foreach $file (@files) {
                if ($file =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(-\d{1,4})?$/) {
                        open FH, "$dir$file" or die "Can't open $file: $!";
                        foreach $line (<FH>) {
                                if ($line =~ /\@/) {
                                        # add ok to end of address and push it into recipients
                                        $recipient = $line;
                                        chomp $recipient;
                                        $recipient .= " OK\n";
                                        push @recipients,$recipient;

                                        # create a domain routing line and push it into rawdomains
                                        (my $ip,my $port) = ($file =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})-?(\d{1,4})?/);
                                        $line = (split("@",$line))[1];
                                        chomp $line;
                                        $line .= " smtp:[$ip]";
                                        if ($port ne ) { $line .= ":$port"; }
                                        $line .= "\n";
                                        push @rawdomains,$line;
                                }
                        }
                        close FH;
                }
        }

        # sort domains for transport table to eliminate dupes
        %hashTemp = map { $_ => 1 } @rawdomains;
        @sorteddomains = sort keys %hashTemp;

        open FH, ">$recipientsfile" or die "Can't open $recipientsfile: $!";
        print FH @recipients;
        close FH;
        $message = scalar @recipients;
        $message = $message . " recipients written to $recipientsfile";
        print "$message\n";
        print `$logger $message`;

        open FH, ">$transportfile" or die "Can't open $transportfile: $!";
        print FH @sorteddomains;
        close FH;
        $message = scalar @sorteddomains;
        $message = $message . " domains written to $transportfile";
        print "$message\n";
        print `$logger $message`;

        print `$postmapprogram $recipientsfile`;
        print `$postmapprogram $transportfile`;
}
Personal tools