Index: lib/Mail/SpamAssassin/Conf.pm
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/lib/Mail/SpamAssassin/Conf.pm,v
retrieving revision 1.53
diff -u -r1.53 Conf.pm
--- lib/Mail/SpamAssassin/Conf.pm	2 Feb 2002 04:35:29 -0000	1.53
+++ lib/Mail/SpamAssassin/Conf.pm	18 Feb 2002 06:56:43 -0000
@@ -115,6 +115,8 @@
   $self->{more_spam_to} = { };
   $self->{all_spam_to} = { };
 
+  $self->{blacklist_mx} = { };
+
   $self->{spamphrase} = { };
   $self->{spamphrase_highest_score} = 0;
 
@@ -231,6 +233,17 @@
     }
     if (/^all[-_]spam[-_]to\s+(.+)\s*$/) {
       $self->add_to_addrlist ('all_spam_to', split (' ', $1)); next;
+    }
+
+=item blacklist_mx 127.0.0.1
+
+Penalize the mail if any of the MX servers for the From address are
+listed here.
+
+=cut
+
+    if (/^blacklist[-_]mx\s+(.+)\s*$/) {
+      $self->add_to_addrlist ('blacklist_mx', split (' ', $1)); next;
     }
 
 =item required_hits n.nn   (default: 5)
Index: lib/Mail/SpamAssassin/EvalTests.pm
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/lib/Mail/SpamAssassin/EvalTests.pm,v
retrieving revision 1.105
diff -u -r1.105 EvalTests.pm
--- lib/Mail/SpamAssassin/EvalTests.pm	4 Feb 2002 07:58:50 -0000	1.105
+++ lib/Mail/SpamAssassin/EvalTests.pm	18 Feb 2002 06:56:43 -0000
@@ -68,7 +68,7 @@
   # to give the DNS a chance to recover.
   for my $i (1..$self->{conf}->{check_mx_attempts}) {
     my @mx = Net::DNS::mx ($self->{res}, $from);
-    dbg ("DNS MX records found: ".scalar (@mx));
+    dbg ("DNS MX records found for valid MX test: ".scalar (@mx));
     if (scalar @mx > 0) { return 0; }
     if ($i < $self->{conf}->{check_mx_attempts}) {sleep $self->{conf}->{check_mx_delay}; };
   }
@@ -78,6 +78,38 @@
 
 ###########################################################################
 
+sub check_for_mx_in_blacklist {
+  my ($self) = @_;
+
+  my $from = $self->get ('From:addr');
+  return 0 unless ($from =~ /\@(\S+)/);
+  $from = $1;
+
+  # First check that DNS is available, if not do not perform this check
+  return 0 unless $self->is_dns_available();
+  $self->load_resolver();
+
+  if ($from eq 'compiling.spamassassin.taint.org') {
+    # only used when compiling
+    return 0;
+  }
+
+  # Try 3 times to protect against temporary outages.  sleep between checks
+  # to give the DNS a chance to recover.
+  for my $i (1..$self->{conf}->{check_mx_attempts}) {
+    my @mx = Net::DNS::mx ($self->{res}, $from);
+    dbg ("DNS MX records found for blacklisted MX test: ".scalar (@mx));
+    for my $j (@mx) {
+	dbg ("Current MX server to check: " . $j->exchange);
+        return 1 if ($self->_check_whitelist ($self->{conf}->{blacklist_mx}, $j->exchange));
+    }
+    if ($i < $self->{conf}->{check_mx_attempts}) {sleep $self->{conf}->{check_mx_delay}; };
+  }
+  return 0;
+}
+
+###########################################################################
+
 sub check_for_bad_dialup_ips {
   my ($self) = @_;
   local ($_);
@@ -101,6 +133,19 @@
 
   if ($from eq '' && $to eq '') { return 0; }
   ($from eq $to);
+}
+
+###########################################################################
+
+sub check_if_listed_recipient {
+  my ($self) = @_;
+  my $deliveredto = $self->get ('Delivered-To:addr');
+  my $to = $self->get ('To');
+  my $cc = $self->get ('Cc');
+
+  if ($deliveredto eq '') { return 0; }
+  if (($to =~ /${deliveredto}/i) || ($cc =~ /${deliveredto}/i)) { return 0; }
+  return 1;
 }
 
 ###########################################################################
