You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2004/02/19 08:34:10 UTC

svn commit: rev 6768 - in incubator/spamassassin/trunk: . lib/Mail/SpamAssassin

Author: jm
Date: Wed Feb 18 23:34:09 2004
New Revision: 6768

Added:
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgMetadata.pm
Modified:
   incubator/spamassassin/trunk/MANIFEST
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Bayes.pm
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgContainer.pm
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm
Log:
metadata support; sa-learn can now learn languages and trusted/untrusted relays, so these can now be Bayes tokens

Modified: incubator/spamassassin/trunk/MANIFEST
==============================================================================
--- incubator/spamassassin/trunk/MANIFEST	(original)
+++ incubator/spamassassin/trunk/MANIFEST	Wed Feb 18 23:34:09 2004
@@ -302,3 +302,5 @@
 tools/triplets.pl
 t/reportheader_8bit.t
 t/uri.t
+masses/rule-dev/maildir-scan-headers
+lib/Mail/SpamAssassin/MsgMetadata.pm

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Bayes.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Bayes.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Bayes.pm	Wed Feb 18 23:34:09 2004
@@ -460,14 +460,7 @@
 sub tokenize_headers {
   my ($self, $msg) = @_;
 
-  my $hdrs = $msg->get_all_headers();
-
-  # jm: do not learn additional metadata (X-Languages, X-Relays-Untrusted)
-  # until we can generate that while running sa-learn. TODO
-  #
-  # if ($msg->can ("get_all_metadata")) {
-  # $hdrs .= $msg->get_all_metadata();
-  # }
+  my $hdrs = $msg->get_all_headers() . $msg->get_all_metadata();
 
   my %parsed = ();
 
@@ -677,6 +670,8 @@
     return if $ignore;
   }
 
+  $msg->extract_message_metadata ($self->{main});
+
   my $body = $self->get_body_from_msg ($msg);
   my $ret;
 
@@ -798,6 +793,8 @@
 
   if (!$self->{conf}->{use_bayes}) { return; }
   if (!defined $msg) { return; }
+
+  $msg->extract_message_metadata ($self->{main});
   my $body = $self->get_body_from_msg ($msg);
   my $ret;
 

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm	Wed Feb 18 23:34:09 2004
@@ -2252,35 +2252,14 @@
     return $self->{undesired_language_body};
   }
 
+  $self->{undesired_language_body} = 0;
   my @languages = split (' ', $self->{conf}->{ok_languages});
 
-  # map of languages that are very often mistaken for another, perhaps with
-  # more than 0.02% false positives, we only map if length is < 2048 bytes
-  my %mistakable = ('sco' => 'en');
-
   if (grep { $_ eq "all" } @languages) {
-    $self->{undesired_language_body} = 0;
-    return $self->{undesired_language_body};
-  }
-
-  $body = join ("\n", @{$body});
-  $body =~ s/^Subject://i;
-
-  # need about 256 bytes for reasonably accurate match (experimentally derived)
-  if (length($body) < 256)
-  {
-    dbg("Message too short for language analysis");
-    $self->{undesired_language_body} = 0;
     return $self->{undesired_language_body};
   }
 
-  my @matches = Mail::SpamAssassin::TextCat::classify($self, $body);
-
-  # save matches for possible insertion into headers, etc.
-  $self->{tag_data}->{LANGUAGES} = join(', ', @matches);
-
-  # add to metadata, too, so Bayes gets to take a look
-  $self->{msg}->put_metadata ("X-Languages", $self->{tag_data}->{LANGUAGES});
+  my @matches = @{$self->{msg}->{metadata}->{textcat_matches}};
 
   # not able to get a match, assume it's okay
   if (! @matches) {
@@ -2288,14 +2267,18 @@
     return $self->{undesired_language_body};
   }
 
