initial commit of file from CVS for smeserver-qpsmtpd on Thu 26 Oct 11:25:19 BST 2023

This commit is contained in:
2023-10-26 11:25:19 +01:00
parent c8bfca82cb
commit c45ac2b2d0
197 changed files with 3867 additions and 2 deletions

View File

@@ -0,0 +1,8 @@
{
if (( $qpsmtpd{DMARCReporting} || 'disabled' ) =~ m/^1|on|enabled|yes$/){
$OUT .= '15 0 * * * qpsmtpd /usr/bin/dmarc_send_reports 2>&1 | grep -v "SSL connection failed" | logger -t "DMARC Reporting"' . "\n";
}
else{
$OUT .= "# DMARC Reporting is disabled\n";
}
}

View File

@@ -0,0 +1,5 @@
[organization]
domain = { $DomainName }
org_name = { $ldap{defaultCompany} || 'SME Server powered company' }
email = { $qpsmtpd{DMARCReportEmail} || 'admin@' . $DomainName }
extra_contact_info = { $qpsmtpd{DMARCContactInfo} || 'http://' . $DomainName }

View File

@@ -0,0 +1,3 @@
[report_store]
backend = SQL
dsn = dbi:SQLite:dbname=/var/lib/qpsmtpd/dmarc/reports.sqlite

View File

@@ -0,0 +1,2 @@
[dmarc]
backend = perl

View File

@@ -0,0 +1,3 @@
[dns]
timeout = 5
public_suffix_list = public_suffix_list

View File

@@ -0,0 +1,3 @@
[smtp]
hostname = { $SystemName . '.' . $DomainName }
smarthost = 127.0.0.1

View File

@@ -0,0 +1 @@
{ $qpsmtpd{'DKIMSelector'} || 'default' }

View File

@@ -0,0 +1,2 @@
#spamer@spamdomain.com
#@spamdomain.com

View File

@@ -0,0 +1,9 @@
{
require esmith::AccountsDB;
require esmith::DomainsDB;
%Accounts = esmith::AccountsDB->as_hash;
%Domains = esmith::DomainsDB->as_hash;
"";
}

View File

@@ -0,0 +1,16 @@
{
foreach my $account ( keys %Accounts )
{
next unless ( exists $Accounts{$account}{Visible}
and $Accounts{$account}{Visible} eq "internal" );
$OUT .= "$account\n";
$OUT .= "$account\@$DomainName\n";
foreach my $domain ( keys %Domains )
{
next unless $Domains{$domain}{type} eq "domain";
$OUT .= "$account\@$domain\n";
}
}
}

View File

@@ -0,0 +1,14 @@
{
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB\n";
my @rcpt_hosts = ( "$SystemName.$DomainName" );
foreach my $domain ( $ddb->get_all_by_prop( type => "domain" ) )
{
push @rcpt_hosts, $domain->key;
}
$OUT = join "\n", @rcpt_hosts;
}

View File

@@ -0,0 +1,5 @@
{
return "" unless (defined $ExternalIP);
return "[$ExternalIP]";
}

View File

@@ -0,0 +1,6 @@
0
{
# the first line of this file is being used as the IP
# address tcpserver will bind to. Use 0 to bind to all
# interfaces.
}

View File

@@ -0,0 +1,3 @@
{
$ExternalIP || "# ExternalIP not defined";
}

View File

@@ -0,0 +1 @@
# these domains never uses their domain when greeting us, so reject transactions

View File

@@ -0,0 +1 @@
aol.com

View File

@@ -0,0 +1 @@
yahoo.com

View File

@@ -0,0 +1 @@
! Sorry, bang paths not accepted here

View File

@@ -0,0 +1 @@
@.*@ Sorry, multiple at signs not accepted here

View File

@@ -0,0 +1 @@
^@ Invalid recipient address

View File

@@ -0,0 +1 @@
% Sorry, percent hack not accepted here

