Add parsing of SPF/DKIM log entries. Thanks to r-sherwood for the feature request.

This commit is contained in:
Gilles Darold 2018-06-17 23:47:16 +02:00
parent 39bf967922
commit 709a398708
4 changed files with 325 additions and 8 deletions

View file

@ -240,7 +240,6 @@ ERROR_CODE lang/ERROR_CODE
# sender or recipient relay to determine the email direction.
#VIRTUAL_DOMAIN_DB_QUERY SELECT name FROM virtual_domains
# Syslog name of MimeDefang. Syslog write it to maillog with the pid as follow:
# ... mimedefang.pl[1234] ... This is required to only parse relevant logged lines
# Based on parsing mimedefang log generated by method md_graphdefang_log()
@ -304,6 +303,10 @@ CLAMSMTPD_NAME clamsmtpd
# Can be overwritten with --postgrey or -g
POSTGREY_NAME postgrey|sqlgrey
# Syslog name of SPF and DKIM log entry. Syslog write it to maillog with the
# pid as follow: ... opendmarc[1234] ...
SPF_DKIM_NAME opendmarc|opendkim
# HTML charset to use. Default is iso-8859-1, but with cyrillics you may want
# to use utf-8 instead.
#HTML_CHARSET utf-8

View file

@ -256,6 +256,10 @@ CLAMSMTPD_NAME clamsmtpd
# Can be overwritten with --postgrey or -g
POSTGREY_NAME postgrey|sqlgrey
# Syslog name of SPF and DKIM log entry. Syslog write it to maillog with the
# pid as follow: ... opendmarc[1234] ...
SPF_DKIM_NAME opendmarc|opendkim
# HTML charset to use. Default is iso-8859-1, but with cyrillics you may want
# to use utf-8 instead.
#HTML_CHARSET utf-8

236
sa_cache
View file