+  # map of languages that are very often mistaken for another, perhaps with
+  # more than 0.02% false positives
+  my %mistakable = ('sco' => 'en');
+
   # see if any matches are okay
   foreach my $match (@matches) {
     $match =~ s/\..*//;
-    if (length($body) < 2048 && exists $mistakable{$match}) {
+    if (exists $mistakable{$match}) {
       $match = $mistakable{$match};
     }
     foreach my $language (@languages) {
-      if (length($body) < 2048 && exists $mistakable{$language}) {
+      if (exists $mistakable{$language}) {
 	$language = $mistakable{$language};
       }
       if ($match eq $language) {

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgContainer.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgContainer.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgContainer.pm	Wed Feb 18 23:34:09 2004
@@ -38,6 +38,7 @@
 use MIME::Base64;
 use Mail::SpamAssassin;
 use Mail::SpamAssassin::HTML;
+use Mail::SpamAssassin::MsgMetadata;
 use MIME::Base64;
 use MIME::QuotedPrint;
 
@@ -55,7 +56,7 @@
   my $self = {
     headers		=> {},
     raw_headers		=> {},
-    metadata		=> {},
+    meta_strings	=> {},
     body_parts		=> [],
     header_order	=> [],
     already_parsed	=> 1,
@@ -585,13 +586,26 @@
 
 # ---------------------------------------------------------------------------
 
+sub extract_message_metadata {
+  my ($self, $main) = @_;
+
+  # do this only once
+  if ($self->{already_extracted_metadata}) { return; }
+  $self->{already_extracted_metadata} = 1;
+
+  $self->{metadata} = Mail::SpamAssassin::MsgMetadata->new($self);
+  $self->{metadata}->extract ($self, $main);
+}
+
+# ---------------------------------------------------------------------------
+
 =item $str = get_metadata($hdr)
 
 =cut
 
 sub get_metadata {
   my ($self, $hdr) = @_;
-  $self->{metadata}->{$hdr};
+  $self->{meta_strings}->{$hdr};
 }
 
 =item put_metadata($hdr, $text)
@@ -600,7 +614,7 @@
 
 sub put_metadata {
   my ($self, $hdr, $text) = @_;
-  $self->{metadata}->{$hdr} = $text;
+  $self->{meta_strings}->{$hdr} = $text;
 }
 
 =item delete_metadata($hdr)
@@ -609,7 +623,7 @@
 
 sub delete_metadata {
   my ($self, $hdr) = @_;
-  delete $self->{metadata}->{$hdr};
+  delete $self->{meta_strings}->{$hdr};
 }
 
 =item $str = get_all_metadata()
@@ -620,10 +634,23 @@
   my ($self) = @_;
 
   my @ret = ();
-  foreach my $key (sort keys %{$self->{metadata}}) {
-    push (@ret, $key, ": ", $self->{metadata}->{$key}, "\n");
+  foreach my $key (sort keys %{$self->{meta_strings}}) {
+    push (@ret, $key, ": ", $self->{meta_strings}->{$key}, "\n");
   }
   return join ("", @ret);
+}
+
+# ---------------------------------------------------------------------------
+
+=item finish()
+
+Clean up an object so that it can be destroyed.
+
+=cut
+
+sub finish {
+  my ($self) = @_;
+  $self->{metadata}->finish();
 }
 
 # ---------------------------------------------------------------------------

Added: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgMetadata.pm
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/MsgMetadata.pm	Wed Feb 18 23:34:09 2004
@@ -0,0 +1,215 @@
+# $Id: MIME.pm,v 1.8 2003/10/02 22:59:00 quinlan Exp $
+
+# <@LICENSE>
+# Copyright 2004 Apache Software Foundation
+# 
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+#     http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# </...@LICENSE>
+
+=head1 NAME
+
+Mail::SpamAssassin::MsgMetadata - extract metadata from a message
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+This module will extract metadata from an email message.
+
+=head1 PUBLIC METHODS
+
+=over 4
+
+=cut
+
+package Mail::SpamAssassin::MsgMetadata;
+use strict;
+
+use Mail::SpamAssassin;
+use Mail::SpamAssassin::Received;
+use Mail::SpamAssassin::TextCat;
+
+use constant MAX_BODY_LINE_LENGTH =>        2048;
+
+=item new()
+
+=cut
+
+sub new {
+  my ($class, $msg) = @_;
+  $class = ref($class) || $class;
+  my $self = {
+    msg => $msg
+  };
+  bless($self,$class);
+  $self;
+}
+
+sub extract {
+  my ($self, $msg, $main) = @_;
+
+  # add pointers temporarily
+  $self->{main} = $main;
+  $self->{conf} = $main->{conf};
+
+  # pre-chew Received headers
+  $self->parse_received_headers ($msg);
+
+  # and identify the language (if we're going to do that), before we
+  # run any Bayes tests, so they can use that as a token
+  $self->check_language();
+
+  $self->{main}->call_plugins ("extract_metadata", { msg => $msg });
+
+  # remove pointers to avoid circular refs, which break GC'ing
+  delete $self->{main};
+  delete $self->{conf};
+}
+
+sub finish {
+  my ($self) = @_;
+  delete $self->{msg};
+}
+
+# ---------------------------------------------------------------------------
+
+sub check_language {
+  my ($self) = @_;
+
+  my @languages = split (' ', $self->{conf}->{ok_languages});
+  if (grep { $_ eq "all" } @languages) {
+    # user doesn't care what lang it's in, so return.
+    # TODO: might want to have them as bayes tokens all the same, though.
+    # should we add a new config setting to control that?  or make it a
+    # plugin?
+    return;
+  }
+
+  my $body = $self->get_rendered_body_text_array();
+  $body = join ("\n", @{$body});
+  $body =~ s/^Subject://i;
+
+  # need about 256 bytes for reasonably accurate match (experimentally derived)
+  if (length($body) < 256)
+  {
+    dbg("Message too short for language analysis");
+    return;
+  }
+
+  my @matches = Mail::SpamAssassin::TextCat::classify($self, $body);
+  $self->{textcat_matches} = \@matches;
+  my $matches_str = join(' ', @matches);
+
+  # add to metadata so Bayes gets to take a look
+  $self->{msg}->put_metadata ("X-Languages", $matches_str);
+
+  dbg ("metadata: X-Languages: $matches_str");
+}
+
+# ---------------------------------------------------------------------------
+
+sub get_rendered_body_text_array {
+  my ($self) = @_;
+
+  if (exists $self->{text_rendered}) { return $self->{text_rendered}; }
+  local ($_);
+
+  $self->{text_rendered} = [];
+
+  # Find all parts which are leaves
+  my @parts = $self->{msg}->find_parts(qr/^(?:text|message)\b/i,1);
+  return $self->{text_rendered} unless @parts;
+
+  # Go through each part
+  my $text = $self->{msg}->get_header ('subject') || '';
+  for(my $pt = 0 ; $pt <= $#parts ; $pt++ ) {
+    my $p = $parts[$pt];
+
+    my($type, $rnd) = $p->rendered(); # decode this part
+    if ( defined $rnd ) {
+      # Only text/* types are rendered ...
+      $text .= $text ? "\n$rnd" : $rnd;
+
+      # TVD - if there are multiple parts, what should we do?
+      # right now, just use the last one ...
+      $self->{html} = $p->{html_results} if ( $type eq 'text/html' );
+    }
+    else {
+      $text .= $text ? "\n".$p->decode() : $p->decode();
+    }
+  }
+
+  # whitespace handling (warning: small changes have large effects!)
+  $text =~ s/\n+\s*\n+/\f/gs;                # double newlines => form feed
+  $text =~ tr/ \t\n\r\x0b\xa0/ /s;        # whitespace => space
+  $text =~ tr/\f/\n/;                        # form feeds => newline
+
+  my @textary = split_into_array_of_short_lines ($text);
+  $self->{text_rendered} = \@textary;
+
+  return $self->{text_rendered};
+}
+
+# ---------------------------------------------------------------------------
+
+sub get_decoded_body_text_array {
+  my ($self) = @_;
+
+  if (defined $self->{text_decoded}) { return $self->{text_decoded}; }
+
+  $self->{text_decoded} = [ ];
+  local ($_);
+
+  # Find all parts which are leaves
+  my @parts = $self->{msg}->find_parts(qr/./,1);
+  return $self->{text_decoded} unless @parts;
+
+  # Go through each part
+  for(my $pt = 0 ; $pt <= $#parts ; $pt++ ) {
+    my $p = $parts[$pt];
+
+    # For below, we really only care about textual parts
+    if ( $p->{'type'} !~ /^(?:text|message)\b/i ) {
+      # remove this part from our array
+      splice @parts, $pt--, 1;
+      next;
+    }
+
+    $p->decode(); # decode this part
+    push(@{$self->{text_decoded}}, "\n") if ( @{$self->{text_decoded}} );
+    push(@{$self->{text_decoded}},
+      map { split_into_array_of_short_lines($_) } @{$p->{'decoded'}} );
+  }
+
+  return $self->{text_decoded};
+}
+
+# ---------------------------------------------------------------------------
+
+sub split_into_array_of_short_lines {
+  my @result = ();
+  foreach my $line (split (/^/m, $_[0])) {
+    while (length ($line) > MAX_BODY_LINE_LENGTH) {
+      push (@result, substr($line, 0, MAX_BODY_LINE_LENGTH));
+      substr($line, 0, MAX_BODY_LINE_LENGTH) = '';
+    }
+    push (@result, $line);
+  }
+  @result;
+}
+
+# ---------------------------------------------------------------------------
+
+#sub dbg { Mail::SpamAssassin::dbg(@_); }
+
+1;

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm	Wed Feb 18 23:34:09 2004
@@ -55,12 +55,9 @@
 use Mail::SpamAssassin::EvalTests;
 use Mail::SpamAssassin::AutoWhitelist;
 use Mail::SpamAssassin::Conf;
-use Mail::SpamAssassin::Received;
 use Mail::SpamAssassin::Util;
 use Mail::SpamAssassin::MsgContainer;
 
-use constant MAX_BODY_LINE_LENGTH =>        2048;
-
 use vars qw{
   @ISA
 };
@@ -140,19 +137,7 @@
     $self->{conf}->set_score_set ($set|2);
   }
 
-  # pre-chew Received headers
-  $self->parse_received_headers();
-
-  # and identify the language (if we're going to do that), before we
-  # run any Bayes tests, so they can use that as a token
-  {
-    my $decoded = $self->get_decoded_stripped_body_text_array();
-    $self->_check_language ($decoded);
-    undef $decoded;                # this is cached anyway for the main set
-  }
-
-  # allow plugins to add more metadata, read the stuff that's there, etc.
-  $self->{main}->call_plugins ("parsed_metadata", { permsgstatus => $self });
+  $self->extract_message_metadata();
 
   {
     # Here, we launch all the DNS RBL queries and let them run while we
@@ -1000,114 +985,37 @@
 }
 
 ###########################################################################
-# Non-public methods from here on.
 
-sub get_decoded_body_text_array {
+sub extract_message_metadata {
   my ($self) = @_;
 
-  if (defined $self->{decoded_body_text_array}) { return $self->{decoded_body_text_array}; }
-
-  local ($_);
+  $self->{msg}->extract_message_metadata($self->{main});
 
-  $self->{decoded_body_text_array} = [ ];
-  $self->{found_encoding_base64} = 0;
-  $self->{found_encoding_quoted_printable} = 0;
-
-  # Find all parts which are leaves
-  my @parts = $self->{msg}->find_parts(qr/./,1);
-  return $self->{decoded_body_text_array} unless @parts;
-
-  # Go through each part
-  for(my $pt = 0 ; $pt <= $#parts ; $pt++ ) {
-    my $p = $parts[$pt];
-
-    # Mark if there's a part with base64 or qp encoding.  If we've already found at least one of each,
-    # don't bother looking for anymore of them.
-    unless ( $self->{found_encoding_base64} && $self->{found_encoding_quoted_printable} ) {
-      my $cte = $p->get_header ('Content-Transfer-Encoding');
-      if (defined $cte && $cte =~ /quoted-printable/i) {
-        $self->{found_encoding_quoted_printable} = 1;
-      }
-      elsif (defined $cte && $cte =~ /base64/i) {
-        $self->{found_encoding_base64} = 1;
-      }
-    }
-
-    # For below, we really only care about textual parts
-    if ( $p->{'type'} !~ /^(?:text|message)\b/i ) {
-      # remove this part from our array
-      splice @parts, $pt--, 1;
-      next;
-    }
-
-    $p->decode(); # decode this part
-    push(@{$self->{decoded_body_text_array}}, "\n") if ( @{$self->{decoded_body_text_array}} );
-    push(@{$self->{decoded_body_text_array}},
-      map { $self->split_into_array_of_short_lines($_) } @{$p->{'decoded'}} );
+  foreach my $item (qw(
+	relays_trusted relays_trusted_str num_relays_trusted
+	relays_untrusted relays_untrusted_str num_relays_untrusted
+	))
+  {
+    $self->{$item} = $self->{msg}->{metadata}->{$item};
   }
 
-  return $self->{decoded_body_text_array};
-}
-
-sub split_into_array_of_short_lines {
-  my $self = shift;
+  $self->{tag_data}->{RELAYSTRUSTED} = $self->{relays_trusted_str};
+  $self->{tag_data}->{RELAYSUNTRUSTED} = $self->{relays_untrusted_str};
+  $self->{tag_data}->{LANGUAGES} = $self->{msg}->{metadata}->{"X-Languages"};
 
-  my @result = ();
-  foreach my $line (split (/^/m, $_[0])) {
-    while (length ($line) > MAX_BODY_LINE_LENGTH) {
-      push (@result, substr($line, 0, MAX_BODY_LINE_LENGTH));
-      substr($line, 0, MAX_BODY_LINE_LENGTH) = '';
-    }
-    push (@result, $line);
-  }
-  @result;
+  # allow plugins to add more metadata, read the stuff that's there, etc.
+  $self->{main}->call_plugins ("parsed_metadata", { permsgstatus => $self });
 }
 
-
 ###########################################################################
+# Non-public methods from here on.
 
-# this really wants to get the rendered version ...
-sub get_decoded_stripped_body_text_array {
-  my ($self) = @_;
-
-  if (defined $self->{decoded_stripped_body_text_array}) { return $self->{decoded_stripped_body_text_array}; }
-
-  local ($_);
-
-  $self->{decoded_stripped_body_text_array} = [];
-
-  # Find all parts which are leaves
-  my @parts = $self->{msg}->find_parts(qr/^(?:text|message)\b/i,1);
-  return $self->{decoded_stripped_body_text_array} unless @parts;
-
-  # Go through each part
-  my $text = $self->get('subject') || '';
-  for(my $pt = 0 ; $pt <= $#parts ; $pt++ ) {
-    my $p = $parts[$pt];
-
-    my($type, $rnd) = $p->rendered(); # decode this part
-    if ( defined $rnd ) {
-      # Only text/* types are rendered ...
-      $text .= $text ? "\n$rnd" : $rnd;
-
-      # TVD - if there are multiple parts, what should we do?
-      # right now, just use the last one ...
-      $self->{html} = $p->{html_results} if ( $type eq 'text/html' );
-    }
-    else {
-      $text .= $text ? "\n".$p->decode() : $p->decode();
-    }
-  }
-
-  # whitespace handling (warning: small changes have large effects!)
-  $text =~ s/\n+\s*\n+/\f/gs;                # double newlines => form feed
-  $text =~ tr/ \t\n\r\x0b\xa0/ /s;        # whitespace => space
-  $text =~ tr/\f/\n/;                        # form feeds => newline
-
-  my @textary = $self->split_into_array_of_short_lines ($text);
-  $self->{decoded_stripped_body_text_array} = \@textary;
+sub get_decoded_body_text_array {
+  return $_[0]->{msg}->{metadata}->get_decoded_body_text_array();
+}
 
-  return $self->{decoded_stripped_body_text_array};
+sub get_decoded_stripped_body_text_array {
+  return $_[0]->{msg}->{metadata}->get_decoded_body_text_array();
 }
 
 ###########################################################################

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin.pm	Wed Feb 18 23:34:09 2004
@@ -214,10 +214,31 @@
 }
 
 # ---------------------------------------------------------------------------
+=item $plugin->extract_metadata ( { options ... } )
+
+Signals that a message is being mined for metadata.  Some plugins may wish
+to add their own metadata as well.
+
+=over 4
+
+=item msg
+
+The C<Mail::SpamAssassin::MsgContainer> object for this message.
+
+=back
+
+=cut
+
+sub extract_metadata {
+  my ($self, $opts) = @_;
+  return 0;	# implemented by subclasses, no-op by default
+}
+
+# ---------------------------------------------------------------------------
 =item $plugin->parsed_metadata ( { options ... } )
 
 Signals that a message's metadata has been parsed, and can now be
-accessed, or supplemented, by the plugin.
+accessed by the plugin.
 
 =over 4
 

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Received.pm	Wed Feb 18 23:34:09 2004
@@ -41,17 +41,22 @@
 package Mail::SpamAssassin::Received;
 1;
 
-package Mail::SpamAssassin::PerMsgStatus;
-
+package Mail::SpamAssassin::MsgMetadata;
 use strict;
 use bytes;
 
 use Mail::SpamAssassin::Dns;
+use Mail::SpamAssassin::PerMsgStatus;
 
 use vars qw{
-  $LOCALHOST $CCTLDS_WITH_SUBDELEGATION
+  $LOCALHOST $CCTLDS_WITH_SUBDELEGATION $IP_ADDRESS $IPV4_ADDRESS
+  $IP_IN_RESERVED_RANGE
 };
 
+$IPV4_ADDRESS = $Mail::SpamAssassin::PerMsgStatus::IPV4_ADDRESS;
+$IP_ADDRESS = $Mail::SpamAssassin::PerMsgStatus::IP_ADDRESS;
+$IP_IN_RESERVED_RANGE = $Mail::SpamAssassin::PerMsgStatus::IP_IN_RESERVED_RANGE;
+
 $LOCALHOST = qr{(?:
 		  localhost(?:\.localdomain|)|
 		  127\.0\.0\.1|
@@ -74,11 +79,11 @@
 # ---------------------------------------------------------------------------
 
 sub parse_received_headers {
-  my ($self) = @_;
+  my ($self, $msg) = @_;
 
   $self->{relays} = [ ];
 
-  my $hdrs = $self->get('Received');
+  my $hdrs = $msg->get_header('Received');
   $hdrs ||= '';
 
   $hdrs =~ s/\n[ \t]+/ /gs;
@@ -299,20 +304,17 @@
   # so protect against that here.  These will not appear in the final
   # message; they're just used internally.
 
-#  if ($self->{msg}->can ("delete_header")) {
-#    $self->{msg}->delete_header ("X-Spam-Relays-Trusted");
-#    $self->{msg}->delete_header ("X-Spam-Relays-Untrusted");
-#
-#    if ($self->{msg}->can ("put_metadata")) {
-#      $self->{msg}->put_metadata ("X-Spam-Relays-Trusted",
-#				$self->{relays_trusted_str});
-#      $self->{msg}->put_metadata ("X-Spam-Relays-Untrusted",
-#				$self->{relays_untrusted_str});
-#    }
-#  }
-
-  $self->{tag_data}->{RELAYSTRUSTED} = $self->{relays_trusted_str};
-  $self->{tag_data}->{RELAYSUNTRUSTED} = $self->{relays_untrusted_str};
+  if ($self->{msg}->can ("delete_header")) {
+    $self->{msg}->delete_header ("X-Spam-Relays-Trusted");
+    $self->{msg}->delete_header ("X-Spam-Relays-Untrusted");
+ 
+    if ($self->{msg}->can ("put_metadata")) {
+      $self->{msg}->put_metadata ("X-Spam-Relays-Trusted",
+			$self->{relays_trusted_str});
+      $self->{msg}->put_metadata ("X-Spam-Relays-Untrusted",
+			$self->{relays_untrusted_str});
+    }
+  }
 
   # be helpful; save some cumbersome typing
   $self->{num_relays_trusted} = scalar (@{$self->{relays_trusted}});
@@ -1134,6 +1136,8 @@
   my ($domain) = @_;
   return ($domain =~ /\.${CCTLDS_WITH_SUBDELEGATION}$/);
 }
+
+sub dbg { Mail::SpamAssassin::dbg(@_); }
 
 # ---------------------------------------------------------------------------