Index: lib/Mail/SpamAssassin/Message/Metadata/Received.pm =================================================================== --- lib/Mail/SpamAssassin/Message/Metadata/Received.pm (revision 418439) +++ lib/Mail/SpamAssassin/Message/Metadata/Received.pm (working copy) @@ -81,9 +81,11 @@ # now figure out what relays are trusted... my $trusted = $main->{conf}->{trusted_networks}; my $internal = $main->{conf}->{internal_networks}; + my $msa = $main->{conf}->{msa_networks}; my $first_by; my $in_trusted = 1; my $in_internal = 1; + my $found_msa = 0; if ($trusted->get_num_nets() > 0 && $internal->get_num_nets() > 0) { # good; we can use both reliably. @@ -127,14 +129,14 @@ } # trusted_networks matches? - if ($in_trusted && $did_user_specify_trust && !$relay->{auth} && !$trusted->contains_ip ($relay->{ip})) + if ($in_trusted && $did_user_specify_trust && !$relay->{auth} && !$found_msa && !$trusted->contains_ip ($relay->{ip})) { $in_trusted = 0; # we're in deep water now } # internal_networks matches? if ($did_user_specify_internal) { - if (!$relay->{auth} && !$internal->contains_ip ($relay->{ip})) { + if (!$relay->{auth} && !$found_msa && !$internal->contains_ip ($relay->{ip})) { $in_internal = 0; } } else { @@ -149,6 +151,13 @@ $in_trusted = 1; } + # msa_networks matches? + if ($in_trusted && $did_user_specify_trust && $msa->contains_ip($relay->{ip})) + { + $found_msa = 1; + $relay->{msa} = 1; # TODO: add this to make_relay_as_string and fix tests and rules + } + # OK, infer the trusted/untrusted handover, if we don't have real info. # Here's the algorithm used (taken from Dan's mail): # @@ -258,7 +267,8 @@ dbg("received-header: relay ".$relay->{ip}. " trusted? ".($in_trusted ? "yes" : "no"). - " internal? ".($in_internal ? "yes" : "no")); + " internal? ".($in_internal ? "yes" : "no"). + " msa? ".($relay->{msa} ? "yes" : "no")); if ($in_internal) { $relay->{internal} = 1; Index: lib/Mail/SpamAssassin/Conf.pm =================================================================== --- lib/Mail/SpamAssassin/Conf.pm (revision 418439) +++ lib/Mail/SpamAssassin/Conf.pm (working copy) @@ -991,6 +991,54 @@ } }); +=item msa_networks ip.add.re.ss[/mask] ... (default: none) + +What networks or hosts are acting as MSAs in your setup. B means +that the relay hosts on these networks accept mail from your own users +and authenticates them appropriately. These relays will never accept +mail from hosts that aren't authenticated in some way. Examples of +authentication include, IP lists, SMTP AUTH, POP-before-SMTP, etc. + +All relays found in the message headers after the MSA relay will take +on the same trusted and internal classifcations as the MSA relay itself. + +For example, if the MSA relay is trusted and internal so will all of the +relays that precede it. + +Warning: Never include an MSA that also acts as an MX or otherwise +accepts mail from non-authenticated users in msa_networks. Doing so +will result in unknown external relays being trusted (and internal if +internal_networks are being used). + +=cut + + push (@cmds, { + setting => 'msa_networks', + code => sub { + my ($self, $key, $value, $line) = @_; + unless (defined $value && $value !~ /^$/) { + return $MISSING_REQUIRED_VALUE; + } + foreach my $net (split (/\s+/, $value)) { + $self->{msa_networks}->add_cidr ($net); + } + } + }); + +=item clear_msa_networks + +Empty the list of msa networks. + +=cut + + push (@cmds, { + setting => 'clear_msa_networks', + code => sub { + my ($self, $key, $value, $line) = @_; + $self->{msa_networks} = Mail::SpamAssassin::NetSet->new(); + } + }); + =item always_trust_envelope_sender ( 0 | 1 ) (default: 0) Trust the envelope sender even if the message has been passed through one or @@ -2816,6 +2864,7 @@ $self->{trusted_networks} = Mail::SpamAssassin::NetSet->new(); $self->{internal_networks} = Mail::SpamAssassin::NetSet->new(); + $self->{msa_networks} = Mail::SpamAssassin::NetSet->new(); # Make sure we add in X-Spam-Checker-Version $self->{headers_spam}->{"Checker-Version"} =