View File

@@ -0,0 +1 @@
# Format is pattern\s+Response - don't forget to tie the pattern if required

View File

@@ -0,0 +1,8 @@
{
use esmith::AccountsDB;
use esmith::DomainsDB;
$a = esmith::AccountsDB->open_ro or die "Couldn't open AccountsDB";
$d = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB";
$OUT = '';
}

View File

@@ -0,0 +1,12 @@
{
$OUT .= '';
foreach my $alias ( $a->users, $a->groups, $a->pseudonyms ){
next unless ( $alias->prop('Visible') || '') =~ m/^(internal|none)$/i;
$OUT .= $alias->key . "\n" and next if $alias->key =~ m/@/;
foreach my $domain ( $d->domains ){
$OUT .= $alias->key . '@' . $domain->key . "\n";
}
}
}

View File

@@ -0,0 +1,23 @@
{
use esmith::util;
my @prefixes = esmith::util::computeAllLocalNetworkPrefixes($LocalIP,
$LocalNetmask);
require esmith::NetworksDB;
my $n = esmith::NetworksDB->open;
foreach my $network ($n->get_all_by_prop(type => 'network'))
{
push(@prefixes,
esmith::util::computeAllLocalNetworkPrefixes(
$network->key, $network->prop('Mask')));
}
foreach my $prefix ( @prefixes )
{
my $dot = ( $prefix =~ /\d+\.\d+\.\d+\.\d+/ ) ? '' : '.';
$OUT .= $prefix . $dot . "\n";
}
$OUT .= "127.0.0.1";
}

View File

@@ -0,0 +1,7 @@
{
my @rbllist = split /[,]/, ${qpsmtpd}{RBLList} || '';
return "# No RBLs are defined" unless (scalar @rbllist);
return join "\n", @rbllist;
}

View File

@@ -0,0 +1,6 @@
{
# rbl.mail-abuse.org
# spamsources.fabel.dk
# relays.ordb.org
# sbl.spamhaus.org
}

View File

@@ -0,0 +1,9 @@
{
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB";
@domains = map $_->key, $ddb->domains;
"";
}

View File

@@ -0,0 +1,5 @@
{
return "" unless (defined $ExternalIP);
return "postmaster\@[$ExternalIP]";
}

View File

@@ -0,0 +1,8 @@
{
$OUT = "";
for my $user ( qw(admin root) )
{
$OUT .= "$user\@$_\n" for (@domains);
}
}

View File

@@ -0,0 +1,24 @@
{
# Make a list of all valid local recipients
use esmith::AccountsDB;
my %valid = map { $_ => 1 } qw(group pseudonym user mailmanlist mailinglist);
$OUT = "";
my $adb = esmith::AccountsDB->open_ro();
foreach my $account ($adb->get_all)
{
my $key = $account->key;
next unless $valid{$account->prop('type')};
if ($key =~ /\@/)
{
$OUT .= "$key\n";
}
else
{
$OUT .= "$key\@$_\n" for (@domains);
}
}
}

View File

@@ -0,0 +1,17 @@
{
$OUT = "";
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro();
for my $domain ( $ddb->domains )
{
my $mail_server = $domain->prop('MailServer')
|| $DelegateMailServer
|| 'localhost';
next if ( $mail_server eq 'localhost' );
$OUT .= '@' . $domain->key . "\n";
}
}

View File

@@ -0,0 +1,2 @@
127.0.0.0/8
0.0.0.0/8

View File

@@ -0,0 +1,14 @@
{
# Log levels
# LOGDEBUG = 8
# LOGINFO = 7
# LOGNOTICE = 6
# LOGWARN = 5
# LOGERROR = 4
# LOGCRIT = 3
# LOGALERT = 2
# LOGEMERG = 1
# LOGRADAR = 0
return $qpsmtpd{LogLevel};
}

View File

