summaryrefslogtreecommitdiff
path: root/tools/blacklist-update
blob: 4621ef2804c19d1ccaf1f79859402fbc6f9d4085 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#! /usr/bin/perl -w

#########################
# BEWARE:
#
# The most dangerous criminals routinely forge email from-addresses.
# Therefore blacklisting addresses only works for senders
# who have bad manners but are otherwise quasi-legitimate.
#
# Overuse of blacklisting will punish innocent parties
# whose domain-names look nice to forgers.

## hint:  mail-scan +from * | iconv -c \...
##  | sed 's/.*@//;s/>$//' | sort | uniq -c | sort -nr > some-junk.from-count

use strict;
use Symbol;

main: {
  my $baremode = 0;
  my @argv = @ARGV;
  @ARGV = ();
  while (@argv){
    my $arg = shift @argv;
    if ($arg eq '-bare') {
      $baremode++;
    } else {
      die "Unrecognized verbiage '$arg'\n";
    }
  }
  my $file = '/etc/mail/spamassassin/local.cf';
  my $inch = Symbol::gensym;
  my $mainpart = '';
  my %blacklist = ();
  my $verb = 'blacklist_from';
  open($inch, '<', $file)
    || die "Could not open input file '$file'\n";
  while (my $line = <$inch>) {
    chomp $line;
    my @stuff = split(' ', $line, 2);
    if (0+@stuff == 2 && $stuff[0] eq $verb) {
        my $key = lc($stuff[1]);
        $blacklist{$stuff[1]} ++;
    } else {
      $mainpart .= $line . "\n";
    }
  }
  close $inch;
  my $unchanged = 0;
  my $new = 0;
  liner: while (my $line=<>){
    chomp $line;
    my $domain = '';
    if ($baremode) {
      my @stuff = split(' ', $line);
      $domain = $stuff[$#stuff];
    } else {
      if ($line =~ m'<.*@(.*)>$') {
        $domain = $1;
      } else {
        print STDERR "no '<user\@domain>'; ignoring line ...\n";
        print STDERR "... '$line'\n";
        next liner;
      }
    }
    if ($domain ne '') {
      my $key = "*@" . lc($domain);
      if (exists $blacklist{$key}) {
        $unchanged++;
      } else {
        $new++;
      }
      $blacklist{$key} ++;
    }

  }

  my $ouch = Symbol::gensym;
  open($ouch, '>', $file)
    || die "Could not open output file '$file'\n";
  print $ouch $mainpart;
  for my $baddy (sort keys %blacklist){
    print $ouch "$verb $baddy\n";
  }
  close $ouch;
  my $updated = $unchanged + $new;
  my $total = 0+(keys %blacklist);
  print "$new new + $unchanged unchanged = $updated updated;  $total new total\n";
}