"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/Mail/SpamAssassin/PerMsgStatus.pm" between
Mail-SpamAssassin-3.4.4.tar.bz2 and Mail-SpamAssassin-3.4.5.tar.bz2

About: SpamAssassin is a mail filter that uses a wide range of heuristic tests on mail headers and body text to identify "spam" (also known as unsolicited commercial email) incl. Bayesian (statistical) spam filter and several internet-based realtime blacklists.

PerMsgStatus.pm  (Mail-SpamAssassin-3.4.4.tar.bz2):PerMsgStatus.pm  (Mail-SpamAssassin-3.4.5.tar.bz2)
skipping to change at line 310 skipping to change at line 310
my $dbgcache = would_log('dbg', 'rules'); my $dbgcache = would_log('dbg', 'rules');
if ($dbgcache || $self->{save_pattern_hits}) { if ($dbgcache || $self->{save_pattern_hits}) {
$self->{should_log_rule_hits} = 1; $self->{should_log_rule_hits} = 1;
} }
# known valid tags that might not get their entry in pms->{tag_data} # known valid tags that might not get their entry in pms->{tag_data}
# in some circumstances # in some circumstances
my $tag_data_ref = $self->{tag_data}; my $tag_data_ref = $self->{tag_data};
foreach (qw(SUMMARY REPORT SUBJPREFIX RBL)) { $tag_data_ref->{$_} = '' } foreach (qw(SUMMARY REPORT SUBJPREFIX RBL)) { $tag_data_ref->{$_} = '' }
foreach (qw(AWL AWLMEAN AWLCOUNT AWLPRESCORE foreach (qw(AWL AWLMEAN AWLCOUNT AWLPRESCORE
DCCB DCCR DCCREP PYZOR DKIMIDENTITY DKIMDOMAIN DCCB DCCR DCCREP PYZOR DKIMIDENTITY DKIMDOMAIN DKIMSELECTOR
BAYESTC BAYESTCLEARNED BAYESTCSPAMMY BAYESTCHAMMY BAYESTC BAYESTCLEARNED BAYESTCSPAMMY BAYESTCHAMMY
HAMMYTOKENS SPAMMYTOKENS TOKENSUMMARY)) { HAMMYTOKENS SPAMMYTOKENS TOKENSUMMARY)) {
$tag_data_ref->{$_} = undef; # exist, but undefined $tag_data_ref->{$_} = undef; # exist, but undefined
} }
bless ($self, $class); bless ($self, $class);
$self; $self;
} }
sub DESTROY { sub DESTROY {
skipping to change at line 1102 skipping to change at line 1102
my $cc = $self->{msg}->get_pristine_header("Cc"); my $cc = $self->{msg}->get_pristine_header("Cc");
my $subject = $self->{msg}->get_pristine_header("Subject"); my $subject = $self->{msg}->get_pristine_header("Subject");
my $msgid = $self->{msg}->get_pristine_header('Message-Id'); my $msgid = $self->{msg}->get_pristine_header('Message-Id');
my $date = $self->{msg}->get_pristine_header("Date"); my $date = $self->{msg}->get_pristine_header("Date");
# It'd be nice to do this with a foreach loop, but with only three # It'd be nice to do this with a foreach loop, but with only three
# possibilities right now, it's easier not to... # possibilities right now, it's easier not to...
if (defined $self->{conf}->{rewrite_header}->{Subject}) { if (defined $self->{conf}->{rewrite_header}->{Subject}) {
# Add a prefix to the subject if needed # Add a prefix to the subject if needed
$subject = "\n" if !defined $subject;
if((defined $self->{subjprefix}) and ($self->{subjprefix} ne "")) { if((defined $self->{subjprefix}) and ($self->{subjprefix} ne "")) {
$tag = $self->_replace_tags($self->{subjprefix}); $tag = $self->_replace_tags($self->{subjprefix});
$tag =~ s/\n/ /gs; $tag =~ s/\n/ /gs;
$subject = $tag . $subject; $subject = $tag . $subject;
} }
# Add a **SPAM** prefix # Add a **SPAM** prefix
$subject = "\n" if !defined $subject;
$tag = $self->_replace_tags($self->{conf}->{rewrite_header}->{Subject}); $tag = $self->_replace_tags($self->{conf}->{rewrite_header}->{Subject});
$tag =~ s/\n/ /gs; # strip tag's newlines $tag =~ s/\n/ /gs; # strip tag's newlines
$subject =~ s/^(?:\Q${tag}\E )?/${tag} /g; # For some reason the tag may alr eady be there!? $subject =~ s/^(?:\Q${tag}\E )?/${tag} /g; # For some reason the tag may alr eady be there!?
} }
if (defined $self->{conf}->{rewrite_header}->{To}) { if (defined $self->{conf}->{rewrite_header}->{To}) {
$to = "\n" if !defined $to; $to = "\n" if !defined $to;
my $tag = $self->_replace_tags($self->{conf}->{rewrite_header}->{To}); my $tag = $self->_replace_tags($self->{conf}->{rewrite_header}->{To});
$tag =~ s/\n/ /gs; # strip tag's newlines $tag =~ s/\n/ /gs; # strip tag's newlines
$to =~ s/(?:\t\Q(${tag})\E)?$/\t(${tag})/; $to =~ s/(?:\t\Q(${tag})\E)?$/\t(${tag})/;
skipping to change at line 2925 skipping to change at line 2925
$self->{test_log_msgs}->{TERSE} .= sprintf ("[%s]\n", $msg); $self->{test_log_msgs}->{TERSE} .= sprintf ("[%s]\n", $msg);
if (length($msg) > 47) { if (length($msg) > 47) {
$self->{test_log_msgs}->{LONG} .= sprintf ("%78s\n", "[$msg]"); $self->{test_log_msgs}->{LONG} .= sprintf ("%78s\n", "[$msg]");
} else { } else {
$self->{test_log_msgs}->{LONG} .= sprintf ("%27s [%s]\n", "", $msg); $self->{test_log_msgs}->{LONG} .= sprintf ("%27s [%s]\n", "", $msg);
} }
} }
########################################################################### ###########################################################################
# helper for get(). Do not call directly, as get() caches its results # helper for get()
# and this does not!
sub get_envelope_from { sub get_envelope_from {
my ($self) = @_; my ($self) = @_;
# Cached?
return $self->{envelopefrom} if exists $self->{envelopefrom};
# bug 2142: # bug 2142:
# Get the SMTP MAIL FROM:, aka. the "envelope sender", if our # Get the SMTP MAIL FROM:, aka. the "envelope sender", if our
# calling app has helpfully marked up the source message # calling app has helpfully marked up the source message
# with it. Various MTAs and calling apps each have their # with it. Various MTAs and calling apps each have their
# own idea of what header to use for this! see # own idea of what header to use for this! see
my $envf; my $envf;
# Rely on the 'envelope-sender-header' header if the user has configured one. # Rely on the 'envelope-sender-header' header if the user has configured one.
# Assume that because they have configured it, their MTA will always add it. # Assume that because they have configured it, their MTA will always add it.
# This will prevent us falling through and picking up inappropriate headers. # This will prevent us falling through and picking up inappropriate headers.
if (defined $self->{conf}->{envelope_sender_header}) { if (defined $self->{conf}->{envelope_sender_header}) {
# make sure we get the most recent copy - there can be only one EnvelopeSend er. # make sure we get the most recent copy - there can be only one EnvelopeSend er.
$envf = $self->get($self->{conf}->{envelope_sender_header}.":addr",undef); $envf = $self->get($self->{conf}->{envelope_sender_header}.":addr",undef);
# ok if it contains an "@" sign, or is "" (ie. "<>" without the < and >) # ok if it contains an "@" sign, or is "" (ie. "<>" without the < and >)
goto ok if defined $envf && ($envf =~ /\@/ || $envf eq ''); if (defined $envf && (index($envf, '@') > 0 || $envf eq '')) {
dbg("message: using envelope_sender_header '%s' as EnvelopeFrom: '%s'",
$self->{conf}->{envelope_sender_header}, $envf);
$self->{envelopefrom} = $envf;
return $envf;
}
# Warn them if it's configured, but not there or not usable. # Warn them if it's configured, but not there or not usable.
if (defined $envf) { if (defined $envf) {
chomp $envf; dbg("message: envelope_sender_header '%s': '%s' is not valid, ignoring",
dbg("message: envelope_sender_header '%s: %s' is not an FQDN, ignoring",
$self->{conf}->{envelope_sender_header}, $envf); $self->{conf}->{envelope_sender_header}, $envf);
} else { } else {
dbg("message: envelope_sender_header '%s' not found in message", dbg("message: envelope_sender_header '%s' not found in message",
$self->{conf}->{envelope_sender_header}); $self->{conf}->{envelope_sender_header});
} }
# Couldn't get envelope-sender using the configured header. # Couldn't get envelope-sender using the configured header.
$self->{envelopefrom} = undef;
return; return;
} }
# User hasn't given us a header to trust, so try to guess the sender. # User hasn't given us a header to trust, so try to guess the sender.
# use the "envelope-sender" string found in the Received headers, # use the "envelope-sender" string found in the Received headers,
# if possible... use the last untrusted header, in case there's # if possible... use the last untrusted header, in case there's
# trusted headers. # trusted headers.
my $lasthop = $self->{relays_untrusted}->[0]; my $lasthop = $self->{relays_untrusted}->[0];
my $lasthop_str = 'last untrusted';
if (!defined $lasthop) { if (!defined $lasthop) {
# no untrusted headers? in that case, the message is ALL_TRUSTED. # no untrusted headers? in that case, the message is ALL_TRUSTED.
# use the first trusted header (ie. the oldest, originating one). # use the first trusted header (ie. the oldest, originating one).
$lasthop = $self->{relays_trusted}->[-1]; $lasthop = $self->{relays_trusted}->[-1];
$lasthop_str = 'first trusted';
} }
if (defined $lasthop) { if (defined $lasthop) {
$envf = $lasthop->{envfrom}; $envf = $lasthop->{envfrom};
# TODO FIXME: Received.pm puts both null senders and absence-of-sender # ok if it contains an "@" sign, or is "" (ie. "<>" without the < and >)
# into the relays array as '', so we can't distinguish them :( if (defined $envf && (index($envf, '@') > 0 || $envf eq '')) {
if ($envf && ($envf =~ /\@/)) { dbg("message: using $lasthop_str relay envelope-from as EnvelopeFrom: '$en
goto ok; vf'");
$self->{envelopefrom} = $envf;
return $envf;
} }
} }
# WARNING: a lot of list software adds an X-Sender for the original env-from # WARNING: a lot of list software adds an X-Sender for the original env-from
# (including Yahoo! Groups). Unfortunately, fetchmail will pick it up and # (including Yahoo! Groups). Unfortunately, fetchmail will pick it up and
# reuse it as the env-from for *its* delivery -- even though the list # reuse it as the env-from for *its* delivery -- even though the list
# software had used a different env-from in the intervening delivery. Hence, # software had used a different env-from in the intervening delivery. Hence,
# if this header is present, and there's a fetchmail sig in the Received # if this header is present, and there's a fetchmail sig in the Received
# lines, we cannot trust any Envelope-From headers, since they're likely to # lines, we cannot trust any Envelope-From headers, since they're likely to
# be incorrect fetchmail guesses. # be incorrect fetchmail guesses.
if ($self->get("X-Sender") =~ /\@/) { if (index($self->get("X-Sender"), '@') != -1) {
my $rcvd = join(' ', $self->get("Received")); my $rcvd = join(' ', $self->get("Received"));
if ($rcvd =~ /\(fetchmail/) { if (index($rcvd, '(fetchmail') != -1) {
dbg("message: X-Sender and fetchmail signatures found, cannot trust envelo pe-from"); dbg("message: X-Sender and fetchmail signatures found, cannot trust envelo pe-from");
$self->{envelopefrom} = undef;
return; return;
} }
} }
# procmailrc notes this (we now recommend adding it to Received instead) # procmailrc notes this (we now recommend adding it to Received instead)
if ($envf = $self->get("X-Envelope-From")) { if (defined($envf = $self->get("X-Envelope-From:addr",undef))) {
# heuristic: this could have been relayed via a list which then used # heuristic: this could have been relayed via a list which then used
# a *new* Envelope-from. check # a *new* Envelope-from. check
if ($self->get("ALL") =~ /^Received:.*?^X-Envelope-From:/smi) { if ($self->get("ALL") =~ /^Received:.*?^X-Envelope-From:/smi) {
dbg("message: X-Envelope-From header found after 1 or more Received lines, cannot trust envelope-from"); dbg("message: X-Envelope-From header found after 1 or more Received lines, cannot trust envelope-from");
$self->{envelopefrom} = undef;
return; return;
} else { } else {
goto ok; dbg("message: using X-Envelope-From header as EnvelopeFrom: '$envf'");
$self->{envelopefrom} = $envf;
return $envf;
} }
} }
# qmail, new-inject(1) # qmail, new-inject(1)
if ($envf = $self->get("Envelope-Sender")) { if (defined($envf = $self->get("Envelope-Sender:addr",undef))) {
# heuristic: this could have been relayed via a list which then used # heuristic: this could have been relayed via a list which then used
# a *new* Envelope-from. check # a *new* Envelope-from. check
if ($self->get("ALL") =~ /^Received:.*?^Envelope-Sender:/smi) { if ($self->get("ALL") =~ /^Received:.*?^Envelope-Sender:/smi) {
dbg("message: Envelope-Sender header found after 1 or more Received lines, cannot trust envelope-from"); dbg("message: Envelope-Sender header found after 1 or more Received lines, cannot trust envelope-from");
} else { } else {
goto ok; dbg("message: using Envelope-Sender header as EnvelopeFrom: '$envf'");
$self->{envelopefrom} = $envf;
return $envf;
} }
} }
# Postfix, sendmail, amavisd-new, ... # Postfix, sendmail, amavisd-new, ...
# RFC 2821 requires it: # RFC 2821 requires it:
# When the delivery SMTP server makes the "final delivery" of a # When the delivery SMTP server makes the "final delivery" of a
# message, it inserts a return-path line at the beginning of the mail # message, it inserts a return-path line at the beginning of the mail
# data. This use of return-path is required; mail systems MUST support # data. This use of return-path is required; mail systems MUST support
# it. The return-path line preserves the information in the <reverse- # it. The return-path line preserves the information in the <reverse-
# path> from the MAIL command. # path> from the MAIL command.
if ($envf = $self->get("Return-Path")) { if (defined($envf = $self->get("Return-Path:addr",undef))) {
# heuristic: this could have been relayed via a list which then used # heuristic: this could have been relayed via a list which then used
# a *new* Envelope-from. check # a *new* Envelope-from. check
if ($self->get("ALL") =~ /^Received:.*?^Return-Path:/smi) { if ($self->get("ALL") =~ /^Received:.*?^Return-Path:/smi) {
dbg("message: Return-Path header found after 1 or more Received lines, can not trust envelope-from"); dbg("message: Return-Path header found after 1 or more Received lines, can not trust envelope-from");
} else { } else {
goto ok; dbg("message: using Return-Path header as EnvelopeFrom: '$envf'");
$self->{envelopefrom} = $envf;
return $envf;
} }
} }
# give up. # give up.
$self->{envelopefrom} = undef;
return; return;
ok:
$envf =~ s/^<*//s; # remove <
$envf =~ s/>*\s*\z//s; # remove >, whitespace, newlines
return $envf;
} }
########################################################################### ###########################################################################
# helper for get(ALL-*). get() caches its results, so don't call this # helper for get(ALL-*). get() caches its results, so don't call this
# directly unless you need a range of headers not covered by the ALL-* # directly unless you need a range of headers not covered by the ALL-*
# psuedo-headers! # psuedo-headers!
# Get all the headers found between an index range of received headers, the # Get all the headers found between an index range of received headers, the
# index doesn't care if we could parse the received headers or not. # index doesn't care if we could parse the received headers or not.
 End of changes. 23 change blocks. 
25 lines changed or deleted 39 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)