You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by qu...@apache.org on 2004/08/12 07:45:23 UTC

svn commit: rev 36272 - in spamassassin/trunk: lib/Mail/SpamAssassin rules

Author: quinlan
Date: Wed Aug 11 22:45:22 2004
New Revision: 36272

Modified:
   spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
   spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
   spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
   spamassassin/trunk/rules/20_dnsbl_tests.cf
   spamassassin/trunk/rules/20_head_tests.cf
   spamassassin/trunk/rules/50_scores.cf
Log:
bug 3494: rewrite NO_DNS_FOR_FROM to use DNS-in-background code


Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm	Wed Aug 11 22:45:22 2004
@@ -1278,9 +1278,9 @@
 
 =item rbl_timeout n		(default: 15)
 
-All RBL queries are made at the beginning of a check and we try to read the
+All DNS queries are made at the beginning of a check and we try to read the
 results at the end.  This value specifies the maximum period of time to wait
-for an RBL query.  If most of the RBL queries have succeeded for a particular
+for an DNS query.  If most of the DNS queries have succeeded for a particular
 message, then SpamAssassin will not wait for the full period to avoid wasting
 time on unresponsive server(s).  For the default 15 second timeout, here is a
 chart of queries remaining versus the effective timeout in seconds:
@@ -1304,31 +1304,6 @@
     type => $CONF_TYPE_NUMERIC
   });
 
-=item check_mx_attempts n	(default: 2)
-
-By default, SpamAssassin checks the From: address for a valid MX this many
-times, waiting 5 seconds each time.
-
-=cut
-
-  push (@cmds, {
-    setting => 'check_mx_attempts',
-    default => 2,
-    type => $CONF_TYPE_NUMERIC
-  });
-
-=item check_mx_delay n		(default: 5)
-
-How many seconds to wait before retrying an MX check.
-
-=cut
-
-  push (@cmds, {
-    setting => 'check_mx_delay',
-    default => 5,
-    type => $CONF_TYPE_NUMERIC
-  });
-
 =item dns_available { yes | test[: name1 name2...] | no }   (default: test)
 
 By default, SpamAssassin will query some default hosts on the internet to
