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::DMARC::opendmarc - Perl extension wrapping OpenDMARC's libopendmarc library

SYNOPSIS

  use Mail::DMARC::opendmarc;

  my $dmarc = Mail::DMARC::opendmarc->new();

  # Get spf and dkim auth results from Authentication-Results (RFC5451) header
  # Store them into the dmarc object together with from domain and let object
  # query DNS too
  $dmarc->query_and_store_auth_results(
        'mlu.contactlab.it',  # From: domain
        'example.com',  # envelope-from domain
        Mail::DMARC::opendmarc::DMARC_POLICY_SPF_OUTCOME_NONE, # SPF check result
        'neutral', # human-readable SPF check result
        'mlu.contactlab.it', # DKIM domain
        Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_OUTCOME_PASS, # DKIM check result
        'ok' # human-readable DKIM check result
		);
		
  my $result = $dmarc->verify();
  
  # result is a hashref with the following attributes:
  #		'spf_alignment' 
  #		'dkim_alignment'
  #		'policy'
  #		'human_policy' 
  #		'utilized_domain'

  print "DMARC check result: " . $result->{human_policy} . "\n";
  print "DMARC domain used for policy evaluation: " . $result->{utilized_domain} . "\n";
  (warning: utilized_domain is only reliable if you have libopendmarc 1.1.3+)
  
  # Diagnostic output of internal libopendmarc structure via this handy function:
  print $dmarc->dump_policy() if ($debug);
  # Use it often. Side-effects on the library's internal structure might
  # interfere if you're trying to optimize call sequences.
  
  if ($result->{policy} == Mail::DMARC::opendmarc::DMARC_POLICY_PASS)
		...

DESCRIPTION

A very thin layer wrapping Trusted Domain Project's libopendmarc. Please refer to http://www.trusteddomain.org/opendmarc.html for more information on opendmarc

Look into the test suite for more usage examples.

METHODS

Basic housekeeping

new
# $dmarc will hold a reference to a Mail::DMARC::opendmarc instance
my $dmarc = Mail::DMARC::opendmarc->new();

Initializes a new object to interact with libopendmarc

DESTROY

Performs libopendmarc cleanup when objects goes out of scope. Automatically invoked by Perl as needed.

Utility methods

policy_status_to_str

Wraps: opendmarc_policy_status_to_str. Returns a human-readable string for libopendmarc status codes (OPENDMARC_STATUS_T)

# Will print "Success. No errors"
print $dmarc->policy_status_to_str(0);
dump_policy

Wraps opendmarc_policy_to_buf. Dumps the values of libopendmarc's DMARC_POLICY_T opaque struct, the per-message library context. Useful for debugging and learning DMARC.

DMARC policy retrieval / parsing

query

Performs a DNS lookup for $domain's DMARC policy. Initializes the object's internal structure for later handling. Returns a status code (0 is success - see policy_status_to_str)

my $rcode = $dmarc->query('example.com');
store

Wraps: opendmarc_policy_store_dmarc Stores a DMARC policy and initializes the object's internal structure for later handling. Doesn't perform DNS queries to retrieve the DMARC policy - you pass the domain, policy record and organization domain to store (and parse). Returns a status code (0 is success - see policy_status_to_str)

my $rcode = $dmarc->store($dmarc_policy_record, $domain, $organizational_domain);
my $rcode = $dmarc->store('v=DMARC1;p=none','mail.example.com','example.com');
parse

Wraps: opendmarc_policy_parse_dmarc Parses a DMARC policy and initializes the object's internal structure for later handling. Doesn't perform DNS queries to retrieve the DMARC policy - you pass the policy to parse. You should use store() instead of parse(). Returns a status code (0 is success - see policy_status_to_str)

