#!/usr/bin/perl -wT
# Add spammers to the badmailfrom list (qmail utility)
# Copyright (c) 1999, 2001 by Andrew Pam <xanni@sericyb.com.au>
# v0.1 24 Feb 1999 by Andrew Pam
# v0.2 25 Feb 1999 by Andrew Pam
# v0.3 26 Feb 1999 by Andrew Pam
# v0.9 08 Mar 1999 by Andrew Pam
# v1.0 09 Mar 1999 by Andrew Pam
# v1.1 31 Aug 1999 by Andrew Pam
# v1.2 08 Sep 1999 by Andrew Pam
# v1.3 08 Mar 2001 by Andrew Pam
# SCRIPT DEPRECATED - PLEASE DO NOT USE

# As a system administrator or postmaster, do you get a lot of spam
# addressed to invalid email addresses within your domain(s) that
# double-bounces because it can't be returned to the spammer?
#
# Maybe this script can help.  If you set up qmail aliases to run this
# script for the invalid addresses, email to those addresses will
# automatically add the envelope sender to the badmailfrom file,
# ensuring that qmail doesn't even accept emails from that sender again.
# Since the invalid addresses often seem to come from some sort of
# "bulk mail list", this will often help prevent spam addressed to valid
# addresses in your domain(s) as well!
#
# See "man dot-qmail" for information on setting up qmail aliases.
#
# You can also resend (bounce, not forward!) spam to this script
# and it will add the From: sender of the message to the badmailfrom
# file, since the envelope sender is in one of your own domain(s).
# Because email can easily be forged, this script will never add
# addresses within your own domains(s) as listed in the rcpthosts file
# and will always notify you when it has added an entry.
#
# 2003 update:  PLEASE DO NOT USE THIS SCRIPT.  With changes in the way
# spammers send their emails in the last couple of years this script is not
# only ineffective now but can also potentially result in blocking email
# from legitimate senders whose addresses have been forged by spammers.
#
# Share and enjoy,
#		*** Xanni ***

exit;
use strict;
my $FALSE = 0;
my $TRUE = not $FALSE;
my $CONTROL = "/var/qmail/control";
$ENV{ENV} = "";
$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin";

# Exit with "delivery failed" status
sub fatal($)
{
  warn $_[0];
  exit 100;
}

# Helper subroutine to check if an address matches a domain in rcpthosts
sub inrcpthosts($)
{
  my $address = shift;

  if (open(RCPTHOSTS, "$CONTROL/rcpthosts"))
  {
    while (<RCPTHOSTS>)
    {
      chomp;
      return $TRUE if ($address =~ /\Q$_\E$/i);
    }
    close(RCPTHOSTS);
  }
  return $FALSE;
}

# First, check whether the envelope sender is "one of us"
fatal("Must be executed by qmail, sorry.\n") unless defined $ENV{SENDER};
my $sender = $ENV{SENDER} or fatal("No envelope sender.\n");
my $local = inrcpthosts($sender);
my $from;

if (not $local and ($sender ne "#@[]"))
{ $from = $sender; }
else
{
  # Find the From: header
  while (<>)
  {
    if (/^From: .*\b(\S+\@[\w\.]+)\b/)
    { $from = $1; last; }
  }
  fatal("Sorry, can't find a valid From: header.\n") unless $from;
  fatal("Hey!  <$from> is one of our addresses!\n") if inrcpthosts($from);
}

# Some addresses are special
if ($from =~ /^(MAILER-DAEMON\@)|(postmaster\@)|(root\@)|(owner-)|(bounces-)/i)
{ fatal("Return to sender, address unknown.\n"); }

# Now see if this entry already exists
# Note: the badmailfrom file should probably be locked first
if (open(BMF, "$CONTROL/badmailfrom"))
{
  while (<BMF>)
  {
    chomp;
    exit 0 if $from =~ /\Q$_\E$/;
  }
  close(BMF);
}

# Guess not - so let's go ahead and append the address
# Note: the badmailfrom file should be unlocked afterwards
open(BMF, ">>$CONTROL/badmailfrom")
  or die("Can't append to $CONTROL/badmailfrom: $!\n");
print BMF "$from\n";
close(BMF);

# Finally, someone must be notified (important in case of forgery!)
$sender = "postmaster" unless $local;
open(REPLY, "|qmail-inject") or die("Can't run qmail-inject: $!\n");
print REPLY "From: postmaster\nTo: $sender\nSubject: Anti-spam\n\n";
print REPLY "As a result of an email to <$ENV{RECIPIENT}>,\n";
print REPLY "<$from> was added to the badmailfrom control file.\n";
close(REPLY);
exit 0;