@@ -2197,7 +2172,7 @@
       if ($value =~ /^(\S+)\s+(?:rbl)?eval:(.*)$/) {
         my ($name, $fn) = ($1, $2);
 
-        if ($fn =~ /^check_rbl/) {
+        if ($fn =~ /^check_(?:rbl|dns)/) {
           $self->{parser}->add_test ($name, $fn, $TYPE_RBL_EVALS);
         }
         else {
@@ -2410,7 +2385,7 @@
 
 =item priority SYMBOLIC_TEST_NAME n
 
-Assign a specific priority to a test.  All tests, except for RBL and Meta
+Assign a specific priority to a test.  All tests, except for DNS and Meta
 tests, are run in priority order. The default test priority is 0 (zero).
 
 =cut

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm	Wed Aug 11 22:45:22 2004
@@ -131,6 +131,19 @@
   $self->{dnspost}->{$set}->{$subtest} = $rule;
 }
 
+sub do_dns_lookup {
+  my ($self, $rule, $type, $host) = @_;
+
+  # only make a specific query once
+  if (!defined $self->{dnspending}->{$type}->{$host}->[BGSOCK]) {
+    dbg("dns: launching DNS $type query for $host in background", "rbl", -1);
+    $self->{rbl_launch} = time;
+    $self->{dnspending}->{$type}->{$host}->[BGSOCK] =
+	$self->{res}->bgsend($host, $type);
+  }
+  push @{$self->{dnspending}->{$type}->{$host}->[RULES]}, $rule;
+}
+
 ###########################################################################
 
 sub dnsbl_hit {
@@ -176,6 +189,19 @@
   return if !defined $packet;
 
   my $question = ($packet->question)[0];
+
+  # NO_DNS_FOR_FROM
+  if ($self->{sender_host} &&
+      $question->qname eq $self->{sender_host} &&
+      $question->qtype =~ /^(?:A|MX)$/ &&
+      $packet->header->rcode =~ /^(?:NXDOMAIN|SERVFAIL)$/ &&
+      ++$self->{sender_host_fail} == 2)
+  {
+    for my $rule (@{$query->[RULES]}) {
+      $self->got_hit($rule, "DNS: ");
+    }
+  }
+  # DNSBL tests are here
   foreach my $answer ($packet->answer) {
     # track all responses
     $self->dnsbl_uri($question, $answer);
@@ -257,6 +283,7 @@
 
   my $timeout = $self->{conf}->{rbl_timeout} + $self->{rbl_launch};
   my @waiting = (values %{ $self->{dnspending}->{A} },
+		 values %{ $self->{dnspending}->{MX} },
 		 values %{ $self->{dnspending}->{TXT} });
   my @left;
   my $total;
@@ -290,9 +317,15 @@
   dbg("RBL: success for " . ($total - @left) . " of $total queries", "rbl", 0);
   # timeouts
   for my $query (@left) {
-    my $sets = join(",", @{$query->[SETS]});
+    my $string = '';
+    if (defined @{$query->[SETS]}) {
+      $string = join(",", grep defined, @{$query->[SETS]});
+    }
+    elsif (defined @{$query->[RULES]}) {
+      $string = join(",", grep defined, @{$query->[RULES]});
+    }
     my $delay = time - $self->{rbl_launch};
-    dbg("RBL: timeout for $sets after $delay seconds", "rbl", 0);
+    dbg("DNS: timeout for $string after $delay seconds", "rbl", 0);
     undef $query->[BGSOCK];
   }
   # register hits

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm	(original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm	Wed Aug 11 22:45:22 2004
@@ -76,64 +76,6 @@
 # HEAD TESTS:
 ###########################################################################
 
-sub check_for_from_dns {
-  my ($self) = @_;
-
-  if (!defined ($self->{checked_for_from_dns})) {
-    $self->{checked_for_from_dns} = $self->_check_for_from_dns();
-  }
-
-  return $self->{checked_for_from_dns};
-}
-
-sub _check_for_from_dns {
-  my ($self) = @_;
-
-  my $from;
-  foreach $from ($self->get('Reply-To:addr'), $self->get('From:addr')) {
-    next unless defined $from;
-
-    # bug 3366
-    $from =~ tr/././s;
-
-    if ($from =~ /\@(\S+\.\S+)/) {
-      $from = $1;
-      last;
-    }
-    undef $from;
-  }
-  return 0 unless (defined $from);
-  $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;
-  }
-
-  if ($self->{conf}->{check_mx_attempts} < 1) {
-    return 0;
-  }
-
-  # Try check_mx_attempts 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}) {
-    return 0 if ($self->lookup_mx_exists ($from));
-    return 0 if ($self->lookup_a ($from));
-    if ($i < $self->{conf}->{check_mx_attempts}) {
-      sleep $self->{conf}->{check_mx_delay};
-    }
-  }
-
-  $self->set_server_failed_to_respond_for_domain($from);
-  return 1;
-}
-
-###########################################################################
-
 # From and To have same address, but are not exactly the same and
 # neither contains intermediate spaces.
 sub check_for_from_to_same {
@@ -1467,6 +1409,50 @@
   $self->load_resolver();
   for my $host (keys %hosts) {
     $self->do_rbl_lookup($rule, $set, 'A', $rbl_server, "$host.$rbl_server");
+  }
+}
+
+sub check_dns_sender {
+  my ($self, $rule) = @_;
+
+  my $host;
+  for my $from ($self->get('EnvelopeFrom:addr')) {
+    next unless defined $from;
+
+    $from =~ tr/././s;		# bug 3366
+    if ($from =~ /\@(\S+\.\S+)/) {
+      $host = lc($1);
+      last;
+    }
+  }
+  return 0 unless defined $host;
+
+  # First check that DNS is available, if not do not perform this check
+  # TODO: need a way to skip DNS checks as a whole in configuration
+  return 0 unless $self->is_dns_available();
+  $self->load_resolver();
+
+  if ($host eq 'compiling.spamassassin.taint.org') {
+    # only used when compiling
+    return 0;
+  }
+
+  dbg ("checking A and MX for host $host", "rbl", -1);
+
+  $self->do_dns_lookup($rule, 'A', $host);
+  $self->do_dns_lookup($rule, 'MX', $host);
+
+  # cache name of host for later checking
+  $self->{sender_host} = $host;
+
+  return 0;
+}
+
+# interface called by SPF plugin
+sub check_for_from_dns {
+  my ($self) = @_;
+  if (defined $self->{sender_host_fail}) {
+    return ($self->{sender_host_fail} == 2); # both MX and A need to fail
   }
 }
 

Modified: spamassassin/trunk/rules/20_dnsbl_tests.cf
==============================================================================
--- spamassassin/trunk/rules/20_dnsbl_tests.cf	(original)
+++ spamassassin/trunk/rules/20_dnsbl_tests.cf	Wed Aug 11 22:45:22 2004
@@ -268,3 +268,10 @@
 #header RCVD_IN_MAPS_OPS	eval:check_rbl_sub('rblplus', '8')
 #describe RCVD_IN_MAPS_OPS	Relay in OPS, http://www.mail-abuse.org/ops/
 #tflags RCVD_IN_MAPS_OPS	net
+
+# ---------------------------------------------------------------------------
+# Other DNS tests
+
+header NO_DNS_FOR_FROM		eval:check_dns_sender()
+describe NO_DNS_FOR_FROM	Envelope sender has no MX or A DNS records
+tflags NO_DNS_FOR_FROM		net

Modified: spamassassin/trunk/rules/20_head_tests.cf
==============================================================================
--- spamassassin/trunk/rules/20_head_tests.cf	(original)
+++ spamassassin/trunk/rules/20_head_tests.cf	Wed Aug 11 22:45:22 2004
@@ -287,10 +287,6 @@
 header FRIEND_PUBLIC		ALL =~ /^(?:to|cc|from):.*friend\@public\.com/im
 describe FRIEND_PUBLIC		sent from or to friend@public.com
 
-header NO_DNS_FOR_FROM		eval:check_for_from_dns()
-describe NO_DNS_FOR_FROM	Domain in From header has no MX or A DNS records
-tflags NO_DNS_FOR_FROM          net
-
 header FROM_AND_TO_SAME		eval:check_for_from_to_same()
 describe FROM_AND_TO_SAME	From and To are the same, but not exactly
 

Modified: spamassassin/trunk/rules/50_scores.cf
==============================================================================
--- spamassassin/trunk/rules/50_scores.cf	(original)
+++ spamassassin/trunk/rules/50_scores.cf	Wed Aug 11 22:45:22 2004
@@ -555,7 +555,7 @@
 score NO_COST 0.078 0.002 0.335 0.000
 score NO_CREDIT_CHECK 0 0.000 1.990 0.037 # n=0
 score NO_DISAPPOINTMENT 0 1.498 1.609 0.410 # n=0
-score NO_DNS_FOR_FROM 0 # n=0 n=1 n=2 n=3
+score NO_DNS_FOR_FROM 0 1.1 0 1.6
 score NO_EXPERIENCE 0 # n=0 n=1
 score NO_FEE 0 # n=0 n=1
 score NO_FORMS 1.622 0.973 0.912 0.011