How do I use async drop-in replacements for common checks?
Mail::MIMEDefang::Async provides async drop-in replacements for the most
common blocking network calls. After calling md_async_init at package
scope, you can swap these in place of their synchronous counterparts in
filter_begin or filter_sender with no other changes to your filter logic.
use Mail::MIMEDefang::Async;
sub filter_begin {
my($entity) = @_;
# Drop-in for relay_is_blacklisted() from Mail::MIMEDefang::Net
my $listed = md_async_relay_is_blacklisted($RelayAddr, 'zen.spamhaus.org');
if ($listed) {
md_syslog('Warning', "Relay $RelayAddr listed in zen.spamhaus.org");
return action_bounce("Mail rejected: $RelayAddr is blacklisted");
}
# Drop-in for md_spf_verify() from Mail::MIMEDefang::SPF
my ($spf_result, $spf_exp) = md_async_spf_verify($sender, $RelayAddr, $Helo);
if ($spf_result eq 'fail') {
return action_bounce("SPF check failed: $spf_exp");
}
# Drop-in for md_get_dmarc_record() from Mail::MIMEDefang::Net
my $from_domain = $sender;
$from_domain =~ s/^.*\@//;
my $dmarc_raw = md_async_dmarc_verify($from_domain);
if (defined $dmarc_raw) {
my ($policy) = ($dmarc_raw =~ /\bp=(\w+)/i);
md_syslog('Info', "DMARC policy for $from_domain: " . ($policy // 'none'));
}
}
sub filter_end {
my($entity) = @_;
# Drop-in for md_spamc_check() from Mail::MIMEDefang::Antispam (needs spamd)
my ($score, $threshold, $report, $isspam) = md_async_spamc_check(
host => '127.0.0.1',
port => 783,
);
if (defined $score && $isspam) {
action_change_header('X-Spam-Flag', 'YES');
action_change_header('X-Spam-Score', "$score / $threshold");
}
# Drop-in for rspamd_check() from Mail::MIMEDefang::Antispam
my ($hits, $req, $tests, $rpt, $action, $is_spam) = md_async_rspamd_check();
md_syslog('Info', "Rspamd: action=$action spam=$is_spam score=$hits/$req");
}