@@ -0,0 +1,2 @@
# Format is IP, or IP part with trailing dot
# e.g. "127.0.0.1", or "192.168."

View File

@@ -0,0 +1,6 @@
{
return '' unless $GatewayIP;
# we allow access from the router, but we do not allow relaying
return $GatewayIP;
}

View File

@@ -0,0 +1,39 @@
{
# this is based on 70spamassassin fragment
# it does the same except it will force check on fetchmail inputs
# You can run the spamassassin plugin with options. See perldoc
# plugins/spamassassin for details.
#
# spamassassin
# rejects mails with a SA score higher than 20 and munges the subject
# of the score is higher than 10.
#
# spamassassin reject_threshold 20 munge_subject_threshold 10
my $status = $spamassassin{status} || 'disabled';
return "# spamassassin disabled" unless ($status eq "enabled");
my @options = qw(forcespamcheck);
if ($spamassassin{Sensitivity} eq "custom")
{
if ($spamassassin{RejectLevel} > $spamassassin{TagLevel})
{
push @options, "reject", $spamassassin{RejectLevel};
}
}
if ($spamassassin{SubjectTag} eq "enabled")
{
push @options, "munge_subject_threshold", $spamassassin{TagLevel};
}
my $size = $spamassassin{MaxMessageSize} || '';
if ($size =~ m/^\d+$/)
{
push @options, "size_limit", $size;
}
return join " ", @options;
}

View File

@@ -0,0 +1 @@
/usr/share/qpsmtpd/plugins

View File

@@ -0,0 +1,11 @@
{
$bounce_unknown_user = 1;
$bounce_unknown_user = 0
if (defined $EmailUnknownUser and $EmailUnknownUser ne 'returntosender');
$bounce_unknown_user = 0
if (defined $DelegateMailServer and $DelegateMailServer);
"";
}

View File

@@ -0,0 +1 @@
logging/logterse

View File

@@ -0,0 +1 @@
tls ssl/cert.pem ssl/cert.pem ssl/cert.pem ssl/dhparam.pem

View File

@@ -0,0 +1,9 @@
{
# my $auth_smtp = ($qpsmtpd{Authentication} eq 'enabled') ? 'yes' : 'no';
# my $auth_ssmtp = ($sqpsmtpd{Authentication} eq 'enabled') ? 'yes' : 'no';
# $OUT = "auth/auth_cvm_unix_local";
# $OUT .= " cvm_socket /var/lib/cvm/cvm-unix-local.socket";
# $OUT .= " enable_smtp $auth_smtp";
# $OUT .= " enable_ssmtp $auth_ssmtp";
}

View File

@@ -0,0 +1,3 @@
{
$OUT .= "auth/auth_imap 127.0.0.1 143";
}

View File

@@ -0,0 +1,6 @@
{
return "# Karma plugin is disabled" unless (($qpsmtpd{Karma} || 'disabled') =~ m/^1|on|yes|enabled$/i);
my $negative = $qpsmtpd{KarmaNegative} || '2';
my $strikes = $qpsmtpd{KarmaStrikes} || '3';
$OUT .= "karma negative $negative strikes $strikes reject naughty db_dir /var/lib/qpsmtpd/karma";
}

View File

@@ -0,0 +1 @@
earlytalker

View File

@@ -0,0 +1 @@
bogus_bounce

View File

@@ -0,0 +1 @@
count_unrecognized_commands 4

View File

@@ -0,0 +1,7 @@
{
return "# bcc disabled" unless ($qpsmtpd{Bcc} eq "enabled");
my $user = $qpsmtpd{BccUser} || '';
return "# bcc user not set" if $user eq '';
$user .= '@' . $DomainName unless $user =~ m/\@/;
return "bcc mode " . $qpsmtpd{BccMode} . " all " . $user;
}

View File

@@ -0,0 +1 @@
relay

View File

@@ -0,0 +1 @@
helo policy { $qpsmtpd{HeloPolicy} || 'lenient' } reject naughty

