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

Good day Bros. I needed a simple mail reflector and did not need all the functionality of listerv or majordomo, et al. So I wrote a script for this purpose myself. It is working fine as far as anticipated functions. Here is the code:
#!/usr/bin/perl -w use strict; use Mail::POP3Client; use Mail::Mailer; our $junk; my $pophost = ''; my $popuser = ''; my $poppw = ''; my $reflectoraddr = ''; my $subjprefix = ''; my $errorfrom = ''; my $errorbcc = ''; my %participants; open(IN,"participants.txt") or die "Can't open participants.txt: $!\n" +; while(<IN>) { chop; if ($_) { $participants{$_} = 1; } } close IN; my $pop = Mail::POP3Client->new(HOST => $pophost, USER => $popuser, PA +SSWORD => $poppw); our $mailer = new Mail::Mailer; my $msgcount = $pop->Count(); print "$msgcount messages\n"; foreach my $k (1..1) { my %header; my $head = $pop->Head($k); my @lines = split(/\n/,$head); my $headerinfo; my ($key,$value); for my $i (0..$#lines) { $lines[$i] =~ s/\r/ /g; if (substr($lines[$i],0,1) =~ /[A-Z]/) { if ($lines[$i] =~ /^Date/) { $key = "Date"; ($value = $lines[$i]) =~ s/Date: //; } else { ($key,$value) = split(/\:/,$lines[$i]); } $header{$key} = $value; } else { $lines[$i] =~ s/^\s+//g; $header{$key} .= " $lines[$i]"; } } if ($header{'Subject'} !~ /undeliverable|delivery (failure|error)/ +i) { delete($header{'Received'}); delete($header{'Envelope-to'}); $header{'Reply-to'} = $reflectoraddr; delete($header{'To'}); $header{'Subject'} =~ s/\[Crawdad\] //g; my $body = $pop->Body($k); open (OUT,">bodytext.txt") or die "No output: $!\n"; print OUT $body; close OUT; my $from; if ($header{'From'} =~ /\<.+\>/) { ($junk, $from) = split(/[\<\>]/,$header{'From'}); } else { $from = $header{'From'}; } if (defined($participants{$from})) { $header{'Subject'} = "\[$subjprefix\] ".$header{'Subject'} +; foreach my $p (keys %participants) { unless ($header{'From'} =~ /$p/) { print "Sending to $p\n"; $header{'To'} = $p; $mailer->open(\%header); print $mailer $body; $mailer->close; } } } else { print "Error to $from\n"; errormsg(\%header,$from); } } $pop->Delete($k); } $pop->Close(); sub errormsg { my ($header,$from) = @_; my $errormsg = "The address $from is not authorized to send to thi +s discussion list.\n\nIf you are a registered user, it may be that yo +u are sending from an e-mail account other than the one you normally +use. Please contact the discussion host to have this account added." +; delete($$header{'Content-Type'}); $$header{'Subject'} = 'ERROR: '.$$header{'Subject'}; $$header{'From'} = $errorfrom; $$header{'To'} = $from; $mailer->open($header); print $mailer $errormsg; $mailer->close; return; }
Since this is a reflector that will run on a chron job or something like that, I am concerned about the possibility of this thing getting error e-mails (e.g. if an address fails, an account gets suspended, etc.) and getting in a mail loop situation via sub errormsg. I have tried to prevent this with if ($header{'Subject'} !~ /undeliverable|delivery (failure|error)/i) but I'm not sure if this is sufficient or the best way to do it.

Any Mail Monks out there who can comment on whether this is good enough? Is there some kind of header I could look at to detect failures, rather than depending on the subject? I've looked around in the SMTP docs and I haven't seen anything that looks suitable.

Thanks.......Steve

Replies are listed 'Best First'.
Re: Avoiding mail loops
by samtregar (Abbot) on Jun 15, 2007 at 16:48 UTC
    The usual way to do loop detection is to parse the Received headers. Look for your host appearing multiple times and you'll have spotted a loop.

    -sam

      Using the Received field can lead to false positives when one uses multiple MTA's within the same domain.

      The proper method is to add a custom header to the email and for incoming emails detect if that particular header is present (if so, then you have a loop condition).

      Custom header names should start with 'X-' so as not to conflict with predefined names, e.g.

      X-Loop: cormanaz@domain.tld
Re: Avoiding mail loops
by GrandFather (Saint) on Jun 15, 2007 at 20:17 UTC

    beware also of indirect loops - mail accounts set to "holiday" mode where they auto-reply with a message can generate an email storm in very short order! http://www.w3.org/Protocols/rfc822/ may be of help. See 4.4. ORIGINATOR FIELDS and in particular 4.4.4.


    DWIM is Perl's answer to Gödel