my $rcode = $dmarc->parse($domain, $dmarc_policy_record);
my $rcode = $dmarc->parse('example.com', 'v=DMARC1;p=none");

Information storage methods

store_from_domain

Wraps: opendmarc_policy_store_from_domain Tell the policy evaluator the From domain of the message to be evaluated

my $rcode = $dmarc->store_from_domain($domain);
my $rcode = $dmarc->store_from_domain('example.com');
store_dkim

Wraps: opendmarc_policy_store_dkim Tell the policy evaluator the domain DKIM-signing the message and the result of the DKIM signature verification. my $rcode = $dmarc->store_dkim($domain, $result, $human_result); my $rcode = $dmarc->store_dkim('example.com', Mail::DMARC::opendmarc::DMARC_POLIY_DKIM_OUTCOME_PASS, 'DKIM pass');

The following symbols are available for result mapping: Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_OUTCOME_FAIL Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_OUTCOME_PASS Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_OUTCOME_TMPFAIL Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_OUTCOME_NONE

store_spf

Wraps: opendmarc_policy_store_spf Tell the policy evaluator the domain DKIM-signing the message and the result of the DKIM signature verification.

my $rcode = $dmarc->store_spf($domain, $result, $origin, $human_result);
my $rcode = $dmarc->store_spf('example.com', 
	Mail::DMARC::opendmarc::DMARC_POLIY_SPF_OUTCOME_PASS, 
	Mail::DMARC::opendmarc::DMARC_POLIY_SPF_ORIGIN_MAILFROM,
	'SPF passed');

The following symbols are available for result mapping: Mail::DMARC::opendmarc::DMARC_POLICY_SPF_OUTCOME_FAIL Mail::DMARC::opendmarc::DMARC_POLICY_SPF_OUTCOME_PASS Mail::DMARC::opendmarc::DMARC_POLICY_SPF_OUTCOME_TMPFAIL Mail::DMARC::opendmarc::DMARC_POLICY_SPF_OUTCOME_NONE The following symbols are available for SPF origin mapping: Mail::DMARC::opendmarc::DMARC_POLICY_SPF_ORIGIN_MAILFROM Mail::DMARC::opendmarc::DMARC_POLICY_SPF_ORIGIN_HELO

Do-it-all-at-once convenience methods

query_and_store_auth_results

Perform DMARC policy retrieval *and* store authentication results for the current message at the same time. Implies SPF authentication is performed against "mail from" and not "helo". Returns a status code.

my $rcode = $dmarc->query_and_store_auth_results(
	$from_domain,
	$spf_domain,
	$spf_result,
	$spf_human_result,
	$dkim_domain,
	$dkim_result,
	$dkim_human_result);
store_auth_results

Like query_and_store_results but does not perform a DMARC policy retrieval - use "store" to initialize the DMARC policy instead. Implies SPF authentication is performed against "mail from" and not "helo". Returns a status code.

my $rcode = $dmarc->store_auth_results(
	$from_domain,
	$spf_domain,
	$spf_result,
	$spf_human_result,
	$dkim_domain,
	$dkim_result,
	$dkim_human_result);

DMARC evaluation result methods

verify

Process the incoming message context information against the DMARC policy. Returns a hash with the following keys:

'utilized_domain': the domain the policy comes from; either the from_domain or the organizational domain
'spf_alignment': result of the DMARC SPF alignment check. Possible values:
	Mail::DMARC::opendmarc::DMARC_POLICY_SPF_ALIGNMENT_PASS 
	Mail::DMARC::opendmarc::DMARC_POLICY_SPF_ALIGNMENT_FAIL
'dkim_alignment': result of the DMARC DKIM alignment check: Possible values:
	Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_ALIGNMENT_PASS 
	Mail::DMARC::opendmarc::DMARC_POLICY_DKIM_ALIGNMENT_FAIL
'policy': the recommended policy to apply to the current message
	Mail::DMARC::opendmarc::DMARC_POLICY_ABSENT 
	Mail::DMARC::opendmarc::DMARC_POLICY_NONE 
	Mail::DMARC::opendmarc::DMARC_POLICY_PASS 
	Mail::DMARC::opendmarc::DMARC_POLICY_QUARANTINE 
	Mail::DMARC::opendmarc::DMARC_POLICY_REJECT
'human_policy': human-readable description of the policy

$dmarc->query_and_store_auth_results(...);
my $result = $dmarc->verify();
print "What should we do with this message: " . $result->{human_policy} . "\n";
if ($result->{policy} == Mail::DMARC::opendmarc::DMARC_POLICY_REJECT) {
	# processing for messages who failed the DMARC check...
get_policy_to_enforce

Get the result of the policy evaluation. Returns one of: Mail::DMARC::opendmarc::DMARC_POLICY_ABSENT Mail::DMARC::opendmarc::DMARC_POLICY_NONE Mail::DMARC::opendmarc::DMARC_POLICY_PASS Mail::DMARC::opendmarc::DMARC_POLICY_QUARANTINE Mail::DMARC::opendmarc::DMARC_POLICY_REJECT

get_policy

Returns a hash containing individual elements of the policy after parsing.

'policy': same as get_policy_to_enforce (for a given message)
'p'
'sp'
'pct'
'adkim'
'aspf'
'spf_aligment'
'dkim_aligment'
'fo'
'rf'
'ruf' NOT IMPLENTED YET
'rua' NOT IMPLEMENTED YET

Please refer to DMARC specs for an explanation of the hash elements and their meaning.

SEE ALSO

About DMARC: http://www.opendmarc.org

Abount opendmarc and libopendmarc: http://www.trusteddomain.org/opendmarc.html

AUTHOR

Davide Migliavacca, <shari@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2012, 2013 by Davide Migliavacca and ContactLab

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.14.2 or, at your option, any later version of Perl 5 you may have available.

This license is not covering the required libopendmarc package from http://www.trusteddomain.org/opendmarc.html. Please refer to appropriate license details for the package.

THis license is not covering the bundled "effective TLD list file" from http://mxr.mozilla.org, which is licensed under the Mozilla Public License 2.0

Please try to have the appropriate amount of fun.

12 POD Errors

The following errors were encountered while parsing the POD:

Around line 152:

'=item' outside of any '=over'

Around line 213:

You forgot a '=back' before '=head3'

Around line 216:

'=item' outside of any '=over'

Around line 247:

You forgot a '=back' before '=head3'

Around line 249:

'=item' outside of any '=over'

Around line 328:

You forgot a '=back' before '=head3'

Around line 331:

'=item' outside of any '=over'

Around line 426:

You forgot a '=back' before '=head3'

Around line 428:

'=item' outside of any '=over'

Around line 551:

You forgot a '=back' before '=head3'

Around line 553:

'=item' outside of any '=over'

Around line 718:

You forgot a '=back' before '=head1'