#!/usr/bin/perl use strict; use warnings; # $Id: requester,v 1.4 2004/02/15 20:38:19 lem Exp $ use IO::File; use Pod::Usage; use Getopt::Std; use NetAddr::IP; use Mail::Mailer; our $VERSION = do { my @r = (q$Revision: 1.4 $ =~ /\d+/g); sprintf " %d."."%03d" x $#r, @r }; =pod =head1 NAME requester - Request additional information from sites with bad reporting practices =head1 SYNOPSIS requester [-h] [-v] [-r relay] [-S separator] -s report-email -t template =head1 DESCRIPTION During your daily operation of the C system, you will find sites that have very poor reporting practices and tend to not send relevant information along with their complaints. One notable example is Hotmail, which sends a generic note that does not even include a timestamp or a specific reason for their complaint. This script, when used as part of an adequate pipeline, can automate the process of answering to known 'offenders', requesting additional information. The pipeline I use looks like: find empty -mtime -1 -type f \ | xargs acat -R___END_OF_REPORT___ \ | requester -t template -r relay -s abuse@mydomain The following options are recognized: =over =item B<-h> Outputs this documentation. =item B<-v> Be verbose about progress. =item B<-r relay> The relay server to use in order to send the email message with the complaint and the evidence. Defaults to 'mail'. =item B<-s report-email> Specify the RFC-822 address that shoud be used as the sender of the send message. The message will be directed to an address that depends on the type of report that is answered to. =item B<-S separator> A string that is used to separate two different reports in the standard input. Defaults to C<___END_OF_REPORT___>. =item B<-t template> The template used to generate the email response. Within the template, the following substitutions can be provided: =over =item %IP% The IP address to which the original reporte referred, or C<[unknown]>. =item %Subject% The subject on the original complaint message or C<[unknown]>. =item %Reply% The address supplied as the sender in the command line. =item %Date% The contents of the C header on the complaint report, or C<[unknown]>. =item %Sender% The sender of the complaint report, as taken from the C, C or C headers, respectively. Otherwise C<[unknown]>. =item %Report% The text of the original report. =back =cut ; use vars qw/ $opt_r $opt_s $opt_S $opt_t $opt_h $opt_v /; getopts('hr:s:S:vt:'); pod2usage(verbose => 2) if $opt_h; pod2usage(verbose => 1) unless $opt_s; pod2usage(verbose => 1) unless $opt_t and -f $opt_t; $opt_r = 'mail' unless $opt_r; $opt_S = '___END_OF_REPORT___' unless $opt_S; $/ = $opt_S; sub report ($$$) { my $r_report = shift; my $destination = shift; my $r_flags = shift; local $/ = undef; my $fh = new IO::File $opt_t or die "Failed to open template $opt_t: $!\n"; my $template = <$fh>; $fh->close; # Perform variable substitution for my $k (keys %$r_flags) { $template =~ s/%$k%/$r_flags->{$k}/g; } # Substitute %Report%, which is a special # case for privacy issues... my $text = ($$r_report =~ /^(Date:.*)$/m) ? "| $1\n" : ''; $text .= ($$r_report =~ /^(From:.*)$/m) ? "| $1\n" : ''; $text .= ($$r_report =~ /^(To:.*)$/m) ? "| $1\n" : ''; $text .= ($$r_report =~ /^(Subject:.*)$/m) ? "| $1\n" : ''; $text .= "| \n"; $text .= ($$r_report =~ /^\s*$ (.*)/msx) ? $1 : '| no body???'; $text =~ s/^([^|])/| $1/gm; $template =~ s/%Report%/$text/g; my $m = new Mail::Mailer 'smtp', Server => $opt_r; $m->open ( { From => $opt_s, To => $destination, 'X-Mailer' => 'Mail::Abuse/requester/' . $VERSION, Subject => 'Automated inquiry about your abuse complaint', }); print $m $template; $m->close; warn "requester: Sent template to $destination\n" if $opt_v; } # Loop through each report fed to us... while (my $report = <>) { # Discard blank lines at the start of the # report... while ($report =~ s/^\s+//) {}; $report =~ s/$opt_S$//; next unless length $report; # MSN - Hotmail if ($report =~ m/^Subject: .* is currently blocked by MSN Hotmail/m and $report =~ m/Microsoft has determined that e-mail or other activity originating from/m and $report =~ m/Your IP address may have been used to conduct/m) { warn "requester: Hotmail report matched\n" if $opt_v; # Match required params my $flags = { Reply => $opt_s }; $report =~ m/^Subject: \[([\d\.]+)\]/m and $flags->{IP} = NetAddr::IP->new($1) || '[unknown]'; $report =~ m/^Date: (.*)/m and $flags->{Date} = $1 || '[unknown]'; $report =~ m/^Subject: (.*)/m and $flags->{Subject} = $1 || '[unknown]'; if ($report =~ m/^From: (.*)/m) { $flags->{Sender} = $1; } elsif ($report =~ m/^Reply-To: (.*)/m) { $flags->{Sender} = $1; } elsif ($report =~ m/^Return-Path: (.*)/m) { $flags->{Sender} = $1; } else { $flags->{Sender} = '[unknown]'; } report \$report, 'nocmail@microsoft.com', $flags; } else { warn "requester: Skipping unknown report type\n" if $opt_v; } } __END__ =pod =back The complaint should be fed through C, as the output of C would. =head1 HISTORY $Log: requester,v $ Revision 1.4 2004/02/15 20:38:19 lem Remove trailing whitespace from the report. Remove delimiter from end of report, if present. Do not process empty inputs. Revision 1.3 2004/02/15 20:22:07 lem Fixed typo in documentation Revision 1.2 2004/02/15 19:55:30 lem Fixed unmatched =back Revision 1.1 2004/02/15 19:36:45 lem Added bin/requester to the distribution. Currently supports reports from MSN Hotmail, which do not include evidence but are too important to simply miss =head1 LICENSE AND WARRANTY This code and all accompanying software comes with NO WARRANTY. You use it at your own risk. This code and all accompanying software can be used freely under the same terms as Perl itself. =head1 AUTHOR Luis E. Muņoz =head1 SEE ALSO perl(1), C, C =cut