@ -278,6 +278,7 @@ our %topauth = ();
our %postgrey = ();
our %toppostgrey = ();
our %starttls = ();
our %spf_dkim = ();
####
@ -634,6 +635,27 @@ sub do_hour_cache
close(IN);
}
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/spf_dkim.dat";
if (open(IN, $file)) {
while (my $l = <IN>) {
chomp($l);
# Format: Hour:Id:Type:Rule:Domain:Status
@data = split(/:/, $l);
$data[0] =~ /^(\d{2})/;
next if ($1 ne $hour);
if ($data[2] eq 'spf') {
$localstat{$data[1]}{$data[2]}{$data[3]}{hour} = $data[0] if (!exists $localstat{$data[1]}{$data[2]}{$data[3]}{hour});
#$localstat{$data[1]}{$data[2]}{$data[3]}{domain}{$data[4]}++;
$localstat{$data[1]}{$data[2]}{$data[3]}{status}{$data[5]}++;
} elsif ($data[2] eq 'dkim') {
$localstat{$data[1]}{$data[2]}{hour} = $data[0] if (!exists $localstat{$data[1]}{$data[2]}{hour});
#$localstat{$data[1]}{$data[2]}{domain}{$data[4]}++;
$localstat{$data[1]}{$data[2]}{status}{$data[5]}++;
}
}
close(IN);
}
for my $typ (sort keys %ANTISPAM_NAME) {
$file = "$CONFIG{OUT_DIR}/$hostname/$year/$month/$day/$typ.dat";
if (open(IN, $file)) {
@ -816,8 +838,6 @@ sub compute_top_stats
$toppostgrey{rcpt}{$STATS->{$id}{rcpt}[$i]}++;
}
$toppostgrey{reason}{$STATS->{$id}{reason}}++;
}
if (exists $STATS->{$id}{spamtype} && grep(/^$STATS->{$id}{spamtype}$/, keys %ANTISPAM_NAME)) {
@ -1475,6 +1495,25 @@ sub compute_global_stats
$postgrey{reason}{$STATS->{$id}{reason}}++;
}
if (exists $STATS->{$id}{spf}) {
foreach my $r (keys %{ $STATS->{$id}{spf} }) {
#foreach my $k (keys %{ $STATS->{$id}{spf}{$r}{domain} }) {
# $spf_dkim{spf}{$r}{domain}{$k} += $STATS->{$id}{spf}{$r}{domain}{$k};
#}
foreach my $k (keys %{ $STATS->{$id}{spf}{$r}{status} }) {
$spf_dkim{spf}{$r}{status}{$k} += $STATS->{$id}{spf}{$r}{status}{$k};
}
}
}
if (exists $STATS->{$id}{dkim}) {
foreach my $k (keys %{ $STATS->{$id}{dkim}{status} }) {
$spf_dkim{dkim}{status}{$k} += $STATS->{$id}{dkim}{status}{$k};
}
#foreach my $k (keys %{ $STATS->{$id}{dkim}{domain} }) {
# $spf_dkim{dkim}{domain}{$k} += $STATS->{$id}{dkim}{domain}{$k};
#}
}
}
# Top STARTTLS stats
@ -1637,6 +1676,32 @@ sub compute_global_stats
print OUT "},\n";
print OUT ");\n\n";
%postgrey = ();
print OUT "\%::spf_dkim = (\n";
print OUT "'spf' => {\n";
foreach my $r (keys %{$spf_dkim{spf}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$spf_dkim{spf}{$r}}) {
print OUT "\t\t'$s' => { ";
foreach my $v (keys %{$spf_dkim{spf}{$r}{$s}}) {
print OUT "'$v' => '$spf_dkim{spf}{$r}{$s}{$v}',";
}
print OUT " },\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT "'dkim' => {\n";
foreach my $r (keys %{$spf_dkim{dkim}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$spf_dkim{dkim}{$r}}) {
print OUT "\t\t'$s' => '$spf_dkim{dkim}{$r}{$s}',\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT ");\n\n";
%spf_dkim = ();
# Viruses flows / Viruses delivery flows / syserr flows
print OUT "\%::virus = (\n";
@ -1831,6 +1896,7 @@ sub do_day_cache
my %localpostgrey = ();
my %localtoppostgrey = ();
my %localstarttls = ();
my %localspf_dkim = ();
my $lbls = '';
my %authval = ();
foreach my $hour ("00" .. "23") {
@ -1899,6 +1965,20 @@ sub do_day_cache
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
}
%postgrey = ();
foreach my $r (keys %{$spf_dkim{spf}}) {
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
}
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
}
}
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
}
%spf_dkim = ();
foreach my $k (keys %virus) {
if (!grep(/^$k$/, 'lbls','x_label','values')) {
$localvirus{$k} += $virus{$k};
@ -2114,6 +2194,32 @@ sub do_day_cache
print OUT ");\n\n";
%localpostgrey = ();
print OUT "\%::spf_dkim = (\n";
print OUT "'spf' => {\n";
foreach my $r (keys %{$localspf_dkim{spf}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
print OUT "\t\t'$s' => { ";
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
}
print OUT " },\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT "'dkim' => {\n";
foreach my $r (keys %{$localspf_dkim{dkim}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT ");\n\n";
%localspf_dkim = ();
print OUT "\%::virus = (\n";
print OUT "'inbound' => '$localvirus{inbound}',\n";
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
@ -2644,6 +2750,7 @@ sub do_month_cache
my %localpostgrey = ();
my %localtoppostgrey = ();
my %localstarttls = ();
my %localspf_dkim = ();
my $lbls = '';
foreach my $day ("01" .. "31") {
$lbls .= "$day:";
@ -2712,6 +2819,20 @@ sub do_month_cache
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
}
%postgrey = ();
foreach my $r (keys %{$spf_dkim{spf}}) {
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
}
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
}
}
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
}
%spf_dkim = ();
foreach my $k (keys %virus) {
if (!grep(/^$k$/, 'lbls','x_label','values')) {
$localvirus{$k} += $virus{$k};
@ -2928,6 +3049,32 @@ sub do_month_cache
print OUT "},\n";
print OUT ");\n\n";
%localpostgrey = ();
print OUT "\%::spf_dkim = (\n";
print OUT "'spf' => {\n";
foreach my $r (keys %{$localspf_dkim{spf}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
print OUT "\t\t'$s' => { ";
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
}
print OUT " },\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT "'dkim' => {\n";
foreach my $r (keys %{$localspf_dkim{dkim}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT ");\n\n";
%localspf_dkim = ();
print OUT "\%::virus = (\n";
print OUT "'inbound' => '$localvirus{inbound}',\n";
@ -3452,6 +3599,7 @@ sub do_year_cache
my %localpostgrey = ();
my %localtoppostgrey = ();
my %localstarttls = ();
my %localspf_dkim = ();
my $lbls = '';
foreach my $month ("01" .. "12") {
@ -3520,6 +3668,20 @@ sub do_year_cache
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
}
%postgrey = ();
foreach my $r (keys %{$spf_dkim{spf}}) {
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
}
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
}
}
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
}
%spf_dkim = ();
foreach my $k (keys %virus) {
if (!grep(/^$k$/, 'lbls','x_label','values')) {
$localvirus{$k} += $virus{$k};
@ -3739,7 +3901,33 @@ sub do_year_cache
print OUT "},\n";
print OUT ");\n\n";
%localpostgrey = ();
print OUT "\%::spf_dkim = (\n";
print OUT "'spf' => {\n";
foreach my $r (keys %{$localspf_dkim{spf}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
print OUT "\t\t'$s' => { ";
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
}
print OUT " },\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT "'dkim' => {\n";
foreach my $r (keys %{$localspf_dkim{dkim}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT ");\n\n";
%localspf_dkim = ();
print OUT "\%::virus = (\n";
print OUT "'inbound' => '$localvirus{inbound}',\n";
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
@ -4376,6 +4564,7 @@ sub do_week_cache
my %localpostgrey = ();
my %localtoppostgrey = ();
my %localstarttls = ();
my %localspf_dkim = ();
my $lbls = '';
my %authval = ();
&clean_globals();
@ -4448,6 +4637,20 @@ sub do_week_cache
$localpostgrey{reason}{$k} += $postgrey{reason}{$k};
}
%postgrey = ();
foreach my $r (keys %{$spf_dkim{spf}}) {
foreach my $k (keys %{$spf_dkim{spf}{$r}{status}}) {
$localspf_dkim{spf}{$r}{status}{$k} += $spf_dkim{spf}{$r}{status}{$k};
}
foreach my $k (keys %{$spf_dkim{spf}{$r}{domain}}) {
$localspf_dkim{spf}{$r}{domain}{$k} += $spf_dkim{spf}{$r}{domain}{$k};
}
}
foreach my $r (keys %{$spf_dkim{dkim}{status}}) {
$localspf_dkim{dkim}{status}{$r} += $spf_dkim{dkim}{status}{$r};
}
%spf_dkim = ();
foreach my $k (keys %virus) {
if (!grep(/^$k$/, 'lbls','x_label','values')) {
$localvirus{$k} += $virus{$k};
@ -4673,6 +4876,32 @@ sub do_week_cache
print OUT ");\n\n";
%localpostgrey = ();
print OUT "\%::spf_dkim = (\n";
print OUT "'spf' => {\n";
foreach my $r (keys %{$localspf_dkim{spf}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{spf}{$r}}) {
print OUT "\t\t'$s' => { ";
foreach my $v (keys %{$localspf_dkim{spf}{$r}{$s}}) {
print OUT "'$v' => '$localspf_dkim{spf}{$r}{$s}{$v}',";
}
print OUT " },\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT "'dkim' => {\n";
foreach my $r (keys %{$localspf_dkim{dkim}}) {
print OUT "\t'$r' => {\n";
foreach my $s (keys %{$localspf_dkim{dkim}{$r}}) {
print OUT "\t\t'$s' => '$localspf_dkim{dkim}{$r}{$s}',\n";
}
print OUT "\t},\n";
}
print OUT "},\n";
print OUT ");\n\n";
%localspf_dkim = ();
print OUT "\%::virus = (\n";
print OUT "'inbound' => '$localvirus{inbound}',\n";
print OUT "'inbound_bytes' => '$localvirus{inbound_bytes}',\n";
@ -4954,7 +5183,6 @@ sub do_week_cache
print OUT ");\n\n";
%localtoppostgrey = ();
# Top virus statistics
$top = 0;
print OUT "\%::topvirus = (\n";

View file

@ -91,6 +91,7 @@ my %AMAVIS_ID = ();
my %STARTTLS = ();
my %SPAMPD = ();
my %KEEP_TEMPORARY = ();
my %SPF_DKIM = ();
# Collect command line arguments
GetOptions (
@ -116,6 +117,7 @@ GetOptions (
'z|zcat=s' => \$CONFIG{ZCAT_PROG},
'y|year=s' => \$CONFIG{DEFAULT_YEAR},
'spamd=s' => \$CONFIG{SPAMD_NAME},
'spf=s' => \$CONFIG{SPF_DKIM_NAME},
'hostname=s' => \$HOSTNAME,
);
@ -250,6 +252,8 @@ sendmailanalyzer v$VERSION usage:
Default /usr/bin/zcat.
--spamd name : syslog Spamd program name. Default: spamd.
--hostname name : set a hostname for exim logs. Default: unknown.
--spf name : syslog SPF and DKIM program name list.
Default: opendmarc|opendkim.
};
exit 0;
}
@ -350,7 +354,7 @@ sub start_loop
my $tmp_last_parsed = $l;
# Only catch relevant logs
next if ($CONFIG{EXCLUDE_LINE} && $tmp_last_parsed =~ m#$CONFIG{EXCLUDE_LINE}#);
if ( ($tmp_last_parsed =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME}|$CONFIG{CLAMSMTPD_NAME})[\/\[:]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
if ( ($tmp_last_parsed =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME}|$CONFIG{CLAMSMTPD_NAME}|$CONFIG{SPF_DKIM_NAME})[\/\[:]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
if ($tmp_last_parsed ne $OLD_LAST_PARSED) {
&dprint("Size is identique but data are more recent than the one at old offset. Rereading from start of the log file.") if ($CONFIG{DEBUG} > 0);
seek(SA_FILE, 0, 0);
@ -381,7 +385,7 @@ sub start_loop
$l = '';
# Only catch relevant logs
next if ($CONFIG{EXCLUDE_LINE} && $LAST_PARSED =~ m#$CONFIG{EXCLUDE_LINE}#);
if ( ($LAST_PARSED =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME}|$CONFIG{CLAMSMTPD_NAME})[\/\[:]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
if ( ($LAST_PARSED =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME}|$CONFIG{CLAMSMTPD_NAME}|$CONFIG{SPF_DKIM_NAME})[\/\[:]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
my $tmpos = tell(SA_FILE);
if ($OLD_LAST_PARSED) {
# Store the last position in the log
@ -469,7 +473,7 @@ sub start_loop
# Only catch relevant logs
next if ($CONFIG{EXCLUDE_LINE} && $LAST_PARSED =~ m#$CONFIG{EXCLUDE_LINE}#);
my $check_time = '';
if ( ($LAST_PARSED =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME})[\/\[]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
if ( ($LAST_PARSED =~ /($CONFIG{MTA_NAME}|$CONFIG{MAILSCAN_NAME}|$CONFIG{AMAVIS_NAME}|$CONFIG{MD_NAME}|$CONFIG{CLAMD_NAME}|$CONFIG{POSTGREY_NAME}|$CONFIG{SPAMD_NAME}|$CONFIG{CLAMSMTPD_NAME}|$CONFIG{SPF_DKIM_NAME})[\/\[]/) || ($LAST_PARSED =~ $EXIM_REGEX) ) {
# Extract common fields and store data in memory
$check_time = &store_data(&parse_common_fields(split(/\s+/, $LAST_PARSED)));
} else {
@ -574,6 +578,8 @@ sub store_data
&parse_postgrey("$date","$time",$host,$other);
} elsif ($CONFIG{SPAMD_NAME} && ($type =~ /^$CONFIG{SPAMD_NAME}/i)) {
&parse_spamd("$date","$time",$host,$other);
} elsif ($CONFIG{SPF_DKIM_NAME} && ($type =~ /^$CONFIG{SPF_DKIM_NAME}/i)) {
&parse_spf_dkim("$date","$time",$host,$other);
} else {
&dprint("Skipping unknown syslog report => $date $time $host [$type]: $other") if ($CONFIG{DEBUG} > 1);
}
@ -2137,6 +2143,44 @@ sub parse_spamd
}
}
####
# Parse DKIM/SPF syslog output
####
sub parse_spf_dkim
{
my ($date,$time,$host,$str) = @_;
my $time_st = "$date$time";
#Jun 7 06:22:58 server opendmarc[980]: 2693E3640260: news.vendita--flash.com none
if ($str =~ /^([^:]+): SPF\(([^\)]+)\): ([^\s]+) ([^\s]+)$/) {
my $id = $1;
$SPF_DKIM{$host}{spf}{$id}{rule} = $2;
$SPF_DKIM{$host}{spf}{$id}{status} = $4;
$SPF_DKIM{$host}{spf}{$id}{domain} = &clean_relay($3);
$SPF_DKIM{$host}{spf}{$id}{date} = $time_st;
#Jun 7 06:22:58 server opendkim[953]: 2693E3640260: DKIM verification successful
} elsif ($str =~ /^([^:]+): DKIM (.*)$/) {
my $id = $1;
$SPF_DKIM{$host}{dkim}{$id}{status} = $2;
$SPF_DKIM{$host}{dkim}{$id}{date} = $time_st;
#Jun 7 08:43:51 server opendkim[953]: 07EE63640A96: DKIM-Signature field added (s=default, d=mydomain.com)
} elsif ($str =~ /^([^:]+): DKIM-([^\(]+) \(s=([^,]+), d=([^\)]+)\)$/) {
my $id = $1;
$SPF_DKIM{$host}{dkim}{$id}{status} = $2;
$SPF_DKIM{$host}{dkim}{$id}{rule} = $3;
$SPF_DKIM{$host}{dkim}{$id}{domain} = $4;
$SPF_DKIM{$host}{dkim}{$id}{date} = $time_st;
}
}
####
# Decode email address and keep only email part
####
@ -2568,6 +2612,42 @@ sub flush_data
# clear all postgrey memory storage
%POSTGREY = ();
# SaveSPF/DKIM objects
&dprint("Writing SPF/DKIM detail data to disk...");
$nobj = 0;
foreach my $host (keys %SPF_DKIM) {
my %spf_dkims = ();
foreach my $kind (keys %{$SPF_DKIM{$host}}) {
foreach my $id (keys %{$SPF_DKIM{$host}{$kind}}) {
if (exists $EXCLUDED{$id}) {
delete $SPF_DKIM{$host}{$kind}{$id};
next;
}
next if ($SPF_DKIM{$host}{$kind}{$id}{date} !~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
# Key: year/month/day, Format: Hour:Id:type:rule:domain:status
$spf_dkims{"$1/$2/$3"} .= "$4$5$6" . ':' . $id . ':' . $kind . ':' . $SPF_DKIM{$host}{$kind}{$id}{rule} . ':' . $SPF_DKIM{$host}{$kind}{$id}{domain} . ':' . $SPF_DKIM{$host}{$kind}{$id}{status} . "\n";
$nobj++;
}
}
foreach my $dir (keys %spf_dkims) {
if (!-d "$CONFIG{OUT_DIR}/$host/$dir") {
&create_directory("$host/$dir");
}
if (not open(OUT, ">>$CONFIG{OUT_DIR}/$host/$dir/spf_dkim.dat") ) {
&logerror("Can't write to file $CONFIG{OUT_DIR}/$host/$dir/spf_dkim.dat: $!");
&logerror("Data will be lost.");
next;
} else {
print OUT $spf_dkims{$dir};
close(OUT);
}
}
}
&dprint("\tWrote $nobj spf/dkim object.");
# clear all spf/dkim memory storage
%SPF_DKIM = ();
# Save Virus objects
&dprint("Writing Virus data to disk...");
$nobj = 0;
@ -2840,6 +2920,7 @@ sub read_config
$CONFIG{PID_DIR} ||= '/var/run';
$CONFIG{POSTGREY_NAME} ||= 'postgrey|sqlgrey';
$CONFIG{SPAMD_NAME} ||= 'spamd';
$CONFIG{SPF_DKIM_NAME} ||= 'opendmarc|opendkim';
}
####
@ -3105,6 +3186,7 @@ sub clean_globals
%STARTTLS = ();
%SPAMPD = ();
%KEEP_TEMPORARY = ();
%SPF_DKIM = ();
}