tertullian01 has asked for the wisdom of the Perl Monks concerning the following question:

I am currently writing a simple filter and forward script. Essentially when an email comes to a certain domain it is passed to the script. The script checks a database to see where the email should be forwarded to and then it also does a lookup against a filter table to see if the body of email should be stored. (This is for a research project in the university) The script does work fine except for one problem. Lets says that an email sent to test@test.com is supposed to forward to tertullian@hotmail.com. Well if I send an email from tertullian@hotmail.com to test@test.com the script does match all of the searches correctly and in the messages that I write to a log file it even says that it successfully forwards the email but the email never arrives. Unfortunately I am not on my own server and I don't have access to the logs to see if any error messages are being written. If I send the email from any other address it works without a problem but it seems that if the from address and the forward address are the same then the email is lost in a big black hole. I am using Mail::Audit and doing a simple resend(). Have any ideas?

Update: I am still having this same problem. I have made all of the changes that have been suggested unless otherwise noted in one of my responses. Everything seems to work fine but the email never arrives. Does anyone have any good ideas?

Replies are listed 'Best First'.
Re: Mail:Audit Resend Problem
by davidrw (Prior) on Jun 21, 2005 at 13:32 UTC
    can you post some relevant code? If it's working for all except this one case, my first thought is that there's some logic bug for when the forward address is the same as the from address...
      Here is the code I have written:
      #!/usr/bin/perl #Declare packages to be used always including strict and utf8 use strict; use utf8; use Mail::Audit; use IO::Handle; use DBI; #Connect to the database my $dbh = DBI->connect("dbi:Pg:dbname=database", "user", "password", { +AutoCommit => 0}); #Declare variables to be used including command line variables if need +ed my ($stored_email, $log, $to, $from, $forward_address, $store, $body, +$sql, $sth, $date, $local_address); my (@filter, @row); my (%forward); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); $date = "$mday/$mon/$year $hour:$min:$sec"; #Create any functions necessary #Main body of program ##Set variable values $sql = "SELECT \"ForwardMailTo\", \"ForwardMailFrom\" FROM \"tblForwardMail\""; $sth = $dbh->prepare($sql); $sth->execute; while (@row = $sth->fetchrow) { $forward{$row[0]} = $row[1]; } $stored_email = "stored_mail.txt"; $log = "audit_mail.log"; $store = "NO"; ##Open the log file open (LOG, ">>$log") or die "$date --- Couldn't open $log"; ##See if there is a match for the to email to find the forward address my $incoming = Mail::Audit->new; $to = $incoming->to(); $from = $incoming->from(); ##Test to see if the to address exists and map the forwarding address while(my ($key, $value) = each(%forward)) { if ($to =~ $key) { $local_address = $key; $forward_address = $value; } } if ($forward_address) { print LOG "$date --- $to has been mapped to $forward_address\n"; $sql = "SELECT \"tblForwardMail\".\"ForwardMailID\", \"tblFilterMa +il\".\"FilterMailEmail\" FROM \"tblForwardMail\" LEFT JOIN \"tblFilterMail\" ON \"tblForwardMail\".\"Forwar +dMailID\"=\"tblFilterMail\".\"ForwardMailID\" WHERE \"tblForwardMail\".\"ForwardMailTo\"='$local_address +'"; $sth = $dbh->prepare($sql); $sth->execute; while (@row = $sth->fetchrow) { push(@filter, $row[1]); } } else { print LOG "$date --- No mapping for $to\n"; close (LOG); exit(); } ##Check to see if the from address is part of the filter list print LOG "$date --- Searching for filter email.\n"; foreach my $email_address(@filter) { if (($from =~ $email_address)){ $store = "YES"; } } ##Either store the email and forward it or just forward the email if ($store eq "YES") { open (OUTPUT, ">>$stored_email") or print LOG "$date --- Couldn't +open $stored_email.\n"; print OUTPUT @{$incoming->body()}; print OUTPUT "##-------------------------------------------------- +-------------##"; close(OUTPUT); print LOG "$date --- Filter address found. $to has been forwarded +to $forward_address\n"; $incoming->resend($forward_address) or print LOG "$date --- Couldn +'t forward to $forward_address\n"; } else { print LOG "$date --- No filter address found. $to has been forwar +ded to $forward_address.\n"; $incoming->resend($forward_address) or print LOG "$date --- Couldn +'t forward to $forward_address\n"; } ##Close the log file close (LOG); $dbh->disconnect();
        First, a few code comments:


        0) (Update:) Doh--i missed one of the first and foremost things-- add use strict; and use warnings; !!!
        1) For this, check perldoc -f localtime:
        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); $date = "$mday/$mon/$year $hour:$min:$sec"; # THIS IS WRONG!!!! # do something like this instead: my @time = localtime; my $date = sprintf("%2d/%2d/%4d %02d:%02d:%02d", $time[4] + 1, $time[3 +], $time[5] + 1900, @time[2,1,0]);
        2) This (look at perldoc -f exists):
        while(my ($key, $value) = each(%forward)) { if ($to =~ $key) { $local_address = $key; $forward_address = $value; } }
        should be replaced with:
        if( exists $forward{$to} ){ $local_address = $key; $forward_address = $value; }
        3) Use (see DBI docs) heredocs and placeholders. (Also, i believe this 'LEFT JOIN' should be just 'JOIN')
        $sql = <<EOF; SELECT "tblForwardMail"."ForwardMailID", "tblFilterMail"."FilterMailEm +ail" FROM "tblForwardMail" LEFT JOIN "tblFilterMail" ON "tblForwardMail"."ForwardMail +ID"="tblFilterMail"."ForwardMailID" WHERE "tblForwardMail"."ForwardMailTo"=? EOF # $sth = $dbh->prepare($sql); # $sth->execute( $local_address ); # while (@row = $sth->fetchrow) { # push(@filter, $row[1]); # } # # But it seems like what you want next is just: (undef,$filter_address) = $dbh->selectrow_array($dbh,{},$local_address +); # make sure to pre-declare $filter_address
        4) This:
        foreach my $email_address(@filter) { if (($from =~ $email_address)){ $store = "YES"; } }
        could be:
        $store = "YES" if grep( $_ eq $from, @filter );
        but if you use my comment #3, then it's just:
        $store = "YES" if $from eq $filter_address;
        BUT, you should treat $store as a boolean and give it true (1) and false (0, undef) values, so you don't have to string match 'YES' later..
        $store = 1; # true $store = 0; # false if( $store ){ ... } if( ! $store ){ ... }
        5) This:
        #Declare variables to be used including command line variables if need +ed my ($stored_email, $log, $to, $from, $forward_address, $store, $body, +$sql, $sth, $date, $local_address);
        is "c-ish" .. here it's usally better to declare stuff just when it's being used (especially if it only exists in a limited block/scope)

        gotta cut back to work for a moment ;) but then i'll go back and see if can find the bug..
        I don't see where your program uses warnings, so could it be that $forward_address is undefined ?
        Dodge This!
Re: Mail:Audit Resend Problem
by tirwhan (Abbot) on Jun 21, 2005 at 13:37 UTC
    Any number of possible reasons come to mind. Maybe you should post (the relevant part of) your code so we can see whether there's something wrong with it?