View File

@@ -0,0 +1 @@
resolvable_fromhost

View File

@@ -0,0 +1,8 @@
{
$OUT = "headers";
# Note: You can't specify a maximum offset of 0 days, but that's fair
my $days = $qpsmtpd{MaximumDateOffset} || '';
$OUT .= " future $days past $days" if ($days);
}

View File

@@ -0,0 +1 @@
loadcheck max_load { $qpsmtpd{MaxLoad} || '7' }

View File

@@ -0,0 +1,5 @@
{
return "# rhsbl disabled" unless (${qpsmtpd}{RHSBL} eq "enabled");
"rhsbl";
}

View File

@@ -0,0 +1 @@
sender_permitted_from reject 1 no_dmarc_policy { $qpsmtpd{SPFRejectPolicy} || '0' }

View File

@@ -0,0 +1 @@
dkim reject 0

View File

@@ -0,0 +1 @@
dmarc reject { (( $qpsmtpd{DMARCReject} || 'disabled' ) =~ m/^1|on|enabled|yes$/) ? '1' : '0' } reporting { (( $qpsmtpd{DMARCReporting} || 'enabled' ) =~ m/^1|on|enabled|yes$/) ? '1' : '0' }

View File

@@ -0,0 +1,5 @@
{
return "# dnsbl disabled" unless (${qpsmtpd}{DNSBL} eq "enabled");
"dnsbl reject naughty";
}

View File

@@ -0,0 +1 @@
naughty reject mail

View File

@@ -0,0 +1,5 @@
{
return "# uribl disabled" unless (${qpsmtpd}{URIBL} eq "enabled");
"uribl action deny";
}

View File

@@ -0,0 +1 @@
badmailfrom

View File

@@ -0,0 +1 @@
badrcptto

View File

@@ -0,0 +1 @@
badrcptto more_badrcptto badrcptto_ext

View File

@@ -0,0 +1,13 @@
{
return "check_smtp_forward" if $DelegateMailServer;
use esmith::DomainsDB;
my $ddb = esmith::DomainsDB->open_ro();
for my $domain ( $ddb->domains )
{
return "check_smtp_forward" if $domain->prop('MailServer');
}
return "# check_smtp_forward not required";
}

View File

@@ -0,0 +1,5 @@
{
return "" unless $bounce_unknown_user;
"check_goodrcptto extn -";
}

View File

@@ -0,0 +1,4 @@
{
# this plugin needs to run after all other "rcpt" plugins
}
rcpt_ok

View File

@@ -0,0 +1,7 @@
{
return "# pattern_filter disabled"
unless ($qpsmtpd{PatternsScan} eq "enabled");
return "virus/pattern_filter check=patterns action=deny";
}

View File

@@ -0,0 +1,6 @@
{
return "# tnef to mime conversion disabled"
unless ($qpsmtpd{tnef2mime} eq "enabled");
return "tnef2mime";
}

View File

@@ -0,0 +1,6 @@
{
return "# disclaimer disabled"
unless ($qpsmtpd{disclaimer} || 'disabled') eq "enabled";
return "disclaimer";
}

View File

@@ -0,0 +1,36 @@
{
# You can run the spamassassin plugin with options. See perldoc
# plugins/spamassassin for details.
#
# spamassassin
# rejects mails with a SA score higher than 20 and munges the subject
# of the score is higher than 10.
#
# spamassassin reject_threshold 20 munge_subject_threshold 10
my $status = $spamassassin{status} || 'disabled';
return "# spamassassin disabled" unless ($status eq "enabled");
my @options = qw(spamassassin);
if ($spamassassin{Sensitivity} eq "custom")
{
if ($spamassassin{RejectLevel} > $spamassassin{TagLevel})
{
push @options, "reject", $spamassassin{RejectLevel};
}
}
if ($spamassassin{SubjectTag} eq "enabled")
{
push @options, "munge_subject_threshold", $spamassassin{TagLevel};
}
my $size = $spamassassin{MaxMessageSize} || '';
if ($size =~ m/^\d+$/)
{
push @options, "size_limit", $size;
}
return join " ", @options;
}

