On Sun, Nov 10, 2024 at 10:06:48AM -0500, Alex wrote: > I now have a subscription, but they never respond to support requests, even > to numerous emails, including ad...@dnswl.org. > > There also appears to be a reference to an automated script using a > key/token, but no information on how to do that. I can't spend time feeding > these into some webform.
I've been using this attached DNSWLh.pm (from now defunct http://www.chaosreigns.com/dnswl/sa_plugin/) Worked fine for me, but caveat emptor... add to your ".pre" file: loadplugin Mail::SpamAssassin::Plugin::DNSWLh /etc/spamassassin/plugins/DNSWLh.pm and to your ".cf" file: ifplugin Mail::SpamAssassin::Plugin::DNSWLh # get token from https://www.dnswl.org/selfservice/?action=selfservice.spamreport dnswl_token FIXME endif and afterwards "spamassassin --report" automatically reports to DNSWL too -- Opinions above are GNU-copylefted.
# DNSWLh.pm by dar...@chaosreigns.com, released under the GPL. # # Adds DNSWL.org to recipients of spamassassin --report. # # In a SpamAssassin config file, add the lines: # # loadplugin Mail::SpamAssassin::Plugin::DNSWLh # dnswl_token yourtoken # # The token must be generated by creating an account here: # https://www.dnswl.org/selfservice/?action=register # Then you can find your reporting API token on: # https://www.dnswl.org/selfservice/?action=selfservice.spamreport # # # 2010-02-26-23 Initial release. # 2010-02-27-11 Also call report successful on unlisted IPs. # 2010-02-28-20 State when reported email has trust level "Unlisted". # 2010-03-02-10 Report the IP DNSWL thought was interesting. # 2014-11-03-15 Handle IPv6. Handle DNSWL now recording unlisted IPs. # 2019-03-02-14 Handle new DNSWL submission form. # <@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> =head1 NAME Mail::SpamAssassin::Plugin::DNSWL - perform DNSWL reporting of messages =head1 SYNOPSIS loadplugin Mail::SpamAssassin::Plugin::DNSWL =head1 DESCRIPTION DNSWL is a service which lists known legitimate mail servers. This module enables automatic reporting of spam to DNSWL, to improve the accuracy of their database. Note that spam reports sent by this plugin to DNSWL each include the entire spam message. See http://www.dnswl.org/ for more information about DNSWL. =cut package Mail::SpamAssassin::Plugin::DNSWLh; use Mail::SpamAssassin::Plugin; use Mail::SpamAssassin::Logger; use IO::Socket; use strict; use warnings; use bytes; use re 'taint'; use constant HAS_LWP_USERAGENT => eval { require LWP::UserAgent; }; use vars qw(@ISA); @ISA = qw(Mail::SpamAssassin::Plugin); sub new { my $class = shift; my $mailsaobject = shift; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsaobject); bless ($self, $class); # are network tests enabled? if (!$mailsaobject->{local_tests_only} && HAS_LWP_USERAGENT) { $self->{dnswl_available} = 1; dbg("DNSWL: network tests on, attempting DNSWL"); } else { $self->{dnswl_available} = 0; dbg("DNSWL: local tests only, disabling DNSWL"); } $self->set_config($mailsaobject->{conf}); return $self; } sub set_config { my($self, $conf) = @_; my @cmds; =head1 USER OPTIONS =over 4 =cut push (@cmds, { setting => 'dnswl_token', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING, code => sub { my ($self, $key, $value, $line) = @_; if ($value =~ /^(\S+)$/) { $self->{dnswl_token} = $1; } elsif ($value =~ /^$/) { return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; } else { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } }, }); =item dnswl_max_report_size (default: 50) Messages larger than this size (in kilobytes) will be truncated in report messages sent to DNSWL. The default setting is the maximum size that DNSWL will accept at the time of release. =cut push (@cmds, { setting => 'dnswl_max_report_size', default => 50, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); $conf->{parser}->register_commands(\@cmds); } sub plugin_report { my ($self, $options) = @_; return unless $self->{dnswl_available}; #dbg("DNSWL: address/pass: " . $options->{report}->{conf}->{dnswl_address} # .' '. $options->{report}->{conf}->{dnswl_password} ); if (!$options->{report}->{options}->{dont_report_to_dnswl}) { if ($options->{report}->{conf}->{dnswl_token}) { if ($self->dnswl_report($options)) { $options->{report}->{report_available} = 1; info("DNSWL: spam reported to DNSWL"); $options->{report}->{report_return} = 1; } else { info("DNSWL: could not report spam to DNSWL"); } } else { dbg("DNSWL: dnswl_token not defined."); } } } sub dnswl_report { my ($self, $options) = @_; # original text my $original = ${$options->{text}}; # check date my $header = $original; $header =~ s/\r?\n\r?\n.*//s; my $date = Mail::SpamAssassin::Util::receive_date($header); # if ($date && $date < time - 2*86400) { # warn("DNSWL: Message older than 2 days, not reporting\n"); # return 0; # } # message variables my $description = "spam report via " . Mail::SpamAssassin::Version(); my $trusted = $options->{msg}->{metadata}->{relays_trusted_str}; my $untrusted = $options->{msg}->{metadata}->{relays_untrusted_str}; # message data # truncate message if (length($original) > $self->{main}->{conf}->{dnswl_max_report_size} * 1024) { substr($original, ($self->{main}->{conf}->{dnswl_max_report_size} * 1024)) = "\n[truncated by SpamAssassin]\n"; } my $body = <<"EOM"; Content-Description: $description X-Spam-Relays-Trusted: $trusted X-Spam-Relays-Untrusted: $untrusted $original EOM # compose message my $message; $message = $body; # send message my %form = ( 'action', 'save', 'token', $options->{report}->{conf}->{dnswl_token}, 'report',$message, ); my $ua = LWP::UserAgent->new; my $netloc = 'www.dnswl.org:80'; my $realm = 'dnswl.org Abuse Reporting'; # $ua->credentials( $netloc, $realm, $options->{report}->{conf}->{dnswl_token} ); #my $response = $ua->post('http://www.dnswl.org/abuse/report.pl', \%form); #my $response = $ua->post('http://www.dnswl.org/report-testing.pl', \%form); my $response = $ua->post('https://www.dnswl.org/report2/', \%form); # my $response = $ua->post('http://www.dnswl.org/abuse/report.test.pl', \%form); # open OUT, ">/tmp/dnswlbody.".time.".txt"; # print OUT $form{'report'}; # close OUT;;; if ($response->is_success) { # print "Response: ". $response->content ." \n"; #if ( $response->content =~ m#Thank you for your report# ) { # if ( $response->content =~ m#IP ([\d\.]+) matches with DNSWL# ) { # if ( $response->content =~ m#IP ([\d\.:]+) matches with DNSWL# ) { # if ( $response->content =~ m#IP ([\d\.:a-f]+) matches with DNSWL# ) { # open OUT, ">/tmp/dnswlerr.".time.".txt"; # print OUT $response->content; # close OUT; if ( $response->content =~ m#Abuse report stored# ) { if ( $response->content =~ m#IP ([\d\.:a-f]+) recognized as being part of DNSWL Id (\d+)# ) { my $reportedip = $1; my $dnswlid = $2; dbg("DNSWL: Successfully reported IP $reportedip from DNSWL ID $dnswlid."); print "DNSWL: Successfully reported IP $reportedip from DNSWL ID $dnswlid.\n"; return 1; # IP 83.139.110.18 not recognized as being part of any DNSWL Id } elsif ( $response->content =~ m#IP ([\d\.:a-f]+) not recognized as being part of any DNSWL Id# ) { my $reportedip = $1; dbg("DNSWL: Successfully reported IP $reportedip, no DNSWL ID."); print "DNSWL: Successfully reported IP $reportedip, no DNSWL ID.\n"; return 1; } else { dbg("DNSWL: Successfully reported."); print "DNSWL: Successfully reported.\n"; return 1; } } else { dbg("DNSWL: Failed to report, acknowledgement not received."); print "DNSWL: Failed to report, acknowledgement not received.\n"; # open OUT, ">/tmp/dnswlerr.".time.".txt"; # print OUT $response->content; # close OUT; return 0; } } else { dbg("DNSWL: Failed to report: ". $response->status_line); print "Failed to report to DNSWL, HTTP error: ". $response->status_line ."\n"; return 0; } dbg("DNSWL: Error: This isn't possible."); return 0; } 1; =back =cut