|  | # <@LICENSE> | 
|  | # Licensed to the Apache Software Foundation (ASF) under one or more | 
|  | # contributor license agreements.  See the NOTICE file distributed with | 
|  | # this work for additional information regarding copyright ownership. | 
|  | # The ASF licenses this file to you 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> | 
|  |  | 
|  | # Eval Tests to detect genuine mailing lists. | 
|  |  | 
|  | use strict;  # make Test::Perl::Critic happy | 
|  | package Mail::SpamAssassin::MailingList; 1; | 
|  |  | 
|  | package Mail::SpamAssassin::PerMsgStatus; | 
|  |  | 
|  | use strict; | 
|  | use warnings; | 
|  | # use bytes; | 
|  | use re 'taint'; | 
|  |  | 
|  | sub detect_mailing_list { | 
|  | my ($self) = @_; | 
|  | return 1 if $self->detect_ml_ezmlm(); | 
|  | return 1 if $self->detect_ml_mailman(); | 
|  | return 1 if $self->detect_ml_sympa(); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | # EZMLM | 
|  | # Mailing-List: .*run by ezmlm | 
|  | # Precedence: bulk | 
|  | # List-Post: <mailto: | 
|  | # List-Help: <mailto: | 
|  | # List-Unsubscribe: <mailto:[a-zA-Z\.-]+-unsubscribe@ | 
|  | # List-Subscribe: <mailto:[a-zA-Z\.-]+-subscribe@ | 
|  | sub detect_ml_ezmlm { | 
|  | my ($self) = @_; | 
|  | return 0 unless $self->get('mailing-list') =~ /ezmlm$/; | 
|  | return 0 unless $self->get('precedence') eq "bulk\n"; | 
|  | return 0 unless $self->get('list-post') =~ /^<mailto:/i; | 
|  | return 0 unless $self->get('list-help') =~ /^<mailto:/i; | 
|  | return 0 unless $self->get('list-unsubscribe') =~ /<mailto:[a-zA-Z\.-]+-unsubscribe\@/i; | 
|  | return 0 unless $self->get('list-subscribe') =~ /<mailto:[a-zA-Z\.-]+-subscribe\@/i; | 
|  | return 1; # assume ezmlm then. | 
|  | } | 
|  |  | 
|  | # MailMan (the gnu mailing list manager) | 
|  | #  Precedence: bulk [or list for v2] | 
|  | #  List-Help: <mailto: | 
|  | #  List-Post: <mailto: | 
|  | #  List-Subscribe: .*<mailto:.*=subscribe> | 
|  | #  List-Id: | 
|  | #  List-Unsubscribe: .*<mailto:.*=unsubscribe> | 
|  | #  List-Archive: | 
|  | #  X-Mailman-Version: \d | 
|  | # | 
|  | # However, for mailing list membership reminders, most of | 
|  | # those headers are gone, so we identify on the following: | 
|  | # | 
|  | #  Subject: ...... mailing list memberships reminder  (v1) | 
|  | #  or X-List-Administrivia: yes  (only in version 2) | 
|  | #  X-Mailman-Version: \d | 
|  | #  Precedence: bulk [or list for v2] | 
|  | #  X-No-Archive: yes | 
|  | #  Errors-To: | 
|  | #  X-BeenThere: | 
|  | sub detect_ml_mailman { | 
|  | my ($self) = @_; | 
|  | return 0 unless $self->get('x-mailman-version') =~ /^\d/; | 
|  | return 0 unless $self->get('precedence') =~ /^(?:bulk|list)$/; | 
|  |  | 
|  | if ($self->get('x-list-administrivia') =~ /yes/ || | 
|  | $self->get('subject') =~ /mailing list memberships reminder$/) | 
|  | { | 
|  | return 0 unless defined $self->get('errors-to',undef); | 
|  | return 0 unless defined $self->get('x-beenthere',undef); | 
|  | return 0 unless $self->get('x-no-archive') =~ /yes/; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | return 0 unless defined $self->get('list-id',undef); | 
|  | return 0 unless $self->get('list-help') =~ /^<mailto:/i; | 
|  | return 0 unless $self->get('list-post') =~ /^<mailto:/i; | 
|  | return 0 unless $self->get('list-subscribe') =~ /<mailto:.*=subscribe>/i; | 
|  | return 0 unless $self->get('list-unsubscribe') =~ /<mailto:.*=unsubscribe>/i; | 
|  | return 1; # assume this is a valid mailman list | 
|  | } | 
|  |  | 
|  | # Sympa | 
|  | # Return-Path: somelist-owner@somedomain.com [...] | 
|  | # Precedence: list [...] | 
|  | # List-Id: <somelist@somedomain.com> | 
|  | # List-Help: <mailto:sympa@somedomain.com?subject=help> | 
|  | # List-Subscribe: <mailto:somedomain.com?subject=subscribe%20somelist> | 
|  | # List-Unsubscribe: <mailto:sympa@somedomain.com?subject=unsubscribe%somelist> | 
|  | # List-Post: <mailto:somelist@somedomain.com> | 
|  | # List-Owner: <mailto:somelist-request@somedomain.com> | 
|  | # X-Mailer: Sympa 6.2.22 | 
|  | # X-Sympa-To: somelist@somedomain.com | 
|  | # [and optionally] List-Archive: <http://www.somedomain.com/wws/arc/somelist> | 
|  |  | 
|  | sub detect_ml_sympa { | 
|  | my ($self) = @_; | 
|  | return 1 if $self->get('X-Mailer') =~ /^Sympa \d\.\d\.\d/; | 
|  | return 1 if defined ($self->get('X-Sympa-To',undef)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | # Lyris | 
|  | # Not implemented - need headers | 
|  | sub detect_ml_lyris { | 
|  | } | 
|  |  | 
|  | # ListBuilder | 
|  | # Sep 17 2002 jm: turned off due to bad S/O ratio | 
|  |  | 
|  | # sub detect_ml_listbuilder { | 
|  | #   my ($self, $full) = @_; | 
|  | # | 
|  | #   my $reply = $self->get('Reply-To:addr'); | 
|  | #   if ($reply !~ /\@lb.bcentral.com/) { return 0; } | 
|  | # | 
|  | #   # Received: from unknown (HELO lbrout14.listbuilder.com) (204.71.191.9) | 
|  | #   my $rcvd = $self->get('received'); | 
|  | #   return 0 unless ($rcvd =~ /\blbrout\d+\.listbuilder\.com\b/i); | 
|  | #   return 0 unless ($rcvd =~ /\b204\.71\.191\.\d+\b/); | 
|  | # | 
|  | #   # _______________________________________________________________________ | 
|  | #   # Powered by List Builder | 
|  | #   # To unsubscribe follow the link: | 
|  | #   # http://lb.bcentral.com/ex/sp?c=19511&s=76CA511711046877&m=14 | 
|  | #   $full = join ("\n", @{$full}); | 
|  | # | 
|  | #   if ($full !~ /__________________{40,}\s+Powered by List Builder\s/) { return 0; } | 
|  | #   if ($full !~ | 
|  | #          m,\shttp://lb\.bcentral\.com/ex/sp\?c=[0-9A-Z]*&s=[0-9A-Z]*&m=[0-9A-Z]*\s,) | 
|  | #          { return 0; } | 
|  | # | 
|  | #   return 1; | 
|  | # } | 
|  |  | 
|  | 1; |