View File

@@ -0,0 +1,23 @@
{
# run the clamdscan virus checking plugin
my $s = $clamd{status} || 'disabled';
return "# clamd disabled" unless ($s eq "enabled");
$s = $qpsmtpd{VirusScan} || 'disabled';
return "# clamav disabled" unless ($s eq "enabled");
my $max_size = $qpsmtpd{MaxScannerSize} ||
$clamav{StreamMaxLength} ||
"25M";
$max_size =~ s/[kK]/000/;
$max_size =~ s/[mM]/000000/;
# clamdscan takes size in kb
$max_size = int($max_size / 1000);
$OUT = "virus/clamdscan" .
" scan_all yes" .
" clamd_socket /run/clamd/clamd.socket" .
" defer_on_error yes" .
" max_size $max_size";
}

View File

@@ -0,0 +1,5 @@
{
#return "# DelegateMailServer set" if $DelegateMailServer;
return "queue/qmail-queue";
}

View File

@@ -0,0 +1,5 @@
{
#return "# DelegateMailServer not set" unless $DelegateMailServer;
#return "queue/smtp-forward $DelegateMailServer";
}

View File

@@ -0,0 +1,2 @@
# Format is IP, or IP part with trailing dot
# e.g. "127.0.0.1", or "192.168."

View File

@@ -0,0 +1,5 @@
{
$OUT = "127.0.0.1\n";
$OUT = "127.0.0.\n";
$OUT .= "$LocalIP";
}

View File

@@ -0,0 +1,37 @@
{
use esmith::util::network qw(isValidIP);
use Net::IPv4Addr qw(ipv4_in_network ipv4_parse);
my $relayclients = ${qpsmtpd}{UnauthenticatedRelayClients} || return;
my @relayclients = split /[,:]/, $relayclients;
my $ndb = esmith::NetworksDB->open_ro();
sub convert_to_cidr
{
$_ = shift;
return "$_/32" unless m!/!;
my ($ip,$bits) = ipv4_parse($_);
return "$ip/$bits";
}
my @localAccess = map {
convert_to_cidr($_)
} $ndb->local_access_spec();
foreach my $relayclient (@relayclients)
{
if (!isValidIP($relayclient))
{
$OUT .= "## $relayclient is not an IP\n";
}
elsif (grep { ipv4_in_network($_, $relayclient) } @localAccess)
{
$OUT .= "$relayclient\n";
}
else
{
$OUT .= "## $relayclient is not in any local network\n";
}
}
}

View File

@@ -0,0 +1,25 @@
{
use esmith::util;
my @prefixes = ();
require esmith::NetworksDB;
my $n = esmith::NetworksDB->open;
foreach my $network ($n->get_all_by_prop(type => 'network'))
{
if ( (($qpsmtpd{'RelayRequiresAuth'} || 'enabled') eq 'disabled') or
(($network->prop('RelayRequiresAuth') || 'enabled') eq 'disabled'))
{
push(@prefixes,
esmith::util::computeAllLocalNetworkPrefixes(
$network->key, $network->prop('Mask')));
}
}
foreach my $prefix ( @prefixes )
{
my $dot = ( $prefix =~ /\d+\.\d+\.\d+\.\d+/ ) ? '' : '.';
$OUT .= $prefix . $dot . "\n";
}
}

View File

@@ -0,0 +1,7 @@
{
my @rbllist = split /[,]/, ${qpsmtpd}{SBLList} || '';
return "# No SBLs are defined" unless (scalar @rbllist);
return join "\n", @rbllist;
}

View File

