The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Mail::SPF::Query - query Sender Permitted From for an IP,email,helo

SYNOPSIS

  my $query = new Mail::SPF::Query (ip => "127.0.0.1", sender=>'foo@example.com', helo=>"somehost.example.com");
  my ($result, $smtp_comment, $header_comment) = $query->result();
  my ($guess,  $smtp_comment, $header_comment) = $query->best_guess();

  if    ($result eq "pass")     { ... } # domain is not forged
  elsif ($result eq "fail")     { ... } # domain is forged
  elsif ($result eq "softfail") { ... } # domain may be forged
  else                          {       # domain has not implemented SPF
    if    ($guess eq "pass")    { ... } # result based on $guess_mechs
    elsif ($guess eq "fail")    { ... } # result based on $guess_mechs
    else                        { ... } #
  }

  The default $guess_mechs is "a/24 mx/24 ptr exists:%{d}.wl.trusted-forwarder.org".

ABSTRACT

The SPF protocol relies on sender domains to publish a DNS whitelist of their designated outbound mailers. Given an envelope sender, Mail::SPF::Query determines the legitimacy of an SMTP client IP.

METHODS

Mail::SPF::Query->new()

  my $query = eval { new Mail::SPF::Query (ip    =>"127.0.0.1",
                                           sender=>'foo@example.com',
                                           helo  =>"host.example.com") };

  optional parameters:
     guess_mechs => "a/24 mx/24 ptr exists:%{d}.wl.trusted-forwarder.org",
     debug => 1, debuglog => sub { print STDERR "@_\n" },

  if ($@) { warn "bad input to Mail::SPF::Query: $@" }

Set debug=>1 to watch the queries happen.

$query->result()

  my ($result, $comment) = $query->result();

$result will be one of pass, fail, softfail, unknown, or error.

pass means the client IP is a designated mailer for the sender. The mail should be accepted subject to local policy regarding the sender.

fail means the client IP is not a designated mailer, and the sender wants you to reject the transaction for fear of forgery.

softfail means the transaction should be accepted but subject to further scrutiny because the domain is still transitioning toward SPF adoption.

unknown means the domain either does not publish SPF data or has a configuration error in the published data.

error means the DNS lookup encountered a temporary error during processing.

Results are cached internally for a default of 120 seconds. You can call ->result() repeatedly; subsequent lookups won't hit your DNS.

$query->best_guess()

  my ($result, $smtp_comment, $header_comment) = $query->best_guess();

When a domain does not publish SPF records, this library can produce an educated guess anyway.

It pretends the domain defined A, MX, and PTR mechanisms, plus a few others. The default set of directives is

  "a/24 mx/24 ptr exists:%{d}.wl.trusted-forwarder.org"

That default set will return either "pass" or "unknown".

$query->debuglog()

  Subclasses may override this with their own debug logger.
  I recommend Log::Dispatch.

  Alternatively, pass the C<new()> constructor a
  C<debuglog => sub { ... }> callback, and we'll pass
  debugging lines to that.

EXPORT

None by default.

AUTHOR

Meng Weng Wong, <mengwong+spf@pobox.com>

SEE ALSO

http://spf.pobox.com/