Index: lib/Mail/SpamAssassin/PerMsgStatus.pm
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/lib/Mail/SpamAssassin/PerMsgStatus.pm,v
retrieving revision 1.73
diff -u -r1.73 PerMsgStatus.pm
--- lib/Mail/SpamAssassin/PerMsgStatus.pm	10 Feb 2002 01:37:30 -0000	1.73
+++ lib/Mail/SpamAssassin/PerMsgStatus.pm	18 Feb 2002 06:56:43 -0000
@@ -355,7 +355,7 @@
 
   # add some headers...
 
-  $_ = sprintf ("Yes, hits=%2.1f required=%2.1f tests=%s version=%s",
+  $_ = sprintf ("Yes, hits=%2.2f required=%2.2f tests=%s version=%s",
 	$self->{hits}, $self->{conf}->{required_hits},
 	$self->get_names_of_tests_hit(),
 	$Mail::SpamAssassin::VERSION);
@@ -417,7 +417,7 @@
 
   $self->{test_names_hit} =~ s/,$//;
 
-  $_ = sprintf ("No, hits=%2.1f required=%2.1f tests=%s version=%s",
+  $_ = sprintf ("No, hits=%2.2f required=%2.2f tests=%s version=%s",
 	$self->{hits}, $self->{conf}->{required_hits},
 	$self->get_names_of_tests_hit(),
 	$Mail::SpamAssassin::VERSION);
@@ -1118,7 +1118,7 @@
   $self->{test_names_hit} .= $rule.",";
 
   if ($self->{conf}->{use_terse_report}) {
-    $self->{test_logs} .= sprintf ("* % 2.1f -- %s%s\n%s",
+    $self->{test_logs} .= sprintf ("* % 2.2f -- %s%s\n%s",
                           $score, $area, $desc, $self->{test_log_msgs});
   } else {
     $self->{test_logs} .= sprintf ("%-18s %s%s\n%s",
Index: rules/20_head_tests.cf
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/rules/20_head_tests.cf,v
retrieving revision 1.31
diff -u -r1.31 20_head_tests.cf
--- rules/20_head_tests.cf	13 Feb 2002 16:58:42 -0000	1.31
+++ rules/20_head_tests.cf	18 Feb 2002 06:56:43 -0000
@@ -109,6 +109,9 @@
 header NO_MX_FOR_FROM		eval:check_for_from_mx()
 describe NO_MX_FOR_FROM		No MX records for the From: domain
 
+header FROM_MX_BLACKLISTED	eval:check_for_mx_in_blacklist()
+describe FROM_MX_BLACKLISTED	From: domain MX record in blacklist
+
 header KNOWN_BAD_DIALUPS	eval:check_for_bad_dialup_ips()
 describe KNOWN_BAD_DIALUPS	Received via known spam-harbouring dialups
 
Index: rules/50_scores.cf
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/rules/50_scores.cf,v
retrieving revision 1.35
diff -u -r1.35 50_scores.cf
--- rules/50_scores.cf	6 Feb 2002 07:50:12 -0000	1.35
+++ rules/50_scores.cf	18 Feb 2002 06:56:43 -0000
@@ -284,6 +284,7 @@
 score SUBJ_ENDS_IN_Q_MARK            0.1
 score SUBJ_HAS_Q_MARK                0.1
 score NO_MX_FOR_FROM                 1.8
+score FROM_MX_BLACKLISTED            3.0
 score RAZOR_CHECK		     3.0
 score RCVD_IN_RELAYS_ORDB_ORG	     2.0
 score RCVD_IN_OSIRUSOFT_COM	     2.0
