Date: Tue, 8 Dec 1998 13:00:00 -0600 From: mark david mcCreary I have gotten the new VERP feature of Exim 2.054 working in test, along with some supporting programs to handle bounces that do come back. The routines are included below. The idea is that each message sent out will have a unique envelope sender, and all SMTP engines should return bounces to the machine that sent it, based on the envelope information. The envelope sender is unique in that it contains the mailing list that sent the message, as will as the email address of the recipient. Any message sent back to that address should always be a bounce, and thus there is no need to decipher the body of the message for clues as to which email address bounced. The supporting procmail and perl program simply read the email address, and compose a standard <550> SMTP error message to send to the mailing list. The mailing list (at least Smartlist) will then remove addresses that bounce more than x times. I would guess with some fancy regexp parsing and Exim filters to place a <550> joe@aol.com in the body, the Procmail and Perl routines could be replaced, and the <550> error message generated from within Exim, and then sent to the appropriate mailing list. Please let me know if you figure out how to do that. Part 1 - Exim configuration (needs Exim 2.054 or better) ###################################################################### # TRANPORTS CONFIGURATION # ###################################################################### ## This transport is called for all mailed sent to bounce-* # The comeback procmail will parse it, and create a bounce message # to the correct list bounce_pipe: driver = pipe; command = "/usr/bin/procmail -d comeback", envelope_to_add, user = exim # This transport is used for delivering messages over SMTP connections. # One message at a time, so that the address may be placed in the To: line # Kludge up a message id, so that receiving hosts do not consolidate on same # message id smtp: headers_remove = "To:Message-Id:Resent-To:Resent-Date:Resent-From:Resent-Message-Id:Resent-Bcc", add_headers = "To: $local_part@$domain\n\ Message-Id: ", return_path = "${if match {$return_path}{^(.+?)-request@.*\\$}\ {bounce-$1=$local_part=$domain@$primary_hostname}fail}", driver = smtp; max_rcpt = 1 end ###################################################################### # DIRECTORS CONFIGURATION # ###################################################################### # any mail prefixed with bounce- is probably a bounce message # from the owner-hack delivery method bounce: driver = smartuser, prefix = bounce-; transport = bounce_pipe Part 2 - Procmail Routine - Needs Procmail 3.11pre7 # The mail-list.com front-end for Smartlist Mailing Lists # # Copyright (c) 1998 Internet Tools, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Comeback Bounce Error Routine # # This routine is used when bounced message come back from the owner-hack # method of delivery. That is, each envelope sender is unique, containing # the list name and email address in the envelope. # # Reads email message bounced back and creates and sends # bounce message back to appropriate list # # Calls Perl program comeback.pl to accomplish the bulk of the work PATH=.:/home/ftp/discuss/.bin:/bin:/usr/bin:/usr/local/bin:/usr/sbin:$PATH SHELL=/bin/sh VERBOSE=yes LOGABSTRACT=all LOGFILE=$HOME/procmailog COMSAT=no test=test # /usr/bin/test mkdir=mkdir # /bin/mkdir DOMAIN=mail-list.com # the common domain for all the lists SUBDOMAIN=`hostname` # the fully qualified hostname $test -d backup || $mkdir backup $test -d bounces || $mkdir bounces # save a copy of all incoming files to an existing directory called backup # :0 c backup # detect mail loop # save in folder for debugging purposes # terminate :0 * $^(X-(Unsubscribe:|Diagnostic:)) bounces # weighted scoring to determine if it's a from a mailer_daemon # The E flag executes only if the preceding receipe did not # #:0 h #* -100^0 ^FROM_DAEMON #* 1^0 #{ } #:0 Eh #bounces SENDER = `formail -rtzx To:` SUBJECT = `formail -zxSubject:` TODAY = `date "+%Y-%m-%d %T"` :0 hwic: log.lock | echo -e $TODAY "\t" $SENDER "\t" $SUBJECT >> log-comeback # throw away all messages that are warnings, or notices of receipt :0 h * ^Subject: \ (Message status - opened| \ .*warning| \ .*temporarily unable to deliver| \ .*Undelivered mail in mailqueue|.*Waiting mail|mail warning) /dev/null # filter the email message # throw away the body, all information is in the headers :0 fbi | /bin/true # filter the email message # remove bounce- prefix from envelope-to header # move into from header :0 fh * ^Envelope-to: bounce-\/.* | formail -I"To: $MATCH" # filter the email message # set up the headers for the perl program :0 fh | formail -I"Subject: Bounce from comeback" \ -I"Envelope-to:" \ -I"From: mailer-daemon@[127.0.0.1]" # # pass email message to perl program # which will send out a bounce message to the correct list, from the bouncing # email address # :0 w | comeback.pl Part 3 - Perl Program - needs Perl 5.004 with Perl Modules for Internet mail #!/usr/bin/perl -w # # The mail-list.com front-end for Smartlist Mailing Lists # # Copyright (c) 1998 Internet Tools, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # # This program will generate bounce messages, and send them to the # appropriate list-request address. # # This program is invoked by a Procmail recipe. The body of the email # message came back from the owner-hack delivery, and can be ignored. # # Exim will stick the envelope address in a special header - Envelope-to: # # This program will parse out the offending list and email address from # that Envelope-To address. Then create a bounce message and send it. # # This program uses the Perl Module Mail::Internet to send each message. use Mail::Internet; chop(my $Date = `date "+%Y-%m-%d %T"`); my $bounce_body = ' 550 '; # 550 is SMTP error code for user unknown open(LOG,">>/tmp/comeback.log") || die(" Could not open comeback.log $!"); $ENV{'SMTPHOSTS'} = '[127.0.0.1]'; my $mesg = new Mail::Internet \*STDIN; # look at mail headers, and grab the data my $from = $mesg->head->get('From'); chop($from); my $to = $mesg->head->get('To'); chop($to); my $subject = $mesg->head->get('Subject'); chop($subject); my @tokens = split(/@/, $to); my @parts = split(/=/, $tokens[0], 2); my $long_to = $parts[0]; my $bad_address = $parts[1]; $bad_address =~ s/=/@/; # replace = sign with @ symbol $to = $long_to . "-request\@[127.0.0.1]"; # make the body of the message a simple bounce message that smartlist can handle my $message_body = $bounce_body . "<" . $bad_address . ">" . "\n"; my $new_mesg = new Mail::Internet( [ ], 'Body' => [$message_body] ); # this is who the mail is directed to via SMTP; $ENV{MAILADDRESS} = $from; # these are the addresses placed in the header block of the message. $new_mesg->head()->add('From', $from); $new_mesg->head()->add('To', $to); $new_mesg->head()->add('Subject', $subject); # $new_mesg->print_header(\*LOG); # $new_mesg->print_body(\*LOG); print LOG "$Date\t$to\t$bad_address\n"; my @recips = $new_mesg->smtpsend; unless (@recips > 0) { print LOG "Failed to deliver ($from,$to,$message_body) \n"; } Please send comments or suggestions for improvements to mdm@internet-tools.com mark david mcCreary Internet Tools, Inc. 1436 West Gray #438 mdm@internet-tools.com Houston, Texas 77019 http://www.internet-tools.com 713.627.9600