@@ -0,0 +1,11 @@
{
use esmith::ConfigDB;
$pdb = esmith::ConfigDB->open_ro('mailpatterns');
return "# Couldn't open mailpatterns\n" unless $pdb;
@patterns = $pdb->get_all_by_prop(type => 'pattern');
"";
}

View File

@@ -0,0 +1,14 @@
{
foreach my $pattern (@patterns)
{
my %props = $pattern->props;
next unless ($props{type} eq 'pattern');
next unless ($props{Status} eq 'enabled');
$OUT .= "$_\n" for (split(/,/, $props{Body}));
}
"";
}

View File

@@ -0,0 +1,3 @@
{
$qpsmtpd{Greeting} || "$SystemName.$DomainName";
}

View File

@@ -0,0 +1 @@
/var/spool/qpsmtpd

View File

@@ -0,0 +1,13 @@
{
use esmith::ConfigDB;
my $db = esmith::ConfigDB->open_ro ||
die 'Could not open configuration database';
my $subject = $db->get_prop('spamassassin', 'Subject') || '';
$OUT = $subject;
}

View File

@@ -0,0 +1,4 @@
{
my $timeout = $qpsmtpd{timeout} || 120;
$OUT = "$timeout";
}

View File

@@ -0,0 +1,4 @@
{
my $timeout = $qpsmtpd{timeoutsmtpd} || 120;
$OUT = "$timeout";
}

View File

@@ -0,0 +1,4 @@
# The next line should be set to 0 if you want to offer AUTH without TLS
{
return $qpsmtpd{ TlsBeforeAuth };
}

View File

@@ -0,0 +1,5 @@
{
# When updating CipherSuite both e-smith-apache and smeserver-qpsmtpd templates should be updated.
return $qpsmtpd{tlsCipher} || $modSSL{CipherSuite} || 'ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:HIGH@STRENGTH:!SSLv2:!ADH:!aNULL:!MD5:!RC4';
}

View File

@@ -0,0 +1,8 @@
{
$OUT .= 'SSLv23';
$OUT .= ':!SSLv2' unless ($qpsmtpd{SSLv2} || 'disabled') eq 'enabled';
$OUT .= ':!SSLv3' unless ($qpsmtpd{SSLv3} || 'disabled') eq 'enabled';
$OUT .= ':!TLSv1' unless ($qpsmtpd{TLSv1} || 'enabled') eq 'enabled';
$OUT .= ':!TLSv1.1' unless ($qpsmtpd{TLSv1.1} || 'enabled') eq 'enabled';
$OUT .= ':!TLSv1.2' unless ($qpsmtpd{TLSv1.2} || 'enabled') eq 'enabled';
}

View File

@@ -0,0 +1,19 @@
{
my @ubllist = split /[,]/, ${qpsmtpd}{UBLList} || '';
return "# No URIBLs are defined" unless (scalar @ubllist);
$OUT .= '';
foreach my $bl (@ubllist){
my @l = split /[:]/, $bl;
$OUT .= $l[0];
if ($l[1]){
$l[1] =~ s/-/,/g;
$OUT .= " $l[1]";
if ($l[2] && $l[2] =~ m/^add\-header|deny(soft)?$/){
$OUT .= " $l[2]";
}
}
$OUT .= "\n";
}
}

View File

@@ -0,0 +1 @@
+RELAYCLIENT

View File

@@ -0,0 +1 @@
+RELAYCLIENT{ $OUT = ($qpsmtpd{'RelayRequiresAuth'} || 'enabled') eq 'disabled' ? '=' : '' }

View File

@@ -0,0 +1,4 @@
# This templated file is sourced by the qpsmtpd run
# file. Shell variables can be set here for use by the run
# script, or environment variables can be exported for use
# by qpsmtpd.

View File

@@ -0,0 +1,3 @@
{
return "INSTANCES=" . ($qpsmtpd{Instances} || "40");
}

Some files were not shown because too many files have changed in this diff Show More