sub check_hashbl_emails()

in lib/Mail/SpamAssassin/Plugin/HashBL.pm [529:637]


sub check_hashbl_emails {
  my ($self, $pms, $list, $opts, $from, $subtest, $acl) = @_;

  return 0 if !$self->{hashbl_available};
  return 0 if !$pms->is_dns_available();

  my $conf = $pms->{conf};
  my $rulename = $pms->get_current_eval_rule_name();

  if (!defined $list) {
    warn "HashBL: $rulename blocklist argument missing\n";
    return 0;
  }

  if (defined $acl && $acl ne 'all' && !exists $self->{hashbl_acl}{$acl}) {
    warn "HashBL: $rulename acl '$acl' not defined\n";
    return 0;
  }

  if ($subtest) {
    my ($rec, $err) = compile_regexp($subtest, 0);
    if (!$rec) {
      warn "HashBL: $rulename invalid subtest regex: $@\n";
      return 0;
    }
    $subtest = $rec;
  }

  # Parse opts, defaults
  $opts = _parse_opts($opts || 'sha1/notag/noquote/max=10/shuffle');
  $from = 'ALLFROM/Reply-To/body' if !$from;

  # Find all emails
  my $emails = $self->_get_emails($pms, $opts, $from, $acl);
  if (!@$emails) {
    if (defined $acl) {
      dbg("$rulename: no emails found ($from) on acl $acl");
    } else {
      dbg("$rulename: no emails found ($from)");
    }
    return 0;
  } else {
    dbg("$rulename: raw emails found: ".join(', ', @$emails));
  }

  # Filter list
  my @filtered_emails; # keep order
  my %seen;
  foreach my $email (@$emails) {
    next if $seen{$email}++;
    if (exists $pms->{hashbl_welcomelist}{$email} ||
        $email =~ $conf->{hashbl_email_welcomelist})
    {
      dbg("query skipped, address welcomelisted: $email");
      next;
    }
    my ($username, $domain) = ($email =~ /(.*)\@(.*)/);
    if(not defined $opts->{alldomains}) {
      if (exists $conf->{uridnsbl_skip_domains}->{lc $domain}) {
        dbg("query skipped, uridnsbl_skip_domains: $email");
        next;
      }
      my $dom = $pms->{main}->{registryboundaries}->trim_domain($domain);
      if (exists $conf->{uridnsbl_skip_domains}->{lc $dom}) {
        dbg("query skipped, uridnsbl_skip_domains: $email");
        next;
      }
    }
    $username =~ tr/.//d if $opts->{nodot};
    $username =~ s/\+.*// if $opts->{notag};
    # Final query assembly
    my $qmail;
    if ($opts->{host} || $opts->{domain}) {
      if ($opts->{domain}) {
        $domain = $pms->{main}->{registryboundaries}->trim_domain($domain);
      }
      $qmail = $domain;
    } elsif ($opts->{user}) {
      $qmail = $username;
    } else {
      $qmail = $username.'@'.$domain;
    }
    $qmail = lc $qmail  if !$opts->{case};
    push @filtered_emails, $qmail;
  }

  return 0 unless @filtered_emails;

  # Unique
  @filtered_emails = do { my %seen; grep { !$seen{$_}++ } @filtered_emails; };

  # Randomize order
  if ($opts->{shuffle}) {
    Mail::SpamAssassin::Util::fisher_yates_shuffle(\@filtered_emails);
  }

  # Truncate list
  my $max = $opts->{max} || 10;
  $#filtered_emails = $max-1 if scalar @filtered_emails > $max;

  my $queries;
  foreach my $email (@filtered_emails) {
    my $ret = $self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest);
    $queries++ if defined $ret;
  }

  return 0 if !$queries; # no query started
  return; # return undef for async status
}