my $looks_like_ipv4 = qr/\d+\.\d+\.\d+\.\d+/;
my $looks_like_email = qr/\S+\@\S+/;
use strict;
use vars qw ($ipv4 $ip $sender $helo $fallback $debug $v $test $q $guess_mechs); $debug = defined $debug || defined $v;
use Mail::SPF::Query;
my $ExitCode = 255;
my @Fallbacks = grep { length } (defined $fallback ? split /,/, $fallback : defined $test ? "spf-test.mailzone.com" : "spf.mailzone.com");
my %Query = process_arguments();
if (exists $Query{ipv4}) {
my $spfquery = new Mail::SPF::Query (%Query, debug=>$debug, fallbacks => \@Fallbacks);
my ($passfail, $smtp_comment, $header_comment, $spf_record) = $spfquery->result;
print STDERR "result=$passfail" . ($smtp_comment ? ": $smtp_comment" : "") . "\n" unless defined $q;
print "Received-SPF: $passfail ($header_comment)\n" unless defined $q;
my ($guess, $smtp_guess, $header_guess) = $spfquery->best_guess();
print STDERR "guess=$guess" . ($smtp_guess ? ": $smtp_guess" : "") . "\n" unless defined $q;
print "X-SPF-Guess: $guess ($header_guess)\n" if (not defined $q and $header_guess);
exit0123($passfail);
}
my ($passfail, $text);
while (<>) {
next if /^\s*\
my %Query = process_line($_);
my @output = ($Query{ipv4}, $Query{sender});
my $Res;
print STDERR "process_line got me @{[%Query]}\n" if $debug;
my $spfquery = eval { new Mail::SPF::Query (%Query, debug=>defined $debug, fallbacks => \@Fallbacks, res=>$Res); };
if ($@) { push @output, "error", $@; } else {
$Res ||= $spfquery->resolver;
($passfail, $text) = $spfquery->result;
push @output, $passfail, $text;
}
print join ("\t", @output), "\n";
}
exit0123($passfail);
sub process_arguments {
my %query;
$query{guess_mechs} = $guess_mechs if defined $guess_mechs;
$query{helo} = $helo if defined $helo;
$query{ipv4} = $ipv4 if defined $ipv4;
$query{sender} = $sender if defined $sender;
$query{ip} = $ip if defined $ip;
$query{ipv4} = delete $query{ip} if $query{ip} and $query{ip} =~ $looks_like_ipv4;
use Data::Dumper;
{ no warnings 'uninitialized';
print STDERR "args: fallback=$query{fallback}, ip=$query{ip}, ipv4=$query{ipv4}, sender=$query{sender}\n" if $debug;
}
return %query;
}
sub process_line {
my %query;
local $_ = shift;
s/\s+\
for (split) {
$query{ipv4} = $_ if /$looks_like_ipv4/;
$query{sender} = $_ if /$looks_like_email/;
}
return %query;
}
sub exit0123 {
my $passfail = shift;
my $ExitCode = 255;
$ExitCode=0 if $passfail eq "pass";
$ExitCode=0 if $passfail eq "softfail";
$ExitCode=1 if $passfail eq "fail";
$ExitCode=2 if $passfail eq "error";
$ExitCode=3 if $passfail eq "unknown";
exit $ExitCode;
}