Add SMTP Authentication to OpenDMARC-Reports

Submitted by Tom Thorp on Friday, September 16, 2022 - 23:37
Modified on Saturday, September 17, 2022 - 00:45
OpenDMARC Report
I had successfully set up SPF, DKIM and DMARC into my Postfix/Dovecot email server. However there was one feature I kept getting daily reminders of, that would be a nice feature to implement. That is, the sending out of aggregate reports to email server admins, whom their users sent emails to my email server. OpenDMARC was simple to install and configure, however with the configuration of my email server, it does not work completely out of the box. 
The main issue with OpenDMARC-Reports was how it sent the emails. Apart from checking for the hosts fully-qualified domain name (FQDN), OpenDMARC-Reports does no authentication to establish and send the report. Here is the source code :
# From line 396 on opendmarc-reports

$smtp = Net::SMTP->new($smtp_server,
                       'Port' => $smtp_port,
                       'Hello' => hostfqdn());
if (!defined($smtp))
  print STDERR "$progname: open SMTP server $smtp_server:$smtp_port failed\n";
Obviously if you have properly set up your SMTP server, you would not send out any emails without having authentication built in. As OpenDMARC-Reports has no way of using an intermediary in order to authenticate back to a secure SMTP server, some changes to the source code are in order. 

The Solution

The changes can be broken down into 3 parts :
  • Changes to OpenDMARC-Reports
  • Change to the shell script
  • SMTP Authentication change to Postfix

1) Changes to OpenDMARC-Reports

There are only a few lines in the source code to affect the change. Here they are in order :
# From line 17, add the following use statements :

use Authen::SASL;
use Net::SMTP::SSL;

# Note: these libraries may not be installed by default. If not, from the command line add the following:
root> perl -MCPAN -e shell 
cpan[1]> install Authen::SASL 
cpan[1]> install Net::SMTP::SSL 
cpan[1]> quit
Declare two variables for SMTP Username and SMTP Password .
# Line 147 

my $smtp_user;
my $smtp_pw;
Add SMTP User and SMTP Password in the help screen as the list of options.
# Line 176 

print STDERR "\t--smtp-user smtp server user\n"; 
print STDERR "\t--smtp-password smtp server password\n";
Parse SMTP User and SMTP Password as command line options :
# Line 206 

'smtp-user=s' => \$smtp_user, 
'smtp-password=s' => \$smtp_pw,
Finally, replace the SMTP code block (including the error check) with the following : 
if (!(defined($smtp_user) && defined($smtp_pw))) 
   $smtp = Net::SMTP->new($smtp_server, 'Port' => $smtp_port, 'Hello' => hostfqdn()); 
   $smtp = Net::SMTP->new($smtp_server, 'Port' => $smtp_port, 'Hello' => hostfqdn(), 'SSL' => 1);
if (!defined($smtp)) 
   print STDERR "$progname: open SMTP server $smtp_server:$smtp_port failed\n";
if (defined($smtp_user) && defined($smtp_pw)) 
   $smtp->auth($smtp_user, $smtp_pw); 
Save OpenDMARC-Reports under a different name - say 'opendmarc-reports-sasl'.


2) Change the script : 

With the parameters now set up under your custom OpenDMARC-Reports file, make a change to, using this as a guide : 
# Imports data from OpenDMARC's opendmarc.dat file into a local MySQL DB
# and sends DMARC failure reports to domain owners.
# Based on a script from Hamzah Khan (
set -e
# Database and History File Info

mv ${HISTDIR}/${HISTFILE}.dat ${HISTDIR}/${HISTFILE}_import.dat -f
cat /dev/null > ${HISTDIR}/${HISTFILE}.dat

/usr/sbin/opendmarc-import --dbhost=${DBHOST} --dbuser=${DBUSER} --dbpasswd=${DBPASS} --dbname=${DBNAME} --verbose < ${HISTDIR}/${HISTFILE}_import.dat
/usr/sbin/opendmarc-reports-sasl --dbhost=${DBHOST} --dbuser=${DBUSER} --dbpasswd=${DBPASS} --dbname=${DBNAME} --verbose --interval=86400 --report-email=${RPTEMAIL} --smtp-server=${SMTPHOST} --smtp-port=${SMTPPORT} --smtp-user=${SMTPUSER} --smtp-password=${SMTPPASSWORD}
/usr/sbin/opendmarc-expire --dbhost=${DBHOST} --dbuser=${DBUSER} --dbpasswd=${DBPASS} --dbname=${DBNAME} --verbose

# NOTE: RPTEMAIL is used to send an aliased email address (ie. no mailbox) to a recipient. This is important as 'in this case' we want to advertise that emails won't be replied to, if someone sends a reply email.


3) SMTP Authentication Change to Postfix

In order to be able to send out emails addressed as an alias, it has to be married back to the authenticating account. Within the file of Postfix, there is a configuration clause called 'smtpd_sender_login_maps' which allows you to set which email accounts can use certain aliases to send emails out. 
In most cases, smtpd_sender_login_maps points to a plain text file. I will explain how to change it in this instance.
First, locate for the existence of smtpd_sender_login_maps in . If it doesn't exist, set it up in the format : 
# within 

smtpd_sender_login_maps = hash:/etc/postfix/sendermaps
Then, create (or edit if it exists) the file /etc/postfix/sendermaps and add the following :
where the first column is the alias, and the second column is your authenticated mailbox. Using this method, it is possible for multiple authenticated accounts to send out emails using a dedicated alias. (eg.
Commit the changes to Postfix by typing the following from the command prompt.  
# From /etc/postfix directory

$ postmap /etc/postfix/sendermaps


Once all is ready, restart your Postfix service and check the service for any startup errors. Run the script and monitor the system journal (or mail log) for any errors trying to email the OpenDMARC reports. If all is well, the generated report should successfully authenticate, submit the email to the queue, send it and remove it from the queue. 



About the author

Tom Thorp
Tom Thorp is an IT Consultant living in Miami on Queensland's Gold Coast. With over 30+ years working in the IT industry, Tom's experience is a broad canvas. The IT services Tom provides to his clients, includes :
Website development and hosting
Database Administration
Server Administration (Windows, Linux, Apple)
PABX Hosting and Administration
Helpdesk Support (end-user & technical).
  If you like any of my content, consider a donation via Crypto by clicking on one of the payment methods :