diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e594810
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.rpm
+*.log
+*spec-20*
+*.tar.xz
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..576caac
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+# Makefile for source rpm: smeserver-qpsmtpd
+# $Id: Makefile,v 1.1 2016/02/05 23:28:48 stephdl Exp $
+NAME := smeserver-qpsmtpd
+SPECFILE = $(firstword $(wildcard *.spec))
+
+define find-makefile-common
+for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
+endef
+
+MAKEFILE_COMMON := $(shell $(find-makefile-common))
+
+ifeq ($(MAKEFILE_COMMON),)
+# attept a checkout
+define checkout-makefile-common
+test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
+endef
+
+MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
+endif
+
+include $(MAKEFILE_COMMON)
diff --git a/README.md b/README.md
index e411342..53204a7 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,26 @@
-# smeserver-qpsmtpd
+# smeserver-qpsmtpd
-SMEServer Koozali developed git repo for smeserver-qpsmtpd smeserver
\ No newline at end of file
+SMEServer Koozali developed git repo for smeserver-qpsmtpd smeserver
+
+## Wiki
+
https://wiki.koozali.org/Qpsmtpd
+
https://wiki.koozali.org/Qpsmtpd:help
+
https://wiki.koozali.org/Qpsmtpd:tls
+
https://wiki.koozali.org/Qpsmtpd:bcc
+
https://wiki.koozali.org/Qpsmtpd:fcrdns
+
https://wiki.koozali.org/Qpsmtpd:tls_cert
+
https://wiki.koozali.org/Qpsmtpd:content_log
+
https://wiki.koozali.org/Qpsmtpd:relay
+
https://wiki.koozali.org/Qpsmtpd:peers
+
https://wiki.koozali.org/Qpsmtpd:helo
+
+## Bugzilla
+Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-qpsmtpd&product=SME%20Server%2010.X&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
+
+## Description
+
+
*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
+*Once it has been checked, then this comment will be deleted*
+
+
+Qpsmtpd is an open source, high-performance, extensible SMTP server written in Perl. It provides a secure and reliable way to deliver emails, and is used in many production systems around the world. It is highly customizable, and can be extended with additional plugins to provide advanced features such as spam filtering, virus scanning, and user authentication. Qpsmtpd is reliable, fast, and highly scalable, making it ideal for high-volume email delivery. It is also easy to configure and manage, and integrates seamlessly with other email systems.
diff --git a/contriborbase b/contriborbase
new file mode 100644
index 0000000..ef36a67
--- /dev/null
+++ b/contriborbase
@@ -0,0 +1 @@
+sme10
diff --git a/createlinks b/createlinks
new file mode 100644
index 0000000..a3d90da
--- /dev/null
+++ b/createlinks
@@ -0,0 +1,220 @@
+#!/usr/bin/perl -w
+
+use esmith::Build::CreateLinks qw(:all);
+
+foreach $event (qw(
+ email-update
+ domain-modify
+ domain-create
+ domain-delete
+ bootstrap-console-save
+ smeserver-qpsmtpd-update
+ ))
+{
+ event_link("domains-update-dkim", $event, "30");
+}
+
+my $service = "/var/service/qpsmtpd";
+
+foreach $event (qw(
+ network-create
+ network-delete
+ smeserver-qpsmtpd-update
+ ))
+{
+ templates2events("$service/config/relayclients", $event);
+}
+
+foreach $event (qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ network-create
+ network-delete
+ smeserver-qpsmtpd-update
+ ))
+{
+ templates2events("$service/peers/0", $event);
+ templates2events("$service/peers/local", $event);
+
+ templates2events("$service/config/peers/0", $event);
+ templates2events("$service/config/peers/local", $event);
+}
+
+templates2events("$service/runenv", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ smeserver-qpsmtpd-update
+ ));
+
+templates2events("$service/ssl/cert.pem", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ ssl-update
+ smeserver-qpsmtpd-update
+ ));
+
+templates2events($_, qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ smeserver-qpsmtpd-update
+ ))
+ for (qw(
+ /etc/mail-dmarc.ini
+ /home/e-smith/dkim_keys/default/selector
+ ));
+
+my $secure_service = "/var/service/sqpsmtpd";
+
+templates2events("$secure_service/runenv", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ smeserver-qpsmtpd-update
+ ));
+
+my $control = "/var/qmail/control";
+templates2events("$control/badmailfrom", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ smeserver-qpsmtpd-update
+ ));
+templates2events("$control/badrcptto", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ domain-create
+ domain-delete
+ user-create
+ user-delete
+ user-modify
+ group-create
+ group-delete
+ group-modify
+ pseudonym-create
+ pseudonym-delete
+ pseudonym-modify
+ smeserver-qpsmtpd-update
+ ));
+
+my $config = "/var/service/qpsmtpd/config";
+templates2events("$config/$_", qw(
+ bootstrap-console-save
+ console-save
+ email-update
+ smeserver-qpsmtpd-update
+ ))
+ for (qw(
+ IP
+ badhelo
+ badrcptto
+ badrcptto_ext
+ dnsbl_zones
+ dnsbl_allow
+ uribl_zones
+ loglevel
+ memory_threshold
+ plugins
+ relayclients norelayclients
+ rhsbl_zones
+ signatures_patterns
+ plugin_dirs
+ smtpgreeting
+ spool_dir
+ subject_prefix
+ invalid_resolvable_fromhost
+ timeout
+ timeoutsmtpd
+ tls_before_auth
+ tls_ciphers
+ tls_protocols
+ ));
+templates2events("$config/badrcptto_ext", qw(
+ domain-create
+ domain-delete
+ user-create
+ user-delete
+ user-modify
+ group-create
+ group-delete
+ group-modify
+ pseudonym-create
+ pseudonym-delete
+ pseudonym-modify
+ smeserver-qpsmtpd-update
+ ));
+
+templates2events("$config/$_", qw(
+ ssl-update
+ smeserver-qpsmtpd-update
+ ))
+ for (qw(
+ tls_before_auth
+ tls_ciphers
+ tls_protocols
+ ));
+
+templates2events("$config/badhelo", 'ip-change');
+
+templates2events("$config/goodrcptto", qw(
+ bootstrap-console-save
+ email-update
+ domain-create
+ domain-delete
+ user-create
+ user-delete
+ user-modify
+ pseudonym-create
+ pseudonym-delete
+ pseudonym-modify
+ group-create
+ group-delete
+ group-modify
+ smeserver-qpsmtpd-update
+ ));
+
+safe_touch("root/etc/e-smith/templates/$config/forcespamcheck/template-begin");
+templates2events("$config/forcespamcheck", qw(
+ bootstrap-console-save
+ email-update
+ domain-create
+ domain-delete
+ user-create
+ user-delete
+ user-modify
+ pseudonym-create
+ pseudonym-delete
+ pseudonym-modify
+ group-create
+ group-delete
+ group-modify
+ smeserver-qpsmtpd-update
+ ));
+
+
+
+for my $daemon ( qw(qpsmtpd sqpsmtpd) )
+{
+ safe_symlink("sighup",
+ "root/etc/e-smith/events/email-update/services2adjust/$daemon");
+ safe_symlink("sighup",
+ "root/etc/e-smith/events/ssl-update/services2adjust/$daemon");
+}
+
+for my $event ( qw(network-create network-delete) )
+{
+ safe_symlink("sigusr1",
+ "root/etc/e-smith/events/$event/services2adjust/qpsmtpd");
+}
+
+
+my $event = 'smeserver-qpsmtpd-update';
+safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/qpsmtpd");
+safe_symlink("restart", "root/etc/e-smith/events/$event/services2adjust/sqpsmtpd");
+templates2events("/etc/systemd/system-preset/49-koozali.preset", $event);
+event_link("systemd-reload", $event, "89");
+event_link("systemd-default", $event, "88");
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Authentication b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Authentication
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Authentication
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Bcc b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Bcc
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Bcc
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccMode b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccMode
new file mode 100644
index 0000000..46c1d61
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccMode
@@ -0,0 +1 @@
+cc
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccUser b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccUser
new file mode 100644
index 0000000..371f1e8
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/BccUser
@@ -0,0 +1 @@
+maillog
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/DNSBL b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/DNSBL
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/DNSBL
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Instances b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Instances
new file mode 100644
index 0000000..425151f
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Instances
@@ -0,0 +1 @@
+40
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/InstancesPerIP b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/InstancesPerIP
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/InstancesPerIP
@@ -0,0 +1 @@
+5
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/LogLevel b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/LogLevel
new file mode 100644
index 0000000..1e8b314
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/LogLevel
@@ -0,0 +1 @@
+6
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaxScannerSize b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaxScannerSize
new file mode 100644
index 0000000..430a17b
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaxScannerSize
@@ -0,0 +1 @@
+25000000
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaximumDateOffset b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaximumDateOffset
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/MaximumDateOffset
@@ -0,0 +1 @@
+0
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/PatternsScan b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/PatternsScan
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/PatternsScan
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Proxy b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Proxy
new file mode 100644
index 0000000..650e036
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/Proxy
@@ -0,0 +1 @@
+blocked
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RBLList b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RBLList
new file mode 100644
index 0000000..c8a4f69
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RBLList
@@ -0,0 +1 @@
+bl.spamcop.net,dnsbl-1.uceprotect.net,dnsbl-2.uceprotect.net,psbl.surriel.com,zen.spamhaus.org
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RHSBL b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RHSBL
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RHSBL
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RelayRequiresAuth b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RelayRequiresAuth
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/RelayRequiresAuth
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/SBLList b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/SBLList
new file mode 100644
index 0000000..99aa424
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/SBLList
@@ -0,0 +1 @@
+multi.surbl.org,black.uribl.com,rhsbl.sorbs.net
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPPort b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPPort
new file mode 100644
index 0000000..7273c0f
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPPort
@@ -0,0 +1 @@
+25
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPProxyPort b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPProxyPort
new file mode 100644
index 0000000..7273c0f
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TCPProxyPort
@@ -0,0 +1 @@
+25
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TlsBeforeAuth b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TlsBeforeAuth
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/TlsBeforeAuth
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/UBLList b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/UBLList
new file mode 100644
index 0000000..a8a5c5e
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/UBLList
@@ -0,0 +1 @@
+multi.surbl.org:8-16-64-128,black.uribl.com,rhsbl.sorbs.net
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/URIBL b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/URIBL
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/URIBL
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/VirusScan b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/VirusScan
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/VirusScan
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/access b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/access
new file mode 100644
index 0000000..a48cf0d
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/access
@@ -0,0 +1 @@
+public
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/qplogsumm b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/qplogsumm
new file mode 100644
index 0000000..7a68b11
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/qplogsumm
@@ -0,0 +1 @@
+disabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/status b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/status
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/status
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/tnef2mime b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/tnef2mime
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/tnef2mime
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/qpsmtpd/type b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/type
new file mode 100644
index 0000000..24e1098
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/qpsmtpd/type
@@ -0,0 +1 @@
+service
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Authentication b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Authentication
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Authentication
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Instances b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Instances
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/Instances
@@ -0,0 +1 @@
+10
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/TCPPort b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/TCPPort
new file mode 100644
index 0000000..073c57b
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/TCPPort
@@ -0,0 +1 @@
+465
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/access b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/access
new file mode 100644
index 0000000..a48cf0d
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/access
@@ -0,0 +1 @@
+public
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/status b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/status
new file mode 100644
index 0000000..86981e6
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/status
@@ -0,0 +1 @@
+enabled
diff --git a/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/type b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/type
new file mode 100644
index 0000000..24e1098
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/defaults/sqpsmtpd/type
@@ -0,0 +1 @@
+service
diff --git a/root/etc/e-smith/db/configuration/migrate/20RBLList b/root/etc/e-smith/db/configuration/migrate/20RBLList
new file mode 100644
index 0000000..8bdcc3a
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/migrate/20RBLList
@@ -0,0 +1,35 @@
+{
+ $qpsmtpd = $DB->get('qpsmtpd');
+ return unless $qpsmtpd;
+ my $rbl = $qpsmtpd->prop('RBLList');
+ return unless $rbl;
+
+ my @rbl = ();
+ # Migrate to use , as separator instead of :
+ if ($rbl !~ m/,/){
+ my @zones = split /[:]/, $rbl;
+ my $fqdn_re = qr/([a-zA-Z0-9][a-zA-Z0-9\-]{1,61}\.)*[a-zA-Z0-9][a-zA-Z0-9\-]{1,61}\.[a-zA-Z]{2,}/;
+ if (scalar @zones == 2 && $zones[1] !~ m/^$fqdn_re$/){
+ # When we have only two entries, check if the second one looks like a valid hostname
+ # so if you only have something like dnsbl.foo.net:Sorry you are blacklisted
+ # it won't be migrated to dnsbl.foo.net,Sorry you are blacklisted
+ @rbl = ($rbl);
+ }
+ else{
+ @rbl = @zones;
+ }
+ }
+ else{
+ @rbl = split /[,]/, $rbl;
+ }
+
+ my %obsolete = map { $_ => 1} qw(
+ combined.njabl.org
+ list.dsbl.org
+ multihop.dsbl.org
+ dnsbl.ahbl.org
+ );
+
+ @rbl = grep { ! $obsolete{$_} } @rbl;
+ $qpsmtpd->set_prop('RBLList', join ',', @rbl);
+}
diff --git a/root/etc/e-smith/db/configuration/migrate/20RequireResolvableFromHost b/root/etc/e-smith/db/configuration/migrate/20RequireResolvableFromHost
new file mode 100644
index 0000000..1af8727
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/migrate/20RequireResolvableFromHost
@@ -0,0 +1,3 @@
+{
+ return unless $DB->get_prop_and_delete('qpsmtpd', 'RequireResolvableFromHost');
+}
diff --git a/root/etc/e-smith/db/configuration/migrate/20SBLLIST b/root/etc/e-smith/db/configuration/migrate/20SBLLIST
new file mode 100644
index 0000000..64d4b96
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/migrate/20SBLLIST
@@ -0,0 +1,38 @@
+{
+ $qpsmtpd = $DB->get('qpsmtpd');
+ return unless $qpsmtpd;
+ my $sbl = $qpsmtpd->prop('SBLList');
+ return unless $sbl;
+
+ my @sbl = ();
+ # Migrate to use , as separator instead of :
+ if ($sbl !~ m/,/){
+ my @zones = split /[:]/, $sbl;
+ my $fqdn_re = qr/([a-zA-Z0-9][a-zA-Z0-9\-]{1,61}\.)*[a-zA-Z0-9][a-zA-Z0-9\-]{1,61}\.[a-zA-Z]{2,}/;
+ if (scalar @zones == 2 && $zones[1] !~ m/^$fqdn_re$/){
+ # When we have only two entries, check if the second one looks like a valid hostname
+ # so if you only have something like rhsbl.foo.net:Sorry you are blacklisted
+ # it won't be migrated to rhsbl.foo.net,Sorry you are blacklisted
+ @sbl = ($sbl);
+ }
+ else{
+ @sbl = @zones;
+ }
+ }
+ else{
+ @sbl = split /[,]/, $sbl;
+ }
+
+ my %obsolete = map { $_ => 1} qw(
+ blackhole.securitysage.com
+ bulk.rhs.mailpolice.com
+ fraud.rhs.mailpolice.com
+ porn.rhs.mailpolice.com
+ adult.rhs.mailpolice.com
+ bogusmx.rfc-ignorant.org
+ ex.dnsbl.org
+ );
+
+ @sbl = grep { !$obsolete{$_} } @sbl;
+ $qpsmtpd->set_prop('SBLList', join ',', @sbl);
+}
diff --git a/root/etc/e-smith/db/configuration/migrate/80Qpsmtpd b/root/etc/e-smith/db/configuration/migrate/80Qpsmtpd
new file mode 100644
index 0000000..b6a9860
--- /dev/null
+++ b/root/etc/e-smith/db/configuration/migrate/80Qpsmtpd
@@ -0,0 +1,19 @@
+{
+ my $smtpd = $DB->get("smtpd");
+ if ($smtpd){
+ my $qpsmtpd = $DB->get("qpsmtpd") ||
+ $DB->new_record("qpsmtpd", { type => "service" });
+
+ $qpsmtpd->merge_props($smtpd->props);
+ $smtpd->delete;
+ }
+
+ my $ssmtpd = $DB->get("ssmtpd");
+ if ($ssmtpd){
+ my $sqpsmtpd = $DB->get("sqpsmtpd") ||
+ $DB->new_record("sqpsmtpd", { type => "service" });
+
+ $sqpsmtpd->merge_props($ssmtpd->props);
+ $ssmtpd->delete;
+ }
+}
diff --git a/root/etc/e-smith/events/actions/domains-update-dkim b/root/etc/e-smith/events/actions/domains-update-dkim
new file mode 100644
index 0000000..366c35f
--- /dev/null
+++ b/root/etc/e-smith/events/actions/domains-update-dkim
@@ -0,0 +1,40 @@
+#!/usr/bin/perl -w
+
+use esmith::DomainsDB;
+use esmith::ConfigDB;
+use File::Find;
+
+my $d = esmith::DomainsDB->open_ro || die "Couldn't open the domains database";
+my $c = esmith::ConfigDB->open_ro || die "Couldn't open the configurtion database";
+
+my $qpsmtpd = $c->get('qpsmtpd');
+die "qpsmtpd service entry not found" unless ($qpsmtpd);
+
+my $dkim_sign = $qpsmtpd->prop('DKIMSigning') || 'disabled';
+
+find({ wanted => \&wanted }, qw(/var/service/qpsmtpd/config/dkim/));
+
+# Build a list of domain for which we want to sign emails
+my @dkim_domains = ();
+
+if ($dkim_sign =~ m/^enabled|yes|1|on$/){
+ foreach my $dom ($d->domains){
+ next if ($dom->prop('DKIMSigning') || 'enabled') eq 'disabled';
+ next if ($dom->prop('MailServer'));
+ push @dkim_domains, $dom->key;
+ }
+}
+
+
+sub wanted{
+ my $domain = $d->get($_);
+ if ( -l && !grep { $_ eq $domain->key } @dkim_domains ){
+ unlink $_;
+ }
+}
+
+foreach my $dom (@dkim_domains){
+ next if (-e '/var/service/qpsmtpd/config/dkim/' . $dom);
+ my $src = ( -e '/home/e-smith/dkim_keys/' . $dom ) ? '/home/e-smith/dkim_keys/' . $dom : '/home/e-smith/dkim_keys/default';
+ symlink $src, '/var/service/qpsmtpd/config/dkim/' . $dom;
+}
diff --git a/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/config/plugins b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/config/plugins
new file mode 100644
index 0000000..497bc32
--- /dev/null
+++ b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/config/plugins
@@ -0,0 +1 @@
+OUTPUT_FILENAME="/var/service/qpsmtpd/config/peers/0"
diff --git a/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/0 b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/0
new file mode 100644
index 0000000..c0fa009
--- /dev/null
+++ b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/0
@@ -0,0 +1 @@
+PERMS=use esmith::ConfigDB; (esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('access') eq "private") ? "000" : "0644"
diff --git a/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/locals b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/locals
new file mode 100644
index 0000000..52f4ffa
--- /dev/null
+++ b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/peers/locals
@@ -0,0 +1 @@
+PERMS=use esmith::ConfigDB; (esmith::ConfigDB->open_ro->get('qpsmtpd')->prop('status') eq "enabled") ? "0644" : "0000"
diff --git a/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/ssl/cert.pem b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/ssl/cert.pem
new file mode 100644
index 0000000..f627b35
--- /dev/null
+++ b/root/etc/e-smith/templates.metadata/var/service/qpsmtpd/ssl/cert.pem
@@ -0,0 +1,4 @@
+TEMPLATE_PATH="/home/e-smith/ssl.pem"
+OUTPUT_FILENAME="/var/service/qpsmtpd/ssl/cert.pem"
+GID="qpsmtpd"
+PERMS=0640
diff --git a/root/etc/e-smith/templates/etc/crontab/DMARCReports b/root/etc/e-smith/templates/etc/crontab/DMARCReports
new file mode 100644
index 0000000..e4eaa0f
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/crontab/DMARCReports
@@ -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";
+ }
+}
diff --git a/root/etc/e-smith/templates/etc/mail-dmarc.ini/100organization b/root/etc/e-smith/templates/etc/mail-dmarc.ini/100organization
new file mode 100644
index 0000000..98e6860
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/mail-dmarc.ini/100organization
@@ -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 }
diff --git a/root/etc/e-smith/templates/etc/mail-dmarc.ini/200ReportStore b/root/etc/e-smith/templates/etc/mail-dmarc.ini/200ReportStore
new file mode 100644
index 0000000..18741ff
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/mail-dmarc.ini/200ReportStore
@@ -0,0 +1,3 @@
+[report_store]
+backend = SQL
+dsn = dbi:SQLite:dbname=/var/lib/qpsmtpd/dmarc/reports.sqlite
diff --git a/root/etc/e-smith/templates/etc/mail-dmarc.ini/300Dmarc b/root/etc/e-smith/templates/etc/mail-dmarc.ini/300Dmarc
new file mode 100644
index 0000000..ab271fb
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/mail-dmarc.ini/300Dmarc
@@ -0,0 +1,2 @@
+[dmarc]
+backend = perl
diff --git a/root/etc/e-smith/templates/etc/mail-dmarc.ini/400Dns b/root/etc/e-smith/templates/etc/mail-dmarc.ini/400Dns
new file mode 100644
index 0000000..721b8e3
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/mail-dmarc.ini/400Dns
@@ -0,0 +1,3 @@
+[dns]
+timeout = 5
+public_suffix_list = public_suffix_list
diff --git a/root/etc/e-smith/templates/etc/mail-dmarc.ini/500Smtp b/root/etc/e-smith/templates/etc/mail-dmarc.ini/500Smtp
new file mode 100644
index 0000000..d504f8b
--- /dev/null
+++ b/root/etc/e-smith/templates/etc/mail-dmarc.ini/500Smtp
@@ -0,0 +1,3 @@
+[smtp]
+hostname = { $SystemName . '.' . $DomainName }
+smarthost = 127.0.0.1
diff --git a/root/etc/e-smith/templates/home/e-smith/dkim_keys/default/selector/template-begin b/root/etc/e-smith/templates/home/e-smith/dkim_keys/default/selector/template-begin
new file mode 100644
index 0000000..b8f476a
--- /dev/null
+++ b/root/etc/e-smith/templates/home/e-smith/dkim_keys/default/selector/template-begin
@@ -0,0 +1 @@
+{ $qpsmtpd{'DKIMSelector'} || 'default' }
diff --git a/root/etc/e-smith/templates/var/qmail/control/badmailfrom/10sample b/root/etc/e-smith/templates/var/qmail/control/badmailfrom/10sample
new file mode 100644
index 0000000..995e8a1
--- /dev/null
+++ b/root/etc/e-smith/templates/var/qmail/control/badmailfrom/10sample
@@ -0,0 +1,2 @@
+#spamer@spamdomain.com
+#@spamdomain.com
diff --git a/root/etc/e-smith/templates/var/qmail/control/badrcptto/00setup b/root/etc/e-smith/templates/var/qmail/control/badrcptto/00setup
new file mode 100644
index 0000000..7443a6a
--- /dev/null
+++ b/root/etc/e-smith/templates/var/qmail/control/badrcptto/00setup
@@ -0,0 +1,9 @@
+{
+ require esmith::AccountsDB;
+ require esmith::DomainsDB;
+
+ %Accounts = esmith::AccountsDB->as_hash;
+ %Domains = esmith::DomainsDB->as_hash;
+
+ "";
+}
diff --git a/root/etc/e-smith/templates/var/qmail/control/badrcptto/10blockVisibleInternal b/root/etc/e-smith/templates/var/qmail/control/badrcptto/10blockVisibleInternal
new file mode 100644
index 0000000..77bf6c4
--- /dev/null
+++ b/root/etc/e-smith/templates/var/qmail/control/badrcptto/10blockVisibleInternal
@@ -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";
+ }
+ }
+}
diff --git a/root/etc/e-smith/templates/var/qmail/control/rcpthosts/10standard b/root/etc/e-smith/templates/var/qmail/control/rcpthosts/10standard
new file mode 100644
index 0000000..4121442
--- /dev/null
+++ b/root/etc/e-smith/templates/var/qmail/control/rcpthosts/10standard
@@ -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;
+}
diff --git a/root/etc/e-smith/templates/var/qmail/control/rcpthosts/12LiteralIP b/root/etc/e-smith/templates/var/qmail/control/rcpthosts/12LiteralIP
new file mode 100644
index 0000000..e55b368
--- /dev/null
+++ b/root/etc/e-smith/templates/var/qmail/control/rcpthosts/12LiteralIP
@@ -0,0 +1,5 @@
+{
+ return "" unless (defined $ExternalIP);
+
+ return "[$ExternalIP]";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/IP/10IP b/root/etc/e-smith/templates/var/service/qpsmtpd/config/IP/10IP
new file mode 100644
index 0000000..b45c65e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/IP/10IP
@@ -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.
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10ExternalIP b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10ExternalIP
new file mode 100644
index 0000000..53c1cdf
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10ExternalIP
@@ -0,0 +1,3 @@
+{
+ $ExternalIP || "# ExternalIP not defined";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10begin b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10begin
new file mode 100644
index 0000000..351fd3f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/10begin
@@ -0,0 +1 @@
+# these domains never uses their domain when greeting us, so reject transactions
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20aol.com b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20aol.com
new file mode 100644
index 0000000..28e30d5
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20aol.com
@@ -0,0 +1 @@
+aol.com
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20yahoo.com b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20yahoo.com
new file mode 100644
index 0000000..bd9a241
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badhelo/20yahoo.com
@@ -0,0 +1 @@
+yahoo.com
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoBangPaths b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoBangPaths
new file mode 100644
index 0000000..7766f97
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoBangPaths
@@ -0,0 +1 @@
+! Sorry, bang paths not accepted here
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoDoubleAt b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoDoubleAt
new file mode 100644
index 0000000..b4152c0
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoDoubleAt
@@ -0,0 +1 @@
+@.*@ Sorry, multiple at signs not accepted here
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoEmptyLocalPart b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoEmptyLocalPart
new file mode 100644
index 0000000..8c2980e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoEmptyLocalPart
@@ -0,0 +1 @@
+^@ Invalid recipient address
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoPercentHack b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoPercentHack
new file mode 100644
index 0000000..b7b18f0
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10NoPercentHack
@@ -0,0 +1 @@
+% Sorry, percent hack not accepted here
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10header b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10header
new file mode 100644
index 0000000..5dce99d
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto/10header
@@ -0,0 +1 @@
+# Format is pattern\s+Response - don't forget to tie the pattern if required
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/00Setup b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/00Setup
new file mode 100644
index 0000000..d0a0bd4
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/00Setup
@@ -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 = '';
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/10InternalPeudonymes b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/10InternalPeudonymes
new file mode 100644
index 0000000..42961e3
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/badrcptto_ext/10InternalPeudonymes
@@ -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";
+ }
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_allow/80LocalNetworks b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_allow/80LocalNetworks
new file mode 100644
index 0000000..ad99d7e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_allow/80LocalNetworks
@@ -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";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10RBLList b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10RBLList
new file mode 100644
index 0000000..b159403
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10RBLList
@@ -0,0 +1,7 @@
+{
+ my @rbllist = split /[,]/, ${qpsmtpd}{RBLList} || '';
+
+ return "# No RBLs are defined" unless (scalar @rbllist);
+
+ return join "\n", @rbllist;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10header b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10header
new file mode 100644
index 0000000..db3bc39
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/dnsbl_zones/10header
@@ -0,0 +1,6 @@
+{
+# rbl.mail-abuse.org
+# spamsources.fabel.dk
+# relays.ordb.org
+# sbl.spamhaus.org
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/00setup b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/00setup
new file mode 100644
index 0000000..f811006
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/00setup
@@ -0,0 +1,9 @@
+{
+ use esmith::DomainsDB;
+
+ my $ddb = esmith::DomainsDB->open_ro or die "Couldn't open DomainsDB";
+
+ @domains = map $_->key, $ddb->domains;
+
+ "";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/12PostmasterAtBracketLiteralIP b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/12PostmasterAtBracketLiteralIP
new file mode 100644
index 0000000..85f46c0
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/12PostmasterAtBracketLiteralIP
@@ -0,0 +1,5 @@
+{
+ return "" unless (defined $ExternalIP);
+
+ return "postmaster\@[$ExternalIP]";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/30ValidAdmin b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/30ValidAdmin
new file mode 100644
index 0000000..8b1027b
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/30ValidAdmin
@@ -0,0 +1,8 @@
+{
+ $OUT = "";
+
+ for my $user ( qw(admin root) )
+ {
+ $OUT .= "$user\@$_\n" for (@domains);
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/40ValidLocalRecipients b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/40ValidLocalRecipients
new file mode 100644
index 0000000..55ff188
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/40ValidLocalRecipients
@@ -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);
+ }
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/50DelegatedDomains b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/50DelegatedDomains
new file mode 100644
index 0000000..8d0bb50
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/goodrcptto/50DelegatedDomains
@@ -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";
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/link_local b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/link_local
new file mode 100644
index 0000000..0e94287
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/link_local
@@ -0,0 +1 @@
+169.254.0.0/16
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/loopback b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/loopback
new file mode 100644
index 0000000..d23935e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/loopback
@@ -0,0 +1,2 @@
+127.0.0.0/8
+0.0.0.0/8
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/multicast b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/multicast
new file mode 100644
index 0000000..e2e59fa
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/invalid_resolvable_fromhost/multicast
@@ -0,0 +1 @@
+224.0.0.0/4
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/loglevel/10loglevel b/root/etc/e-smith/templates/var/service/qpsmtpd/config/loglevel/10loglevel
new file mode 100644
index 0000000..b6f8ef8
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/loglevel/10loglevel
@@ -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};
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/memory_threshold/10memory b/root/etc/e-smith/templates/var/service/qpsmtpd/config/memory_threshold/10memory
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/memory_threshold/10memory
@@ -0,0 +1 @@
+1
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/10header b/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/10header
new file mode 100644
index 0000000..9dff17f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/10header
@@ -0,0 +1,2 @@
+# Format is IP, or IP part with trailing dot
+# e.g. "127.0.0.1", or "192.168."
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/20norelayFromRouter b/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/20norelayFromRouter
new file mode 100644
index 0000000..626af3e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/norelayclients/20norelayFromRouter
@@ -0,0 +1,6 @@
+{
+ return '' unless $GatewayIP;
+
+ # we allow access from the router, but we do not allow relaying
+ return $GatewayIP;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/peers/local/71forcespamcheck b/root/etc/e-smith/templates/var/service/qpsmtpd/config/peers/local/71forcespamcheck
new file mode 100644
index 0000000..175d6e9
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/peers/local/71forcespamcheck
@@ -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;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugin_dirs/10plugins b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugin_dirs/10plugins
new file mode 100644
index 0000000..7846a58
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugin_dirs/10plugins
@@ -0,0 +1 @@
+/usr/share/qpsmtpd/plugins
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/00setup b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/00setup
new file mode 100644
index 0000000..b0e87ad
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/00setup
@@ -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);
+
+ "";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/02logterse b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/02logterse
new file mode 100644
index 0000000..89c0d97
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/02logterse
@@ -0,0 +1 @@
+logging/logterse
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/04tls b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/04tls
new file mode 100644
index 0000000..5191563
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/04tls
@@ -0,0 +1 @@
+tls ssl/cert.pem ssl/cert.pem ssl/cert.pem ssl/dhparam.pem
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/05auth_cvm_unix_local b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/05auth_cvm_unix_local
new file mode 100644
index 0000000..3d86e4c
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/05auth_cvm_unix_local
@@ -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";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/06auth_imap b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/06auth_imap
new file mode 100644
index 0000000..620bc20
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/06auth_imap
@@ -0,0 +1,3 @@
+{
+ $OUT .= "auth/auth_imap 127.0.0.1 143";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/09karma b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/09karma
new file mode 100644
index 0000000..040d410
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/09karma
@@ -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";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/10earlytalker b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/10earlytalker
new file mode 100644
index 0000000..c9f1778
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/10earlytalker
@@ -0,0 +1 @@
+earlytalker
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/11bogus_bounce b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/11bogus_bounce
new file mode 100644
index 0000000..08d39ce
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/11bogus_bounce
@@ -0,0 +1 @@
+bogus_bounce
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/12count_unrecognized_commands b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/12count_unrecognized_commands
new file mode 100644
index 0000000..2a3933c
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/12count_unrecognized_commands
@@ -0,0 +1 @@
+count_unrecognized_commands 4
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/13bcc b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/13bcc
new file mode 100644
index 0000000..057df1f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/13bcc
@@ -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;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/14relay b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/14relay
new file mode 100644
index 0000000..32e541a
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/14relay
@@ -0,0 +1 @@
+relay
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/15helo b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/15helo
new file mode 100644
index 0000000..2b79b79
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/15helo
@@ -0,0 +1 @@
+helo policy { $qpsmtpd{HeloPolicy} || 'lenient' } reject naughty
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/16resolvable_fromhost b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/16resolvable_fromhost
new file mode 100644
index 0000000..52f01c2
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/16resolvable_fromhost
@@ -0,0 +1 @@
+resolvable_fromhost
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/17headers b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/17headers
new file mode 100644
index 0000000..1240232
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/17headers
@@ -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);
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/19loadcheck b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/19loadcheck
new file mode 100644
index 0000000..ebe76ae
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/19loadcheck
@@ -0,0 +1 @@
+loadcheck max_load { $qpsmtpd{MaxLoad} || '7' }
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/20rhsbl b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/20rhsbl
new file mode 100644
index 0000000..60c25a1
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/20rhsbl
@@ -0,0 +1,5 @@
+{
+ return "# rhsbl disabled" unless (${qpsmtpd}{RHSBL} eq "enabled");
+
+ "rhsbl";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/221spf b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/221spf
new file mode 100644
index 0000000..6f883f7
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/221spf
@@ -0,0 +1 @@
+sender_permitted_from reject 1 no_dmarc_policy { $qpsmtpd{SPFRejectPolicy} || '0' }
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/222dkim b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/222dkim
new file mode 100644
index 0000000..1137cee
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/222dkim
@@ -0,0 +1 @@
+dkim reject 0
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/223dmarc b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/223dmarc
new file mode 100644
index 0000000..c9f4786
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/223dmarc
@@ -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' }
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/22dnsbl b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/22dnsbl
new file mode 100644
index 0000000..f08f295
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/22dnsbl
@@ -0,0 +1,5 @@
+{
+ return "# dnsbl disabled" unless (${qpsmtpd}{DNSBL} eq "enabled");
+
+ "dnsbl reject naughty";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/23naughty b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/23naughty
new file mode 100644
index 0000000..2651879
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/23naughty
@@ -0,0 +1 @@
+naughty reject mail
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/24uribl b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/24uribl
new file mode 100644
index 0000000..6abb7cc
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/24uribl
@@ -0,0 +1,5 @@
+{
+ return "# uribl disabled" unless (${qpsmtpd}{URIBL} eq "enabled");
+
+ "uribl action deny";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/30badmailfrom b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/30badmailfrom
new file mode 100644
index 0000000..57cfc17
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/30badmailfrom
@@ -0,0 +1 @@
+badmailfrom
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto
new file mode 100644
index 0000000..367f4c7
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto
@@ -0,0 +1 @@
+badrcptto
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto_ext b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto_ext
new file mode 100644
index 0000000..3e10fa6
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/34badrcptto_ext
@@ -0,0 +1 @@
+badrcptto more_badrcptto badrcptto_ext
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/37check_smtp_forward b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/37check_smtp_forward
new file mode 100644
index 0000000..ba52747
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/37check_smtp_forward
@@ -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";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/38check_goodrcptto b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/38check_goodrcptto
new file mode 100644
index 0000000..476ebae
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/38check_goodrcptto
@@ -0,0 +1,5 @@
+{
+ return "" unless $bounce_unknown_user;
+
+ "check_goodrcptto extn -";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/39rcpt_ok b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/39rcpt_ok
new file mode 100644
index 0000000..08a3113
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/39rcpt_ok
@@ -0,0 +1,4 @@
+{
+# this plugin needs to run after all other "rcpt" plugins
+}
+rcpt_ok
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62pattern_filter b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62pattern_filter
new file mode 100644
index 0000000..3a22312
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62pattern_filter
@@ -0,0 +1,7 @@
+{
+ return "# pattern_filter disabled"
+ unless ($qpsmtpd{PatternsScan} eq "enabled");
+
+ return "virus/pattern_filter check=patterns action=deny";
+}
+
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime
new file mode 100644
index 0000000..0c6f050
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime
@@ -0,0 +1,6 @@
+{
+ return "# tnef to mime conversion disabled"
+ unless ($qpsmtpd{tnef2mime} eq "enabled");
+ return "tnef2mime";
+}
+
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/65disclaimer b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/65disclaimer
new file mode 100644
index 0000000..7d3f2fa
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/65disclaimer
@@ -0,0 +1,6 @@
+{
+ return "# disclaimer disabled"
+ unless ($qpsmtpd{disclaimer} || 'disabled') eq "enabled";
+ return "disclaimer";
+}
+
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/70spamassassin b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/70spamassassin
new file mode 100644
index 0000000..feb9ddb
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/70spamassassin
@@ -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;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/80clamav b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/80clamav
new file mode 100644
index 0000000..96f9054
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/80clamav
@@ -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";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-qmail-queue b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-qmail-queue
new file mode 100644
index 0000000..86da349
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-qmail-queue
@@ -0,0 +1,5 @@
+{
+ #return "# DelegateMailServer set" if $DelegateMailServer;
+
+ return "queue/qmail-queue";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-smtp-forward b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-smtp-forward
new file mode 100644
index 0000000..6cc59ab
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/90queue-smtp-forward
@@ -0,0 +1,5 @@
+{
+ #return "# DelegateMailServer not set" unless $DelegateMailServer;
+
+ #return "queue/smtp-forward $DelegateMailServer";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10LocalNetworks b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10LocalNetworks
new file mode 100644
index 0000000..9dff17f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10LocalNetworks
@@ -0,0 +1,2 @@
+# Format is IP, or IP part with trailing dot
+# e.g. "127.0.0.1", or "192.168."
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10localhost b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10localhost
new file mode 100644
index 0000000..716abd9
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/10localhost
@@ -0,0 +1,5 @@
+{
+ $OUT = "127.0.0.1\n";
+ $OUT = "127.0.0.\n";
+ $OUT .= "$LocalIP";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/60myAppliances b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/60myAppliances
new file mode 100644
index 0000000..84f5f06
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/60myAppliances
@@ -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";
+ }
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/80relayFromLocalNetwork b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/80relayFromLocalNetwork
new file mode 100644
index 0000000..baafde0
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/relayclients/80relayFromLocalNetwork
@@ -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";
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/rhsbl_zones/10SBLList b/root/etc/e-smith/templates/var/service/qpsmtpd/config/rhsbl_zones/10SBLList
new file mode 100644
index 0000000..a6c27bb
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/rhsbl_zones/10SBLList
@@ -0,0 +1,7 @@
+{
+ my @rbllist = split /[,]/, ${qpsmtpd}{SBLList} || '';
+
+ return "# No SBLs are defined" unless (scalar @rbllist);
+
+ return join "\n", @rbllist;
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/rhsbl_zones/template-begin b/root/etc/e-smith/templates/var/service/qpsmtpd/config/rhsbl_zones/template-begin
new file mode 100644
index 0000000..e69de29
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/00setup b/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/00setup
new file mode 100644
index 0000000..a474198
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/00setup
@@ -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');
+
+ "";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/20blockPatterns b/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/20blockPatterns
new file mode 100644
index 0000000..d69f106
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/signatures_patterns/20blockPatterns
@@ -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}));
+ }
+
+ "";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/smtpgreeting/10Body b/root/etc/e-smith/templates/var/service/qpsmtpd/config/smtpgreeting/10Body
new file mode 100644
index 0000000..6c27983
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/smtpgreeting/10Body
@@ -0,0 +1,3 @@
+{
+ $qpsmtpd{Greeting} || "$SystemName.$DomainName";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/smtpgreeting/template-begin b/root/etc/e-smith/templates/var/service/qpsmtpd/config/smtpgreeting/template-begin
new file mode 100644
index 0000000..e69de29
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/spool_dir/10spool b/root/etc/e-smith/templates/var/service/qpsmtpd/config/spool_dir/10spool
new file mode 100644
index 0000000..3052d77
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/spool_dir/10spool
@@ -0,0 +1 @@
+/var/spool/qpsmtpd
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/subject_prefix/10subject b/root/etc/e-smith/templates/var/service/qpsmtpd/config/subject_prefix/10subject
new file mode 100644
index 0000000..391da7f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/subject_prefix/10subject
@@ -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;
+
+}
+
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeout b/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeout
new file mode 100644
index 0000000..b163880
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeout
@@ -0,0 +1,4 @@
+{
+ my $timeout = $qpsmtpd{timeout} || 120;
+ $OUT = "$timeout";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeoutsmtpd b/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeoutsmtpd
new file mode 100644
index 0000000..7e8a036
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/timeoutsmtpd
@@ -0,0 +1,4 @@
+{
+ my $timeout = $qpsmtpd{timeoutsmtpd} || 120;
+ $OUT = "$timeout";
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_before_auth/10Auth b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_before_auth/10Auth
new file mode 100644
index 0000000..95b3e2d
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_before_auth/10Auth
@@ -0,0 +1,4 @@
+# The next line should be set to 0 if you want to offer AUTH without TLS
+{
+return $qpsmtpd{ TlsBeforeAuth };
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_ciphers/10ciphers b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_ciphers/10ciphers
new file mode 100644
index 0000000..0670643
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_ciphers/10ciphers
@@ -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';
+}
+
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_protocols/10protocols b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_protocols/10protocols
new file mode 100644
index 0000000..a96db43
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/tls_protocols/10protocols
@@ -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';
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/config/uribl_zones/10URIBLList b/root/etc/e-smith/templates/var/service/qpsmtpd/config/uribl_zones/10URIBLList
new file mode 100644
index 0000000..6b1bfc4
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/config/uribl_zones/10URIBLList
@@ -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";
+ }
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/peers/0/RELAYCLIENT b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/0/RELAYCLIENT
new file mode 100644
index 0000000..06c8cf2
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/0/RELAYCLIENT
@@ -0,0 +1 @@
++RELAYCLIENT
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/peers/0/template-begin b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/0/template-begin
new file mode 100644
index 0000000..e69de29
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/peers/local/RELAYCLIENT b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/local/RELAYCLIENT
new file mode 100644
index 0000000..2c40699
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/local/RELAYCLIENT
@@ -0,0 +1 @@
++RELAYCLIENT{ $OUT = ($qpsmtpd{'RelayRequiresAuth'} || 'enabled') eq 'disabled' ? '=' : '' }
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/peers/local/template-begin b/root/etc/e-smith/templates/var/service/qpsmtpd/peers/local/template-begin
new file mode 100644
index 0000000..e69de29
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/00preamble b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/00preamble
new file mode 100644
index 0000000..7d2566e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/00preamble
@@ -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.
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES
new file mode 100644
index 0000000..dd175c5
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES
@@ -0,0 +1,3 @@
+{
+ return "INSTANCES=" . ($qpsmtpd{Instances} || "40");
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES_PER_IP b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES_PER_IP
new file mode 100644
index 0000000..954927f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/INSTANCES_PER_IP
@@ -0,0 +1,3 @@
+{
+ return "INSTANCES_PER_IP=" . ($qpsmtpd{InstancesPerIP} || "5");
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PATH b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PATH
new file mode 100644
index 0000000..f3a2e72
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PATH
@@ -0,0 +1 @@
+export PATH=/var/qmail/bin:/bin:/usr/bin:/usr/local/bin
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PORT b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PORT
new file mode 100644
index 0000000..f1e9023
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/PORT
@@ -0,0 +1,3 @@
+{
+ return "export PORT=" . ($qpsmtpd{TCPPort} || "25");
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/SOFTLIMIT b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/SOFTLIMIT
new file mode 100644
index 0000000..1408b06
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/SOFTLIMIT
@@ -0,0 +1,3 @@
+{
+ return "SOFTLIMIT=" . ($qpsmtpd{Softlimit} || "50000000");
+}
diff --git a/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/TCPLOCALHOST b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/TCPLOCALHOST
new file mode 100644
index 0000000..98b3559
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/qpsmtpd/runenv/TCPLOCALHOST
@@ -0,0 +1,3 @@
+{
+ return "export TCPLOCALHOST=$SystemName.$DomainName";
+}
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/00preamble b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/00preamble
new file mode 100644
index 0000000..aa968d0
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/00preamble
@@ -0,0 +1,4 @@
+# This templated file is sourced by the sqpsmtpd run
+# file. Shell variables can be set here for use by the run
+# script, or environment variables can be exported for use
+# by sqpsmtpd.
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES
new file mode 100644
index 0000000..55d219e
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES
@@ -0,0 +1,3 @@
+{
+ return "INSTANCES=" . ($sqpsmtpd{Instances} || $qpsmtpd{Instances} || "10");
+}
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES_PER_IP b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES_PER_IP
new file mode 100644
index 0000000..7b121e9
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/INSTANCES_PER_IP
@@ -0,0 +1,4 @@
+{
+ return "INSTANCES_PER_IP=" .
+ ($sqpsmtpd{InstancesPerIP} || $qpsmtpd{InstancesPerIP} || "5");
+}
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PATH b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PATH
new file mode 100644
index 0000000..f3a2e72
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PATH
@@ -0,0 +1 @@
+export PATH=/var/qmail/bin:/bin:/usr/bin:/usr/local/bin
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PORT b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PORT
new file mode 100644
index 0000000..21889c8
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/PORT
@@ -0,0 +1,3 @@
+{
+ return "export PORT=" . (${sqpsmtpd}{TCPPort} || "465");
+}
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/SOFTLIMIT b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/SOFTLIMIT
new file mode 100644
index 0000000..650525f
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/SOFTLIMIT
@@ -0,0 +1,3 @@
+{
+ return "SOFTLIMIT=" . ($sqpsmtpd{Softlimit} || $qpsmtpd{Softlimit} || "50000000");
+}
diff --git a/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/TCPLOCALHOST b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/TCPLOCALHOST
new file mode 100644
index 0000000..98b3559
--- /dev/null
+++ b/root/etc/e-smith/templates/var/service/sqpsmtpd/runenv/TCPLOCALHOST
@@ -0,0 +1,3 @@
+{
+ return "export TCPLOCALHOST=$SystemName.$DomainName";
+}
diff --git a/root/sbin/e-smith/qpsmtpd-print-dns b/root/sbin/e-smith/qpsmtpd-print-dns
new file mode 100644
index 0000000..a4677ea
--- /dev/null
+++ b/root/sbin/e-smith/qpsmtpd-print-dns
@@ -0,0 +1,80 @@
+#!/usr/bin/perl -w
+
+use esmith::ConfigDB;
+use esmith::DomainsDB;
+my $c = esmith::ConfigDB->open_ro || die "Couldn't open the configuration database";
+my $d = esmith::DomainsDB->open_ro || die "Couldn't open the domains database";
+my $domain = shift || $c->get('DomainName')->value;
+
+die "Domain $domain doesn't exist"
+ unless ($d->get($domain) && $d->get($domain)->prop('type') eq 'domain');
+
+warn "DKIM Signing is disabled for domain $domain"
+ if (($d->get($domain)->prop('DKIMSigning') || 'enabled') eq 'disabled');
+
+die "Can't find DKIM keys for domain $domain"
+ unless (-e "/var/service/qpsmtpd/config/dkim/$domain/public");
+
+die "Can't find the selector for domain $domain"
+ unless (-e "/var/service/qpsmtpd/config/dkim/$domain/selector");
+
+print <<'_EOF';
+
+Here are sample DNS entries you should add in your public DNS.
+
+There are two DKIM key copies.
+Depending on your provider you might be able to copy these as is.
+
+The first has a complete DKIM key with no "" breaks.
+
+The second has the DKIM entry broken into 255 character chunks
+with quotes for providers who cannot support long strings.
+You may need to separate these with either a space, a newline or
+a backslash escaped newline between the "" depending on your
+dns provider.
+
+You should either change the reporting email address for DMARC
+or create the needed pseudonym 'dmarc-feedback'.
+
+_EOF
+
+my $key_string = "v=DKIM1;p=";
+open PUBKEY, "/var/service/qpsmtpd/config/dkim/$domain/public";
+while(){
+ next if /^\-/;
+ chomp;
+ $key_string .= $_;
+}
+close PUBKEY;
+$key_string .= ";t=y";
+open SEL, "/var/service/qpsmtpd/config/dkim/$domain/selector";
+my $selector = ;
+chomp $selector;
+close SEL;
+
+
+print "DKIM complete\n";
+print "=============\n";
+print " \n";
+print "$selector._domainkey IN TXT $key_string\n";
+
+
+my @key_chunks = ( $key_string =~ /.{1,255}/g );
+my $txt = '';
+$txt .= '"' . $_ . '"' foreach (@key_chunks);
+
+print " \n";
+print "DKIM in 255 character chunks\n";
+print "============================\n";
+print " \n";
+
+print <<"_EOF";
+$selector._domainkey IN TXT $txt
+\n
+DMARC records
+=============
+\@ IN SPF "v=spf1 mx a -all"
+\@ IN TXT "v=spf1 mx a -all"
+_dmarc IN TXT "v=DMARC1; p=none; adkim=s; aspf=r; rua=mailto:dmarc-feedback\@$domain; pct=100"
+
+_EOF
diff --git a/root/service/qpsmtpd b/root/service/qpsmtpd
new file mode 120000
index 0000000..7c8b520
--- /dev/null
+++ b/root/service/qpsmtpd
@@ -0,0 +1 @@
+/var/service/qpsmtpd
\ No newline at end of file
diff --git a/root/service/sqpsmtpd b/root/service/sqpsmtpd
new file mode 120000
index 0000000..9c32df3
--- /dev/null
+++ b/root/service/sqpsmtpd
@@ -0,0 +1 @@
+/var/service/sqpsmtpd
\ No newline at end of file
diff --git a/root/usr/lib/systemd/system/qpsmtpd.service b/root/usr/lib/systemd/system/qpsmtpd.service
new file mode 100644
index 0000000..f79bb62
--- /dev/null
+++ b/root/usr/lib/systemd/system/qpsmtpd.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=qpsmtpd
+After=network.target
+Conflicts=proqpsmtpdd.service
+Requires=runit.service
+
+[Service]
+Type=oneshot
+ExecStartPre=/sbin/e-smith/service-status qpsmtpd
+ExecStart=/usr/bin/sv u /service/qpsmtpd
+ExecStop=/usr/bin/sv stop /service/qpsmtpd
+ExecReload=/usr/bin/sv h /service/qpsmtpd
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sme-server.target
diff --git a/root/usr/lib/systemd/system/sqpsmtpd.service b/root/usr/lib/systemd/system/sqpsmtpd.service
new file mode 100644
index 0000000..03a2167
--- /dev/null
+++ b/root/usr/lib/systemd/system/sqpsmtpd.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=sqpsmtpd
+After=network.target
+Conflicts=prosqpsmtpdd.service
+Requires=runit.service
+
+[Service]
+Type=oneshot
+ExecStartPre=/sbin/e-smith/service-status sqpsmtpd
+ExecStart=/usr/bin/sv u /service/sqpsmtpd
+ExecStop=/usr/bin/sv stop /service/sqpsmtpd
+ExecReload=/usr/bin/sv h /service/sqpsmtpd
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sme-server.target
diff --git a/root/usr/local/bin/qplogsumm.pl b/root/usr/local/bin/qplogsumm.pl
new file mode 100644
index 0000000..d2d258b
--- /dev/null
+++ b/root/usr/local/bin/qplogsumm.pl
@@ -0,0 +1,272 @@
+#!/usr/bin/perl
+#
+
+=pod
+
+=head1 SUMMARY
+
+Works with multilog to analyse and summarise log entries generated by the logterse plugin. It is designed
+to be invoked by multilog at log-rotation time. This is specified by an argument to multilog similar to:
+
+=over 4
+
+multilog t !/path/to/qplogsumm ./main
+
+=back
+
+When qplogsumm is invoked, each line will be echoed, meaning the stored log is unchanged, but summary
+information will be written to fd 5 and so stored in the 'state' file by multilog.
+
+This file is fed in on fd 4 at the beginning of the next log rotation, so running totals, etc can be maintained.
+
+=head1 State file format:
+
+One entry per line containing three fields separated by whitespace:
+
+=over 4
+
+=item 1. Disposition (plugin) name.
+
+=item 2. tai64n timestamp recording the first time it was seen in a log.
+
+=item 3. long-term running total.
+
+=back
+
+A disposition is effectively the plugin name that called DENY or the string 'queued' for
+messages that made it through.
+
+A line containing a disposition name of LOGFILE_EPOCH and a timestamp for the earliest known log entry.
+
+Other derived data, such as percentages etc. can also appear in the file, commented
+by a # character. This will be ignored on the next intake.
+
+=head1 AUTHOR
+
+Charles Butcher
+
+=head1 VERSION
+
+This is release 1.0
+
+=cut
+
+use strict;
+use POSIX qw(strftime);
+
+
+my $FS = "\t"; # field separator used by logterse plugin
+my %disp; # hash of dispositions
+
+if (open PREVIOUS, "<&4")
+{
+ while ()
+ {
+ chomp();
+ next if m/^#/;
+ next if m/^\s*$/;
+ my ($plug_name, $plug_epoch, $plug_cumulative) = split /\s+/;
+ my $c = { epoch => $plug_epoch, cum => $plug_cumulative, curr => 0 };
+ $disp{$plug_name} = $c;
+ }
+
+ close PREVIOUS;
+}
+
+my $first_timestamp = 0;
+my $last_timestamp = 0;
+
+
+while (<>)
+{
+ print;
+ chomp;
+ next unless m/terse plugin/;
+
+ my ($timestamp_part, $log_part) = split '`';
+ my ($current_timestamp) = split /\s/, $timestamp_part;
+ $first_timestamp = $current_timestamp unless $first_timestamp;
+ $last_timestamp = $current_timestamp;
+
+ my (@log_items) = split $FS, $log_part;
+ my $disposition = $log_items[5];
+ next unless defined $disposition;
+
+ if ($disp{$disposition})
+ {
+ $disp{$disposition}->{curr} += 1;
+ }
+ else # a new plugin -- make a note of when it first appeared
+ {
+ my $c = { epoch => $current_timestamp, cum => 0, curr => 1 };
+ $disp{$disposition} = $c;
+ }
+}
+
+
+#
+# Set overall epoch
+#
+if (!exists $disp{'LOGFILE_EPOCH'})
+{
+ my $c = { epoch => $first_timestamp, cum => 0, curr => 0};
+ $disp{'LOGFILE_EPOCH'} = $c;
+}
+
+my $current_total = 0;
+my $cumulative_total = 0;
+
+open HOLDOVER, ">&5" and select HOLDOVER;
+
+#
+# Output cumulative values for intake the next time a log is processed
+#
+for my $c (keys %disp)
+{
+ $disp{$c}->{cum} += $disp{$c}->{curr};
+ $current_total += $disp{$c}->{curr};
+ $cumulative_total += $disp{$c}->{cum};
+
+ printf "%-30.30s %s %12d\n", $c, $disp{$c}->{epoch}, $disp{$c}->{cum};
+}
+
+#
+# Output current logfile stats
+#
+
+my $current_elapsed = tai64diff($last_timestamp, $first_timestamp);
+exit 0 if ($current_elapsed == 0);
+
+printf "#
+# Most recent logfile
+# -------------------
+#
+# Start : %s
+# Finish : %s
+# Elapsed: %s
+#
+# Total transactions : %9d
+# Average tx per hour: %9d
+",
+ tai64utc($first_timestamp),
+ tai64utc($last_timestamp),
+ seconds_to_days($current_elapsed),
+ $current_total,
+ $current_total / ($current_elapsed / 3600),
+ ;
+
+#
+# Output cumulative log stats
+#
+my $cumulative_elapsed = tai64diff($last_timestamp, $disp{'LOGFILE_EPOCH'}->{epoch});
+
+printf "#
+# Cumulative Totals
+# -----------------
+#
+# Start : %s
+# Finish : %s
+# Elapsed: %s
+#
+# Total transactions : %12d
+# Average tx per hour: %12d
+",
+ tai64utc($disp{'LOGFILE_EPOCH'}->{epoch}),
+ tai64utc($last_timestamp),
+ seconds_to_days($cumulative_elapsed),
+ $cumulative_total,
+ $cumulative_total / ($cumulative_elapsed / 3600),
+ ;
+
+
+#
+# Output per-plugin stats
+#
+
+print "#
+# Most Recent Logfile Cumulative Totals
+# Disposition (plugin) Total Avg/Day Total Avg/Day
+# ----------------------------------------------------------------------------\n";
+
+my $printf_format = "# %-30.30s %6d %3d%% %8d %10d %3d%% %8d\n";
+
+foreach my $c (sort { $disp{$b}->{curr} <=> $disp{$a}->{curr} } keys %disp)
+{
+ next if ($c eq 'LOGFILE_EPOCH');
+
+ printf $printf_format,
+ $c,
+ $disp{$c}->{curr},
+ $disp{$c}->{curr} / $current_total * 100,
+ $disp{$c}->{curr} / ($current_elapsed / 86400),
+ $disp{$c}->{cum},
+ $disp{$c}->{cum} / $cumulative_total * 100,
+ $disp{$c}->{cum} / (tai64diff($last_timestamp, $disp{$c}->{epoch}) / 86400),
+ ;
+}
+
+print "# ----------------------------------------------------------------------------\n";
+printf $printf_format,
+ 'TOTALS',
+ $current_total,
+ 100,
+ $current_total / ($current_elapsed / 86400),
+ $cumulative_total,
+ 100,
+ $cumulative_total / ($cumulative_elapsed / 86400),
+ ;
+
+exit 0;
+
+
+sub tai64utc {
+ my ($s) = @_;
+
+ # @400000003f6c7bc5253bf98c
+ # 0123456789012345678901234
+ # 0 1 2
+ # |-------------||------|
+ if (substr($s, 0, 2) eq '@4') {
+ my $ts = hex(substr($s, 2, 15));
+ $s = strftime('%Y-%m-%d %H:%M:%S', gmtime($ts));
+ }
+ return $s;
+}
+
+#
+# Return difference in seconds
+#
+sub tai64diff
+{
+ my ($s1, $s2) = @_;
+
+ # @400000003f6c7bc5253bf98c
+ # 0123456789012345678901234
+ # 0 1 2
+ # |-------------||------|
+ if (substr($s1, 0, 2) eq '@4' and substr($s2, 0, 2) eq '@4')
+ {
+ my $ts1 = hex(substr($s1, 2, 15));
+ my $ts2 = hex(substr($s2, 2, 15));
+ return $ts1 - $ts2;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+#
+# Return an english phrase representing a number of seconds
+#
+sub seconds_to_days
+{
+ my ($secs) = @_;
+
+ my $phrase = sprintf "%d days, ", ($secs / 86400);
+ $secs %= 86400;
+ $phrase .= sprintf "%d hours, ", ($secs / 3600);
+ $secs %= 3600;
+ $phrase .= sprintf "%d mins, %d secs", ($secs / 60), ($secs % 60);
+}
diff --git a/root/usr/share/qpsmtpd/plugins/check_smtp_forward b/root/usr/share/qpsmtpd/plugins/check_smtp_forward
new file mode 100644
index 0000000..bbfaa82
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/check_smtp_forward
@@ -0,0 +1,96 @@
+=head1 NAME
+
+check_smtp_forward
+
+=head1 DESCRIPTION
+
+This plugin checks whether SMTP forwarding would be allowed for this
+recipient by connecting to the internal mail server.
+
+If the internal mail server rejects the mail, we DENY it.
+If the internal mail server would accept the mail, we DECLINE.
+If the internal mail server cannot be contacted, we DENYSOFT.
+
+=head1 CONFIG
+
+Reads smtproutes to determine where to send mail for various domains.
+Ignores any default smtproutes entries as they are for upstream mail
+servers (e.g. ISP).
+
+=head1 AUTHOR
+
+Copyright 2006 Gordon Rowell
+
+This software is free software and may be distributed under the same
+terms as qpsmtpd itself.
+
+Based in part on the smtp-forward plugin from the qpsmtpd distribution.
+
+=cut
+
+use Net::SMTP;
+
+sub register {
+ my ($self, $qp, @args) = @_;
+
+ for my $smtp_route ($self->qp->config("smtproutes"))
+ {
+ $smtp_route =~ s/[ \[ \] ]//g;
+ my ($host, $server) = $smtp_route =~ m/(\S+):(\S+)/;
+
+ next unless ($host);
+
+ $self->{_smtp_host}{$host} = $server;
+
+ $self->log(LOGDEBUG, "$host: $server");
+ }
+}
+
+sub hook_rcpt {
+ my ($self, $transaction, $recipient) = @_;
+ my $host = lc $recipient->host;
+
+ my $server = $self->{_smtp_host}{$host} or return (DECLINED);
+ my $port;
+
+ ($server, $port) = split(/:/, $server);
+ $port ||= 25;
+
+ $self->log(LOGDEBUG, "Checking $recipient on $server:$port");
+
+ my $smtp = Net::SMTP->new(
+ $server,
+ Port => $port,
+ Timeout => 60,
+ Hello => $self->qp->config("me"),
+ ) || return (DENYSOFT,
+ "Unable to connect to $server: $!");
+
+ $smtp->mail( $transaction->sender->address || "" );
+ my $rc = $smtp->code;
+ my $message = $smtp->message;
+ chomp($message);
+
+ if ($rc =~ m/^4\d{2}$/ ) {
+ return(DENYSOFT, "Unable to queue message ($message)");
+ } elsif ($rc =~ m/^5\d{2}$/ ) {
+ return(DENY, "Unable to queue message ($message)");
+ }
+
+ $smtp->to($recipient->address);
+ $rc = $smtp->code;
+ $message = $smtp->message;
+ chomp($message);
+
+ if ($rc =~ m/^4\d{2}$/ ) {
+ return(DENYSOFT, "Unable to queue message ($message)");
+ } elsif ($rc =~ m/^5\d{2}$/ ) {
+ return(DENY, "Unable to queue message ($message)");
+ }
+
+ $smtp->quit();
+ $rc = $smtp->code;
+
+ $self->log(LOGDEBUG, "$server would accept message to $recipient");
+ return DECLINED; # Internal mail server is happy
+}
diff --git a/root/usr/share/qpsmtpd/plugins/disclaimer b/root/usr/share/qpsmtpd/plugins/disclaimer
new file mode 100644
index 0000000..5d9d500
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/disclaimer
@@ -0,0 +1,124 @@
+use MIME::Parser;
+use MIME::Entity;
+
+sub register {
+ my ($self, $qp, @args) = @_;
+
+ $self->log(LOGERROR, "Bad parameters for the disclaimer plugin")
+ if @_ % 2;
+
+ %{$self->{_args}} = @args;
+}
+
+sub read_disclaimer {
+ my ($self, $disclaimer_file) = @_;
+ my $disclaimer_dir = $self->{_args}->{disclaimer_dir} || "/service/qpsmtpd/config/";
+ return () unless open DISCLAIMER, "<$disclaimer_dir/$disclaimer_file";
+ my @lines = ;
+ chomp @lines;
+ close DISCLAIMER;
+ return @lines;
+}
+
+sub hook_data_post {
+ my ($self, $transaction) = @_;
+
+ if ( $transaction->header->get('X-Qpsmtp-Disclaimer') ) {
+ $self->log(LOGNOTICE, "Message already has disclaimer attached");
+ return DECLINED;
+ }
+
+ $self->qp->version =~ m/([\.\d]+).*/;
+ my $versionnum = $1;
+
+ my @rcpt_hosts = ($self->qp->config("me"), $self->qp->config("rcpthosts"));
+ my $fromhost = $transaction->sender->host;
+ unless ( $self->{_args}->{tag_all} ) {
+ my $fromlocal = 0;
+
+ for my $allowed (@rcpt_hosts) {
+ $allowed =~ s/^\s*(\S+)/$1/;
+ ($fromlocal = 1, last) if (($fromhost eq lc $allowed) or (substr($allowed,0,1) eq "." and
+ $fromhost =~ m/\Q$allowed\E$/i));
+ }
+
+ if (($versionnum >= 0.26) and ($fromlocal == 0)) {
+ my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
+ $fromlocal = 1 if exists $more_rcpt_hosts->{$fromhost};
+ }
+
+ unless ($fromlocal) {
+ $self->log(LOGDEBUG, "Not from local domain");
+ return DECLINED;
+ }
+ }
+
+ my $specific = 0;
+ my @lines;
+ if ( @lines = $self->read_disclaimer("disclaimer_$fromhost") ) {
+ $self->log(LOGDEBUG, "Found disclaimer for domain: $fromhost");
+ $specific = 1;
+ } elsif ( @lines = $self->read_disclaimer("disclaimer") ) {
+ $self->log(LOGDEBUG, "Found general disclaimer");
+ } else {
+ $self->log(LOGERROR, "No disclaimer found for domain: $fromhost");
+ return DECLINED;
+ }
+
+ unless ( $self->{_args}->{tag_all} ) {
+ my $toexternal=0;
+ foreach my $rcpt ( $transaction->recipients ) {
+ my $local = 0;
+ my $host = $rcpt->host;
+
+ ($toexternal = 1, last) if ( $specific && $host ne $fromhost);
+
+ for my $allowed (@rcpt_hosts) {
+ $allowed =~ s/^\s*(\S+)/$1/;
+ ($local = 1, last) if (($host eq lc $allowed) or (substr($allowed,0,1) eq "." and
+ $host =~ m/\Q$allowed\E$/i));
+ }
+
+ if (($versionnum >= 0.26) and ($local == 0)) {
+ my $more_rcpt_hosts = $self->qp->config('morercpthosts', 'map');
+ $local = 1 if exists $more_rcpt_hosts->{$host};
+ }
+
+ ($toexternal = 1, last) unless $local;
+ }
+
+ unless ($toexternal) {
+ $self->log(LOGDEBUG, "Not to any external domain");
+ return DECLINED;
+ }
+ }
+
+ my $parser = new MIME::Parser;
+ $parser->output_under( $self->spool_dir() );
+ $parser->extract_uuencode(1);
+ my $ent = $parser->parse_open( $transaction->body_filename() );
+
+ $ent->make_multipart( 'mixed', Force => 1 ) if $ent->mime_type ne 'multipart/mixed';
+ $ent->attach( Data => join("\n", @lines),
+ Encoding => $self->{_args}->{mime_encoding} || '-SUGGEST',
+ Filename => $self->{_args}->{mime_filename} || 'disclaimer.txt',
+ Type => $self->{_args}->{mime_type} || 'text/plain');
+ if ($ent->parts <= 2) {
+ $transaction->header->empty();
+ $transaction->header($ent->head());
+ }
+ $transaction->header->replace( 'X-Qpsmtp-Disclaimer', $fromhost );
+ $self->log(LOGNOTICE, "Attached disclaimer for domain: $fromhost");
+
+ open BFN, ">" . $transaction->body_filename();
+ $ent->print(\*BFN);
+ close BFN;
+ $transaction->body_resetpos();
+
+ $ent->purge();
+ rmdir( $parser->output_dir );
+
+ return DECLINED;
+}
+
+# vi: ft=perl ts=4
diff --git a/root/usr/share/qpsmtpd/plugins/dkim_sign b/root/usr/share/qpsmtpd/plugins/dkim_sign
new file mode 100644
index 0000000..9728fa7
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/dkim_sign
@@ -0,0 +1,77 @@
+=head1 NAME
+
+dkim_sigh: attach a DKIM or DomainKeys signature to incoming mail before it is queued.
+Currently we sign all authenticated and allowed relay email.
+
+written by Shad L. Lords
+
+=cut
+
+require Mail::DKIM::Signer;
+require Mail::DKIM::DkSignature;
+
+sub register {
+ my ($self, $qp, @args) = @_;
+ %{$self->{_dkim}} = @args;
+}
+
+sub hook_data_post {
+ my $self = shift;
+ my $trns = shift;
+
+ return DECLINED unless $self->qp->connection->relay_client() || ( $self->qp->auth_mechanism() && $self->qp->auth_user() );
+
+ my $sender = (Qpsmtpd::Address->parse($trns->sender))[0];
+ return DECLINED unless $sender;
+
+ my $dkim = new Mail::DKIM::Signer(
+ Policy => sub {
+ my $dkim = shift;
+
+ my $headers = $self->{_dkim}->{dkim_headers} || "received:from:subject:date:message-id";
+ $headers = $dkim->headers if $headers eq 'all';
+
+ my $keys = $self->{_dkim}->{keys} || 'both';
+
+ $dkim->add_signature(new Mail::DKIM::DkSignature(
+ Algorithm => $self->{_dkim}->{algorithm} || "rsa-sha1",
+ Method => $self->{_dkim}->{dk_method} || "nofws",
+ Selector => $self->{_dkim}->{selector} || "default",
+ Domain => $dkim->message_sender->host,
+ Headers => $headers,
+ )) if $keys eq 'both' || $keys eq 'dk' || $keys eq 'domainkeys';
+
+ $dkim->add_signature(new Mail::DKIM::Signature(
+ Algorithm => $self->{_dkim}->{algorithm} || "rsa-sha1",
+ Method => $self->{_dkim}->{dkim_method} || "relaxed",
+ Selector => $self->{_dkim}->{selector} || "default",
+ Domain => $dkim->message_sender->host,
+ Headers => $headers,
+ )) if $keys eq 'both' || $keys eq 'dkim';
+
+ return 1;
+ },
+ KeyFile => "config/dkimkeys/".$sender->host.".private"
+ );
+ return DECLINED unless $dkim;
+
+ $trns->body_resetpos;
+ foreach my $line (split /\n/, $trns->header->as_string) {
+ chomp $line;
+ $dkim->PRINT("$line\015\012");
+ }
+ while (my $line = $trns->body_getline) {
+ chomp $line;
+ $dkim->PRINT("$line\015\012");
+ }
+ $dkim->CLOSE;
+
+ foreach my $sig ($dkim->signatures) {
+ if ( (my $sig_string = $sig->as_string) =~ /^([^:]+):\s*(.*)$/) {
+ $self->log(LOGINFO, "Added $1 for domain ".$sender->host);
+ $trns->header->add("$1:", $2, 0);
+ }
+ }
+
+ return DECLINED;
+}
diff --git a/root/usr/share/qpsmtpd/plugins/forcespamcheck b/root/usr/share/qpsmtpd/plugins/forcespamcheck
new file mode 100644
index 0000000..753d3f9
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/forcespamcheck
@@ -0,0 +1,61 @@
+#!perl -w
+=head1 NAME
+
+forcespamcheck - SpamAssassin integration for qpsmtpd
+
+=head1 DESCRIPTION
+
+Plugin that forces check if the mail is spam by using the "spamd" daemon
+from the SpamAssassin package. F
+
+=head1 CONFIG
+This plugins needs spamassassin like arguments
+Refer to spamassassin plugin
+
+On top of that it uses a config file with an ip per line corresponding of
+local_ip of the qpsmtpd server on which the remote client is trying to deliver
+the mail. Please be cautious this is not the remote client ip !
+THe initial idea is to force spam check for some deamons by making them
+sending to 127.0.0.200:25 so other daemons trying to deliver on 127.0.0.1:25
+or LAN client delivering on 192.168.0.1:25 will avoid the spam check, unless you
+also specify those ips in forcespamcheck file.
+
+=cut
+
+use strict;
+use warnings;
+use Qpsmtpd::Constants;
+use Qpsmtpd::DSN;
+use Socket qw(:DEFAULT :crlf);
+use IO::Handle;
+
+sub register {
+ my ($self, $qp, %args) = @_;
+ $self->log(LOGERROR, "Bad parameters for the forcespamcheck plugin")
+ if @_ % 2;
+ #first if spamassassin already loaded return DECLINED; not to load it twice
+ my @datahooked = $qp->hooks('data_post');
+ for my $item (@datahooked) {
+ $self->log(LOGNOTICE,"spamassassin aleady loaded") if $item->{name} eq "spamassassin";
+ return DECLINED if $item->{name} eq "spamassassin";
+ }
+ # else we can go on
+ my $param = join(q{ }, map{qq{$_ $args{$_}}} keys %args);
+ my $ip = $self->qp->connection->local_ip;
+ # read here list of ip from file; or default on 127.0.0.200
+ my %forcespamcheck = map { $_ => 1 } $self->qp->config('forcespamcheck');
+ # we force spamcheck on 127.0.0.200 as used by fetchmail
+ $forcespamcheck{'127.0.0.200'} = 1;
+ return DECLINED unless (exists $forcespamcheck{$ip});
+ my $plugin_line = "spamassassin " . $param;
+ my $this_plugin = $self->qp->_load_plugin($plugin_line, $self->qp->plugin_dirs);
+ $self->register_hook('data', 'data_handler');
+}
+
+sub data_handler {
+ my ($self, $transaction) = @_;
+ my $ip = $self->qp->connection->local_ip;
+ # logged only there to avoid double line in log in register.
+ $self->log(LOGINFO,
+ "forcing spamassassin check for connection on $ip");
+}
diff --git a/root/usr/share/qpsmtpd/plugins/logging/logterse b/root/usr/share/qpsmtpd/plugins/logging/logterse
new file mode 100644
index 0000000..90d0006
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/logging/logterse
@@ -0,0 +1,172 @@
+=pod
+
+=head1 SYNOPSIS
+
+logterse [prefix char] [loglevel level]
+
+This plugin is not a logging replacement, but rather an adjunct to the normal logging
+plugins or builtin logging functionality. Specify it in config/plugins not
+config/logging or you'll get "interesting" results.
+
+The idea is to produce a one-line log entry that summarises the outcome of a
+transaction. A message is either queued or rejected (bizarre failure modes are
+not of interest). What is of interest is the details of the sending host and the
+message envelope, and what happened to the message. To do this we hook_deny and
+hook_queue and grab as much info as we can.
+
+This info is then passed to the real logging subsystem as a single line with
+colon-separated fields as follows:
+
+=over 4
+
+=item 1. remote ip
+
+=item 2. remote hostname
+
+=item 3. helo host
+
+=item 4. envelope sender
+
+=item 5. recipient (comma-separated list if more than one)
+
+=item 6. name of plugin that called DENY, or the string 'queued' if message was accepted.
+
+=item 7. return value of DENY plugin (empty if message was queued).
+
+=item 8. the DENY message, or the message-id if it was queued.
+
+=item 9. details of spammassassin scores if messaged was accepted or denied due to score requiring rejection
+ or 'msg denied before queued' if other rejections occur.
+
+
+=back
+
+As with logging/adaptive, a distinctive prefix (the backquote character by default) is
+used to make it easy to extract the lines from the main logfiles, or to take advantage
+of multilog's selection capability as described in the logging/adaptive plugin:
+
+=head1 TYPICAL USAGE
+
+If you are using multilog to handle your logging, you can replace the system
+provided log/run file with something like this:
+
+ #! /bin/sh
+ export LOGDIR=./main
+
+ exec multilog t n10 \
+ $LOGDIR \
+ '-*' '+*` *' $LOGDIR/summary
+
+which will have the following effects:
+
+=over 4
+
+=item 1. All lines will be logged in ./main as usual.
+
+=item 2. ./main/summary will contain only the lines output by this plugin.
+
+=back
+
+
+=head1 AUTHORS
+
+Written by Charles Butcher who took a lot from logging/adaptive by John Peacock.
+
+Added to by Brian Read (March 2007) to add in the spamassassin scores.
+
+=head1 VERSION
+
+This is release 1.1
+
+=cut
+
+#
+# I chose tab as the field separator to help with human-readability of the logs and hopefully minimal
+# chance of a tab showing up _inside_ a field (although they are converted if they do).
+# If you change it here, remember to change it in qplogsumm.pl as well.
+#
+my $FS = "\t";
+#my $FS = "\&";
+
+sub register {
+ my ( $self, $qp, %args ) = @_;
+
+ $self->{_prefix} = '`';
+ if ( defined $args{prefix} and $args{prefix} =~ /^(.+)$/ ) {
+ $self->{_prefix} = $1;
+ }
+
+ $self->{_loglevel} = LOGALERT;
+ if ( defined( $args{loglevel} ) ) {
+ if ( $args{loglevel} =~ /^\d+$/ ) {
+ $self->{_loglevel} = $args{loglevel};
+ }
+ else {
+ $self->{_loglevel} = log_level( $args{loglevel} );
+ }
+ }
+}
+
+
+sub hook_deny {
+ my ( $self, $transaction, $prev_hook, $retval, $return_text ) = @_;
+
+ my $disposition = join($FS,
+ $prev_hook,
+ $retval,
+ $return_text,
+ );
+
+ $self->_log_terse($transaction, $disposition);
+ return DECLINED;
+}
+
+sub hook_queue {
+ my ( $self, $transaction ) = @_;
+
+ my $msg_id = $transaction->header->get('Message-Id') || '';
+ $msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
+ $msg_id = "<$msg_id>" unless $msg_id =~ /^<.*>$/; # surround in <>'s
+ my $disposition = "queued$FS$FS$msg_id";
+
+ $self->_log_terse($transaction, $disposition);
+ return DECLINED;
+}
+
+sub _log_terse {
+ my ( $self, $transaction, $disposition ) = @_;
+
+ my $recipients = join(',', $transaction->recipients);
+
+ my $remote_ip = $self->qp->connection->remote_ip() || '';
+ my $remote_host = $self->qp->connection->remote_host() || '';
+ my $hello_host = $self->qp->connection->hello_host() || '';
+ my $tx_sender = $transaction->sender() || '';
+ my $spamscore = 'msg denied before queued';
+ if (substr($disposition,0,6) =~ 'queued|spamas') {
+ $spamscore = $transaction->header->get('X-Spam-Status') || '';
+ # just pull out scores
+ $spamscore = substr($spamscore,0,index($spamscore,'tests')-1);
+ map(s/\n/_/g,$spamscore)
+ }
+
+ my @log_message;
+
+ push(@log_message,
+ $remote_ip,
+ $remote_host,
+ $hello_host,
+ $tx_sender,
+ $recipients
+ );
+
+ #
+ # Escape any $FS characters anywhere in the log message
+ #
+ map {s/$FS/_/g} @log_message;
+
+ push(@log_message, $disposition);
+ push(@log_message, $spamscore);
+
+ $self->log($self->{_loglevel}, $self->{_prefix}, join($FS, @log_message));
+}
diff --git a/root/usr/share/qpsmtpd/plugins/peers b/root/usr/share/qpsmtpd/plugins/peers
new file mode 100644
index 0000000..5a56166
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/peers
@@ -0,0 +1,120 @@
+# this plugin checks the peers directory for config
+# file most closely matching the client IP address
+# and loads it if found.
+#
+# Note that init() borrows some internals from Qpsmtpd.pm - I
+# didn't see a suitable public interface.
+
+sub init {
+ my $self = shift;
+ my $qp = shift;
+ my $plugins_list_file = shift || 'peers/0';
+ my @plugins = $qp->config($plugins_list_file);
+ my @plugin_dirs = $qp->plugin_dirs;
+
+ for my $plugin_line (@plugins) {
+ my ($plugin, @args) = split ' ', $plugin_line;
+
+ my $package;
+
+ if ($plugin =~ m/::/) {
+ # "full" package plugin (My::Plugin)
+ $package = $plugin;
+ $package =~ s/[^_a-z0-9:]+//gi;
+ my $eval = qq[require $package;\n]
+ .qq[sub ${plugin}::plugin_name { '$plugin' }];
+ $eval =~ m/(.*)/s;
+ $eval = $1;
+ eval $eval;
+ die "Failed loading $package - eval $@" if $@;
+ $self->log(LOGDEBUG, "Loading $package ($plugin_line)")
+ unless $plugin_line =~ /logging/;
+ }
+ else {
+ # regular plugins/$plugin plugin
+ my $plugin_name = $plugin;
+ $plugin =~ s/:\d+$//; # after this point, only used for filename
+
+ # Escape everything into valid perl identifiers
+ $plugin_name =~ s/([^A-Za-z0-9_\/])/sprintf("_%2x",unpack("C",$1))/eg;
+
+ # second pass cares for slashes and words starting with a digit
+ $plugin_name =~ s{
+ (/+) # directory
+ (\d?) # package's first character
+ }[
+ "::" . (length $2 ? sprintf("_%2x",unpack("C",$2)) : "")
+ ]egx;
+
+ $package = "Qpsmtpd::Plugin::$plugin_name";
+
+ # don't reload plugins if they are already loaded
+ unless ( defined &{"${package}::plugin_name"} ) {
+ PLUGIN_DIR: for my $dir (@plugin_dirs) {
+ if (-e "$dir/$plugin") {
+ Qpsmtpd::Plugin->compile($plugin_name, $package,
+ "$dir/$plugin", $self->{_test_mode}, $plugin);
+ Qpsmtpd->varlog(LOGDEBUG, "init", "peers", "Loading $plugin_line from $dir/$plugin")
+ unless $plugin_line =~ /logging/;
+ last PLUGIN_DIR;
+ }
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+sub _peer_plugins {
+ my $qp = shift;
+ my $hook = shift;
+ my $config = shift;
+
+ my $hooks;
+ $hooks->{$_} = delete $qp->hooks->{$_} foreach keys %{$qp->hooks};
+
+ my @plugins = $qp->config($config);
+ unshift @plugins, "peers $config";
+ my @loaded;
+
+ for my $plugin_line (@plugins) {
+ my $this_plugin = $qp->_load_plugin($plugin_line, $qp->plugin_dirs);
+ push @loaded, $this_plugin if $this_plugin;
+ }
+
+ if ($hook eq 'set_hooks') {
+ foreach my $c (@{$hooks->{connect}}) {
+ unshift @{$qp->hooks->{connect}}, $c unless grep { $c->{name} eq $_->{name} } @{$hooks->{connect}};
+ }
+ }
+
+ return @loaded;
+}
+
+sub hook_set_hooks {
+ my ($self, $transaction) = @_;
+ my $qp = $self->qp;
+ my $connection = $qp->connection;
+
+ my $client_ip = $qp->connection->remote_ip;
+ while ($client_ip) {
+ if (-f "config/peers/$client_ip") {
+ _peer_plugins($qp, "set_hooks", "peers/$client_ip");
+ return (DECLINED);
+ }
+ $client_ip =~ s/\.?\d+$//; # strip off another 8 bits
+ }
+ if (-f "config/peers/0") {
+ _peer_plugins($qp, "set_hooks", "peers/0");
+ return (DECLINED);
+ }
+ return (DENY);
+}
+
+sub hook_valid_auth {
+ my ( $self, $transaction) = @_;
+ my $qp = $self->qp;
+ _peer_plugins($qp, "valid_auth", "peers/local") if (-f "config/peers/local");
+ return (DECLINED);
+}
diff --git a/root/usr/share/qpsmtpd/plugins/tnef2mime b/root/usr/share/qpsmtpd/plugins/tnef2mime
new file mode 100644
index 0000000..3799e5a
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/tnef2mime
@@ -0,0 +1,237 @@
+#!/usr/bin/perl -w
+=head1 NAME
+
+tnef2mime
+
+=head1 DESCRIPTION
+
+Plugin that converts ms-tnef attachments (winmail.dat) and uuencoded attachments to MIME.
+
+perl-Convert-TNEF, perl-IO-stringy, perl-File-MMagic and perl-MIME-tools are required.
+
+=head1 AUTHOR
+
+Michael Weinberger, neddix Stuttgart, 2005
+
+=head1 LICENSE
+
+GNU GPL (GNU General Public License)
+
+
+=cut
+use MIME::Parser;
+{
+# this is a dirty fix regarding this bug https://rt.cpan.org/Ticket/Display.html?id=97886
+# this way we can keep on usinhg this plugin waiting for the upstream fix
+# the no warnings avoid message in qpsmtpd log on every mails saying we override the sub.
+no warnings;
+*MIME::Parser::Filer::output_path = sub {
+ my ($self, $head) = @_;
+
+ ### Get the output directory:
+ my $dir = $self->output_dir($head);
+
+ ### Get the output filename as UTF-8
+ my $fname = $head->recommended_filename;
+
+ ### Can we use it:
+ if (!defined($fname)) {
+ $self->debug("no filename recommended: synthesizing our own");
+ $fname = $self->output_filename($head);
+ }
+ elsif ($self->ignore_filename) {
+ $self->debug("ignoring all external filenames: synthesizing our own");
+ $fname = $self->output_filename($head);
+ }
+ elsif ($self->evil_filename($fname)) {
+
+ ### Can we save it by just taking the last element?
+ my $ex = $self->exorcise_filename($fname);
+ if (defined($ex) and !$self->evil_filename($ex)) {
+ $self->whine("Provided filename '$fname' is regarded as evil, ",
+ "but I was able to exorcise it and get something ",
+ "usable.");
+ $fname = $ex;
+ }
+ else {
+ $self->whine("Provided filename '$fname' is regarded as evil; ",
+ "I'm ignoring it and supplying my own.");
+ $fname = $self->output_filename($head);
+ }
+ }
+ $self->debug("planning to use '$fname'");
+
+ #untaint dir and fname
+ $self->debug("it is our own");
+ $fname = ($fname =~ m/^([ \w_.:%-]+)$/ig) ? $1 : $self->output_filename($head);
+ ### Resolve collisions and return final path:
+ return $self->find_unused_path($dir, $fname);
+};
+}
+
+use MIME::Entity;
+use MIME::Head;
+use File::MMagic;
+use Convert::TNEF;
+
+my $parser;
+my $ent;
+my $tmpdir='/var/spool/qpsmtpd';
+my $count=0;
+my $foundtnef=0;
+my (@attachments, @blocked, @tnefs);
+
+
+sub register {
+ my ($self, $qp, %arg) = @_;
+ $self->register_hook("data_post", "tnef2mime");
+}
+
+sub hasMessageClassProperty {
+ my $self = shift;
+ my $data = $self->data("Attachment");
+ return 0 unless $data;
+ return index( $data, pack( "H*", "8008" ) ) >= 0;
+}
+
+# for future use
+sub kill_part ($)
+ {
+ my $part=$_;
+ #my $path = defined $part->bodyhandle ? $part->bodyhandle->path : "";
+ #my $filename = $part->head->recommended_filename || "";
+ return $part;
+ }
+
+sub keep_part ($$)
+ {
+ my ($self,$part)=@_;
+ my $mm = new File::MMagic;
+
+ # when a ms-tnef attachment was sent uuencoded, its MIME type becomes application/octet-stream
+ # after the conversion. Therefore all application/octet-stream attachments are assumed to
+ # be a ms-tnef
+
+ my $path = $part->bodyhandle ? $part->bodyhandle->path : "";
+
+ if( $part->mime_type =~ /ms-tnef/i || $part->mime_type =~ /application\/octet-stream/i )
+ {
+ # convert tnef attachments and write to files
+ my $tnef = Convert::TNEF->read_ent($part,{output_dir=>$tmpdir,output_to_core=>"NONE"});
+
+ # if $tnef is undefined here, the application/octet-stream was not a ms-tnef and we are done.
+ return 1 if( ! defined $tnef );
+
+ my $keep_tnef=0;
+ for ($tnef->attachments)
+ {
+ next if !defined $_->datahandle;
+
+ if( hasMessageClassProperty($_) ) # Outlook MAPI object
+ {
+ $keep_tnef++;
+ $self->log(LOGWARN, sprintf "Outlook MAPI object #%i: %s", $keep_tnef, $_->longname);
+ next;
+ }
+
+ my $mimetype = $mm->checktype_filename( $_->datahandle->path );
+ $attachments[$count] = MIME::Entity->build(
+ Path=>$_->datahandle->path,
+ Filename=>$_->longname,
+ Encoding=>"base64",
+ Type=>$mimetype );
+ $self->log(LOGWARN,
+ sprintf "File attachment #%i: %s (%s, %ld bytes)", $count+1, $_->longname, $mimetype, $_->size );
+ $count++;
+ }
+
+ if( $keep_tnef )
+ {
+ $attachments[$count++] = $part;
+ $self->log(LOGWARN, "Original TNEF file attached." );
+ }
+
+ push( @tnefs, $tnef ); # remind for cleanup
+ $foundtnef=1;
+ return 0;
+ }
+ return 1;
+ }
+
+
+sub tnef2mime ( $$ )
+ {
+ my ($self, $transaction) = @_;
+ # new Parser Object
+ $parser = new MIME::Parser;
+ # if you want to debug the Parser :
+ #use MIME::Tools; MIME::Tools->debugging(1);
+ # temp output directory
+ $parser->output_under( $tmpdir );
+ $parser->extract_uuencode(1);
+
+ #untainted filename
+ $transaction->body_filename() =~ /^([:\-\/\w]+)\z/ or die "Disallowed characters in filename ".$transaction->body_filename();
+ my $bdfilename = $1;
+ # read message body
+ open BFN, "<", $bdfilename ;#$transaction->body_filename();
+ $ent = $parser->parse(\*BFN);
+ my @keep = grep { keep_part($self, $_) } $ent->parts; # @keep now holds all non-tnef attachments
+ close BFN;
+
+ my $founduu = $ent->parts && !$transaction->header->get('MIME-Version');
+
+ if( $foundtnef || $founduu )
+ {
+ my @allatt;
+ @allatt = map { kill_part($_) } ( @keep, @attachments );
+ $ent->parts(\@allatt);
+ # if message is a multipart type, but has MIME version tag, then add
+ # MIME version. PHP imap_fetchstructure() depends on that!
+ my $xac;
+ if( $founduu )
+ {
+ $transaction->header->add('MIME-Version', "1.0" );
+ $xac = "UUENCODE -> MIME";
+ $self->log(LOGDEBUG, "uuencoded attachment converted to MIME" );
+ }
+ # delete the X-MS-TNEF-Correlator header line
+ if( $foundtnef )
+ {
+ $xac .= ( defined $xac ? ", " : "" ) . "MS-TNEF -> MIME";
+ $transaction->header->delete('X-MS-TNEF-Correlator' );
+ }
+ # add own X header
+ if( defined $xac )
+ {
+ $transaction->header->add('X-TNEF2MIME-Plugin', $xac );
+ }
+ # write converted message body
+ open BFN, ">" , $bdfilename;#$transaction->body_filename();
+ $ent->print(\*BFN);
+ close BFN;
+ }
+
+ # cleaning up
+ for( my $i=0; $i<@tnefs; $i++ )
+ {
+ $tnefs[$i]->purge();
+ }
+
+ #untainted filename
+ $parser->output_dir =~ /^([:\-\/\w]+)\z/ or die "Disallowed characters in output dir ".$parser->output_dir;
+ my $output_dir = $1;
+
+ opendir( DIR, $output_dir ) or die "Could not open temporary output dir $output_dir: $!\n";
+ while( defined( my $file = readdir( DIR ) ) )
+ {
+ next if $file =~ /^\.\.?$/;
+ $file =~ s/(^.*$)//;
+ $file = $1;
+ unlink( "$output_dir/$file" );
+ }
+ closedir( DIR );
+ rmdir( $output_dir );
+
+ return DECLINED;
+ }
diff --git a/root/usr/share/qpsmtpd/plugins/virus/pattern_filter b/root/usr/share/qpsmtpd/plugins/virus/pattern_filter
new file mode 100644
index 0000000..23da718
--- /dev/null
+++ b/root/usr/share/qpsmtpd/plugins/virus/pattern_filter
@@ -0,0 +1,186 @@
+=head1 NAME
+
+pattern_filter
+
+=head1 DESCRIPTION
+
+pattern_filter blocks executable (and other) attachments by matching
+each line in a message against a set of known signatures. If a match is
+found, the email is denied.
+
+Signatures are stored one per line in signature files in the qpsmtpd
+config directory. pattern_filter currently supports
+'signature_exe' and 'signature_zip' files.
+
+This version is heavily based on Gavin Carr's exe_filter, but implemented
+so as not to care about MIME boundaries. This traps mangled MIME mail
+which is still interpreted by some mail clients. However, bare lines
+which happen to contain the pattern will match.
+
+This approach has the added advantage of reading the spool file directly,
+rather than reassembling the message in memory for Email::MIME to parse.
+
+=head1 CONFIG
+
+The following parameters can be passed to pattern_filter, or set in a
+'pattern_filter' config file.
+
+=over 4
+
+=item check
+
+where is a comma-separated list of suffixes to check e.g.
+
+ check exe,zip
+
+A corresponding 'signature_' file should exist for each supplied
+suffix.
+
+Default: 'check patterns'.
+
+Note: this argument used to be called 'deny', which is now deprecated but
+still functional.
+
+=item action
+
+The action to take when a signature match is found. Valid values are 'deny'
+(the default), to DENY the mail, and 'note', to record a transaction note
+for some later plugin (and then DECLINE). If action is 'note', the default
+note name is 'virus_score', with a default value of 1. These defaults can
+be modified using an extended note syntax - 'note:NAME=VALUE' e.g.
+
+ action note:virus_score=1 # default settings
+ action note:pattern_filter=virus_found # random example
+
+Numeric note values are accumulated, not replaced.
+
+Default: 'action deny'.
+
+=back
+
+The following parameter can be passed to pattern_filter in
+config/plugins (but not set via a config file):
+
+=over 4
+
+=item per_recipient 1
+
+Allow per-recipient configs to be used (using the per_user_config plugin).
+Default: 0.
+
+=back
+
+
+=head1 BUGS AND LIMITATIONS
+
+pattern_filter is a simple pattern - it does not unpack and scan
+archives for executables like a full-blown virus scanner. Likewise, zip
+filtering blocks *all* zip files, not just those that contain a virus. You
+should use a proper virus scanner if that's what you need.
+
+Because pattern_filter is a post_data plugin, it cannot handle different
+configurations in per_recipient mode. This means that if you want to use
+per_recipient configurations, you should also enforce that only compatible
+recipients occur in a single mail (e.g. using a plugin like
+denysoft_multi_rcpt).
+
+=head1 AUTHOR
+
+Written by Gordon Rowell , heavily based on
+the following:
+
+Written by Gavin Carr , inspired by Russ Nelson's
+viruscan patch to qmail-smtpd
+(http://www.qmail.org/qmail-smtpd-viruscan-1.2.patch).
+
+=head1 COPYRIGHT
+
+Copyright 2005 Gordon Rowell
+Copyright 2004 Gavin Carr
+
+Copyright 2005 Gordon Rowell
+
+This software is free software and may be distributed under the same
+terms as Perl itself.
+
+=cut
+
+# use Email::MIME;
+
+#my $VERSION = 0.04;
+my $VERSION = 0.01;
+my %DEFAULTS = ( deny => 'patterns', action => 'deny', per_recipient => 0 );
+
+sub register {
+ my ($self, $qp, %arg) = @_;
+ $self->{_config_defaults} = { %DEFAULTS, %arg };
+ $self->register_hook("rcpt", "setup_config") if $arg{per_recipient};
+ $self->register_hook("data_post", "pattern_filter");
+}
+
+sub setup_config {
+ my ($self, $transaction, $rcpt) = @_;
+
+ # Setup only once
+ return DECLINED if $self->{_config};
+ return DECLINED
+ unless ref $self->{_config_defaults} eq 'HASH';
+
+ # Setup config from defaults and per_recipient pattern_filter config
+ my @config = $self->qp->config('pattern_filter', { rcpt => $rcpt });
+ $self->{_config} = {
+ %{$self->{_config_defaults}},
+ rcpt => $rcpt,
+ @config ? map { split /\s+/, $_, 2 } @config : ()
+ };
+ return DECLINED;
+}
+
+sub pattern_filter {
+ my ($self, $transaction) = @_;
+
+ # Setup config parameters if not already done
+ my $config = $self->{_config};
+ unless ($config) {
+ my @config = $self->qp->config('pattern_filter');
+ $config = {
+ %{$self->{_config_defaults}},
+ @config ? map { split /\s+/, $_, 2 } @config : ()
+ };
+ };
+ $config->{check} ||= $config->{deny};
+ return DECLINED unless $config->{check};
+
+ # Load signatures
+ my @signatures = ();
+ my $config_arg = $config->{rcpt} ? { rcpt => $config->{rcpt} } : {};
+ for my $suffix (split /\s*,\s*/, $config->{check}) {
+ my @sig = $self->qp->config("signatures_$suffix", $config_arg);
+ $self->log(3, "warning - no signatures_$suffix loaded") unless @sig;
+ push @signatures, @sig if @sig;
+ }
+ return DECLINED unless @signatures;
+
+ my $patterns = join("|", @signatures);
+ my $pat = qr{ ^($patterns) }xmso;
+
+ $transaction->body_resetpos;
+
+ my ($status,$msg);
+
+ while ($_ = $transaction->body_getline)
+ {
+ if ( $_ =~ m{$pat} )
+ {
+ my $match = $1;
+
+ $self->log(6, "the following line matched '$match':\n$_");
+ return (DENY, "We don't accept email with executable content [$match].");
+ }
+ }
+
+ return DECLINED;
+
+}
+
+# arch-tag: 3fc272f2-9d52-42d4-893b-032b529ec71d
diff --git a/root/var/log/qpsmtpd/.gitignore b/root/var/log/qpsmtpd/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/log/sqpsmtpd/.gitignore b/root/var/log/sqpsmtpd/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/config/peers/.gitignore b/root/var/service/qpsmtpd/config/peers/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/config/plugins b/root/var/service/qpsmtpd/config/plugins
new file mode 100644
index 0000000..7cf773d
--- /dev/null
+++ b/root/var/service/qpsmtpd/config/plugins
@@ -0,0 +1,8 @@
+#------------------------------------------------------------
+# !!DO NOT MODIFY THIS FILE!!
+#
+# Plugins are now loaded by the peers plugin from config/peers/*
+#------------------------------------------------------------
+hosts_allow
+peers
+tls ssl/cert.pem ssl/cert.pem ssl/cert.pem ssl/dhparam.pem
diff --git a/root/var/service/qpsmtpd/config/spool_perms b/root/var/service/qpsmtpd/config/spool_perms
new file mode 100644
index 0000000..72fee26
--- /dev/null
+++ b/root/var/service/qpsmtpd/config/spool_perms
@@ -0,0 +1 @@
+2750
diff --git a/root/var/service/qpsmtpd/control/1 b/root/var/service/qpsmtpd/control/1
new file mode 100644
index 0000000..7226b4b
--- /dev/null
+++ b/root/var/service/qpsmtpd/control/1
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+#----------------------------------------------------------------------
+# copyright (C) 2005 Mitel Networks Corporation
+# Copyright (C) 2006 Gordon Rowell
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#----------------------------------------------------------------------
+
+use esmith::tcpsvd;
+
+esmith::tcpsvd::configure_peers('qpsmtpd');
+esmith::tcpsvd::configure_peers('qpsmtpd', '/var/service/qpsmtpd/config/peers');
+
+exit(0);
diff --git a/root/var/service/qpsmtpd/down b/root/var/service/qpsmtpd/down
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/env/.gitignore b/root/var/service/qpsmtpd/env/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/log/run b/root/var/service/qpsmtpd/log/run
new file mode 100755
index 0000000..2ca34df
--- /dev/null
+++ b/root/var/service/qpsmtpd/log/run
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+#----------------------------------------------------------------------
+# copyright (C) 2001 e-smith, inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Technical support for this program is available from e-smith, inc.
+# Please visit our web site www.e-smith.com for details.
+#----------------------------------------------------------------------
+
+status=`/sbin/e-smith/config getprop qpsmtpd qplogsumm`
+num=`/sbin/e-smith/config getprop qpsmtpd KeepLogFiles`
+
+if [ -z $status ]; then
+ status="disabled"
+fi
+
+if [ $status = "enabled" ]; then
+ exec \
+ /usr/local/bin/setuidgid smelog \
+ /usr/local/bin/multilog t s5000000 \
+ n${num:-10} \
+ !/usr/local/bin/qplogsumm.pl /var/log/qpsmtpd
+else
+ exec \
+ /usr/local/bin/setuidgid smelog \
+ /usr/local/bin/multilog t s5000000 \
+ n${num:-10} \
+ /var/log/qpsmtpd
+fi
+
diff --git a/root/var/service/qpsmtpd/log/supervise/.gitignore b/root/var/service/qpsmtpd/log/supervise/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/peers/.gitignore b/root/var/service/qpsmtpd/peers/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/run b/root/var/service/qpsmtpd/run
new file mode 100755
index 0000000..50b19a1
--- /dev/null
+++ b/root/var/service/qpsmtpd/run
@@ -0,0 +1,73 @@
+#!/bin/sh
+#----------------------------------------------------------------------
+# copyright (C) 1999-2005 Mitel Networks Corporation
+# Copyright (C) 2005-2006 Gordon Rowell
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#----------------------------------------------------------------------
+
+exec 2>&1
+
+[ -f ./runenv ] && . ./runenv
+
+export QPSMTPD_CONFIG=/var/service/qpsmtpd/config
+
+./control/1
+[ -e /var/service/qpsmtpd/config/databytes ] && \
+ rm -f /var/service/qpsmtpd/config/databytes
+[ -e /var/service/qpsmtpd/config/badrcptto_patterns ] && \
+ rm -f /var/service/qpsmtpd/config/badrcptto_patterns
+
+# Create dhparam
+[ -e /var/service/qpsmtpd/ssl/dhparam.pem ] || \
+ RANDFILE=/dev/null /usr/bin/openssl dhparam -out /var/service/qpsmtpd/ssl/dhparam.pem 2048
+
+# Create a default dkim key pair
+[ -e /home/e-smith/dkim_keys/default/private ] || (\
+ RANDFILE=/dev/null /usr/bin/openssl genrsa -out /home/e-smith/dkim_keys/default/private 2048
+ /usr/bin/openssl rsa -in /home/e-smith/dkim_keys/default/private \
+ -out /home/e-smith/dkim_keys/default/public -pubout
+ chown qpsmtpd:qpsmtpd /home/e-smith/dkim_keys/default/private
+ chmod 400 /home/e-smith/dkim_keys/default/private
+)
+
+# Init the DMARC report DB
+[ -s /var/lib/qpsmtpd/dmarc/reports.sqlite ] || (\
+ SCHEMA=$(rpm -qd perl-Mail-DMARC | grep mail_dmarc_schema.sqlite)
+ /usr/bin/sqlite3 /var/lib/qpsmtpd/dmarc/reports.sqlite < $SCHEMA
+ chown qpsmtpd:qpsmtpd /var/lib/qpsmtpd/dmarc/reports.sqlite
+ chmod 640 /var/lib/qpsmtpd/dmarc/reports.sqlite
+)
+
+exec /usr/local/bin/softlimit -d ${SOFTLIMIT:-50000000} -s ${SOFTLIMIT:-50000000} -l ${SOFTLIMIT:-50000000} \
+ /usr/bin/qpsmtpd-forkserver \
+ -u qpsmtpd \
+ -l 0.0.0.0 \
+ -p ${PORT:-25} \
+ -c ${INSTANCES:-40} \
+ -m ${INSTANCES_PER_IP:-5}
+
+#sub usage {
+# print <<"EOT";
+#usage: qpsmtpd-forkserver [ options ]
+# -l, --listen-address addr : listen on a specific address; default 0.0.0.0
+# -p, --port P : listen on a specific port; default 2525
+# -c, --limit-connections N : limit concurrent connections to N; default 15
+# -u, --user U : run as a particular user (defualt 'smtpd')
+# -m, --max-from-ip M : limit connections from a single IP; default 5
+#EOT
+# exit 0;
+#}
+#
diff --git a/root/var/service/qpsmtpd/ssl/.gitignore b/root/var/service/qpsmtpd/ssl/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/qpsmtpd/supervise/.gitignore b/root/var/service/qpsmtpd/supervise/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/sqpsmtpd/config b/root/var/service/sqpsmtpd/config
new file mode 120000
index 0000000..d392d48
--- /dev/null
+++ b/root/var/service/sqpsmtpd/config
@@ -0,0 +1 @@
+../qpsmtpd/config
\ No newline at end of file
diff --git a/root/var/service/sqpsmtpd/down b/root/var/service/sqpsmtpd/down
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/sqpsmtpd/log/run b/root/var/service/sqpsmtpd/log/run
new file mode 100755
index 0000000..663e96c
--- /dev/null
+++ b/root/var/service/sqpsmtpd/log/run
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+#----------------------------------------------------------------------
+# copyright (C) 2001 e-smith, inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Technical support for this program is available from e-smith, inc.
+# Please visit our web site www.e-smith.com for details.
+#----------------------------------------------------------------------
+
+num=`/sbin/e-smith/config getprop sqpsmtpd KeepLogFiles`
+
+exec \
+ /usr/local/bin/setuidgid smelog \
+ /usr/local/bin/multilog t s5000000 \
+ n${num:-10} \
+ /var/log/sqpsmtpd
diff --git a/root/var/service/sqpsmtpd/log/supervise/.gitignore b/root/var/service/sqpsmtpd/log/supervise/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/service/sqpsmtpd/run b/root/var/service/sqpsmtpd/run
new file mode 100755
index 0000000..81087d0
--- /dev/null
+++ b/root/var/service/sqpsmtpd/run
@@ -0,0 +1,48 @@
+#!/bin/sh
+#----------------------------------------------------------------------
+# copyright (C) 1999-2005 Mitel Networks Corporation
+# Copyright (C) 2005-2006 Gordon Rowell
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#----------------------------------------------------------------------
+
+exec 2>&1
+
+[ -f ./runenv ] && . ./runenv
+
+export QPSMTPD_CONFIG=/var/service/qpsmtpd/config
+
+../qpsmtpd/control/1
+
+exec /usr/local/bin/softlimit -d ${SOFTLIMIT:-50000000} -s ${SOFTLIMIT:-50000000} -l ${SOFTLIMIT:-50000000} \
+ /usr/bin/qpsmtpd-forkserver \
+ -u qpsmtpd \
+ -l 0.0.0.0 \
+ -p ${PORT:-465} \
+ -c ${INSTANCES:-40} \
+ -m ${INSTANCES_PER_IP:-5}
+
+#sub usage {
+# print <<"EOT";
+#usage: qpsmtpd-forkserver [ options ]
+# -l, --listen-address addr : listen on a specific address; default 0.0.0.0
+# -p, --port P : listen on a specific port; default 2525
+# -c, --limit-connections N : limit concurrent connections to N; default 15
+# -u, --user U : run as a particular user (defualt 'smtpd')
+# -m, --max-from-ip M : limit connections from a single IP; default 5
+#EOT
+# exit 0;
+#}
+#
diff --git a/root/var/service/sqpsmtpd/sqpsmtpd b/root/var/service/sqpsmtpd/sqpsmtpd
new file mode 100644
index 0000000..b2f49db
--- /dev/null
+++ b/root/var/service/sqpsmtpd/sqpsmtpd
@@ -0,0 +1,27 @@
+#! /bin/sh
+#----------------------------------------------------------------------
+# copyright (C) 1999-2005 Mitel Networks Corporation
+# Copyright (C) 2005 Gordon Rowell
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Technical support for this program is available from Mitel Networks
+# Please visit our web site www.mitel.com/sme/ for details.
+#----------------------------------------------------------------------
+
+exec sslio -vv -/ ../qpsmtpd/ssl \
+ -u qpsmtpd -U qpsmtpd \
+ /usr/bin/qpsmtpd
+
diff --git a/root/var/service/sqpsmtpd/ssl b/root/var/service/sqpsmtpd/ssl
new file mode 120000
index 0000000..79d1c4b
--- /dev/null
+++ b/root/var/service/sqpsmtpd/ssl
@@ -0,0 +1 @@
+../qpsmtpd/ssl
\ No newline at end of file
diff --git a/root/var/service/sqpsmtpd/supervise/.gitignore b/root/var/service/sqpsmtpd/supervise/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/root/var/spool/qpsmtpd/.gitignore b/root/var/spool/qpsmtpd/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/smeserver-qpsmtpd.spec b/smeserver-qpsmtpd.spec
new file mode 100644
index 0000000..a60ca14
--- /dev/null
+++ b/smeserver-qpsmtpd.spec
@@ -0,0 +1,1039 @@
+# $Id: smeserver-qpsmtpd.spec,v 1.57 2023/08/16 02:19:17 jpp Exp $
+
+Summary: SME Server qpsmtpd module
+%define name smeserver-qpsmtpd
+Name: %{name}
+%define version 2.7.0
+%define release 15
+Version: %{version}
+Release: %{release}%{?dist}
+License: GPL
+Group: Networking/Daemons
+Source: %{name}-%{version}.tar.xz
+
+BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
+Requires: qpsmtpd >= 0.96-19
+Requires: perl(Mail::DKIM)
+Requires: perl(Mail::DKIM::DkSignature)
+Requires: perl(ClamAV::Client)
+Requires: perl(Mail::DMARC)
+Requires: perl(Net::IMAP::Simple) >= 1.2212
+Requires: daemontools
+Requires: qpsmtpd-plugins >= 0.0.1-sme04
+Requires: ipsvd
+Requires: e-smith-lib >= 1.16.0-08
+#Requires: e-smith-cvm-unix-local
+Requires: smeserver-clamav >= 2.7.0
+Obsoletes: e-smith-obtuse-smtpd
+Obsoletes: e-smith-qmail-smtpd
+Obsoletes: e-smith-mailfront
+Obsoletes: e-smith-ssl-mailfront
+Provides: e-smith-smtpd
+Obsoletes: e-smith-qpsmtpd
+Provides: e-smith-qpsmtpd
+Obsoletes: smeserver-qpsmtpd-tnef2mime
+Provides: smeserver-qpsmtpd-tnef2mime
+Requires: e-smith-base >= 4.15.2
+Requires: perl-Convert-TNEF
+Requires: perl-IO-stringy
+Requires: perl-File-MMagic
+Requires: perl-MIME-tools
+BuildArchitectures: noarch
+BuildRequires: e-smith-devtools
+AutoReqProv: no
+
+%description
+SME Server qpsmtpd smtpd module
+
+%changelog
+* Thu Oct 26 2023 cvs2git.sh aka Brian Read 2.7.0-15.sme
+- Roll up patches and move to git repo [SME: 12338]
+
+* Thu Oct 26 2023 BogusDateBot
+- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
+ by assuming the date is correct and changing the weekday.
+
+* Tue Aug 15 2023 Jean-Philippe Pialasse 2.7.0-14.sme
+- fix unable to auth with imap if set to localhost access [SME: 12398]
+
+* Mon Aug 14 2023 Jean-Philippe Pialasse 2.7.0-13.sme
+- fix imap auth needs escaping passwords [SME: 12395]
+ now requires perl(Net::IMAP::Simple) >= 1.2212 (1.2034)
+ do not requires e-smith-cvm-unix-local anymore
+
+* Sun Feb 05 2023 John Crisp 2.7.0-12.sme
+- migrate from cvm-unix auth to imap auth [SME: 12193]
+
+* Wed May 18 2022 John Crisp 2.7.0-11.sme
+- Print both 255 char and full length DKIM keys [SME: 11974]
+
+* Tue Apr 05 2022 Jean-Philippe Pialasse 2.7.0-10.sme
+- fix unable to set internal only pseudonym as full email [SME: 11933]
+
+* Tue Apr 05 2022 Jean-Philippe Pialasse 2.7.0-9.sme
+- add softlimit template for qpsmtpd [SME: 11858]
+ increase softlimit to 50000000.
+
+* Thu Feb 10 2022 Jean-Philippe Pialasse 2.7.0-8.sme
+- fix regression Set the default helo policy to lenient [SME: 11864]
+
+* Tue Nov 16 2021 Jean-Philippe Pialasse 2.7.0-7.sme
+- mail sent on 127.0.0.200:25 should be spam checked [SME: 10289]
+ filtering again fetchmail originating mails
+
+* Mon Nov 15 2021 Jean-Philippe Pialasse 2.7.0-6.sme
+- sighup on reload [SME: 11759]
+
+* Thu Sep 16 2021 Jean-Philippe Pialasse 2.7.0-5.sme
+- fix tnef2mime FATAL PLUGIN ERROR [SME: 11648]
+ this will be a temp fix by redefining MIME::Parser::Filer::output_path
+ until it has been fixed upstream
+
+* Tue Mar 30 2021 Jean-Philippe Pialasse 2.7.0-3.sme
+- update depreacted reject_threshold to reject [SME: 11492]
+
+* Fri Feb 12 2021 Jean-Philippe Pialasse 2.7.0-2.sme
+- remove /usr/lib/systemd/system-preset/80-koozali-qpsmtpd.preset [SME: 10958]
+
+* Wed Dec 16 2020 John Crisp 2.7.0-1.sme
+- modify for clamav 0.103.0 [SME: 11210]
+- roll up patches
+
+* Thu Dec 10 2020 Michel Begue 2.6.0-40.sme
+- add Requires=runit.service (qpsmtpd & sqpsmtpd) [SME: 11245]
+
+* Sun Dec 06 2020 Jean-Philippe Pialasse 2.6.0-39.sme
+- fix service not enabled [SME: 11107]
+ remove reset-unsavedflag
+
+* Fri Nov 27 2020 Michel Begue 2.6.0-37.sme
+- Move qpsmtpd & sqpsmtpd services to systemd [SME: 11107]
+- Create smeserver-qpsmtpd-update event [SME: 11164]
+
+* Sat Jun 27 2020 Jean-Philippe Pialasse 2.6.0-36.sme
+- expand badrcptto_ext when needed [SME: 10638]
+ this avoid user, group or pseudonyms for internal purpose to be reachable
+ from outside
+
+* Sat May 02 2020 Jean-Philippe Pialasse 2.6.0-34.sme
+- minimum Protocol TLSv1.0 [SME: 10460]
+ better ciphers order.
+
+* Sun Mar 11 2018 Jean-Philippe Pialasse 2.6.0-32.sme
+- add forcespamcheck support for fetchmail [SME: 10290]
+
+* Thu Aug 3 2017 Daniel Berteaud 2.6.0-31.sme
+- Log DMARC reporting in syslog instead of sending email to the admin.
+ Also suppress SSL connection failed warnings [SME: 10298]
+
+* Sat May 20 2017 Daniel Berteaud 2.6.0-30.sme
+- Turn DMARC reporting off by default [SME: 10303]
+
+* Wed Apr 12 2017 Jean-Philippe Pialasse 2.6.0-29.sme
+- update patch smeserver-qpsmtpd-2.6.0-smtpd_to_qpsmtpd.patch [SME: 9478]
+- Greeting property was still attached to smtpd in a template
+
+* Mon Feb 27 2017 Jean-Philippe Pialasse 2.6.0-28.sme
+- updated regex for RBL and SBL in smeserver-qpsmtpd-2.6.0-change_rbl_sbl_list_separator.patch
+- to take into account list using a subdomain [SME: 10123]
+- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
+ by assuming the date is correct and changing the weekday.
+ Thu May 11 2005 --> Thu May 05 2005 or Wed May 11 2005 or Thu May 12 2005 or ....
+ Sun Sep 25 2010 --> Sun Sep 19 2010 or Sat Sep 25 2010 or Sun Sep 26 2010 or ....
+
+* Tue Jul 12 2016 Daniel Berteaud 2.6.0-27.sme
+- Turn SPF and DMARC rejects off by default [SME: 9664]
+
+* Fri Jun 17 2016 Daniel Berteaud 2.6.0-26.sme
+- Fix disabling DMARC reporting [SME: 9206]
+
+* Tue Jun 7 2016 Daniel Berteaud 2.6.0-25.sme
+- Add missing tnef2mime and MaximumDateOffset to qpsmtpd [SME: 9560]
+
+* Fri May 27 2016 Daniel Berteaud 2.6.0-24.sme
+- Create missing directories for DKIM keys [SME: 9496]
+- Create missing directory for the DMARC report database [SME: 9206]
+
+* Tue May 24 2016 Daniel Berteaud 2.6.0-23.sme
+- Remove o and r DKIM fields as they are not standard [SME: 9496]
+
+* Mon May 16 2016 Daniel Berteaud 2.6.0-22.sme
+- In qpsmtpd-print-dns set DKIM options after the public key so the string
+ will still be splitted correctly [SME: 9496]
+
+* Sat May 7 2016 Daniel Berteaud 2.6.0-21.sme
+- Fix a syntax error in qpsmtpd-print-dns script [SME: 9206]
+
+* Fri May 6 2016 Daniel Berteaud 2.6.0-20.sme
+- Enable DMARC checking and reporting [SME: 9206]
+- Add helper to publish DKIM/DMARC/SPF policy [SME: 9496]
+- Allow DKIM signing of outbound emails [SME: 9496]
+- Possibility to reject on SPF failure [SME: 9479]
+
+* Fri May 6 2016 Daniel Berteaud 2.6.0-19.sme
+- Enable inbound dkim checking (without reject) [SME: 9480]
+
+* Fri May 6 2016 Daniel Berteaud 2.6.0-18.sme
+- Enable inbound SPF checking (without reject) [SME: 9479]
+
+* Fri Apr 22 2016 Daniel Berteaud 2.6.0-17.sme
+- Merge smtpd entry into qpsmtpd, same for ssmtpd into sqpsmtpd [SME: 9478]
+
+* Fri Apr 22 2016 Daniel Berteaud 2.6.0-16.sme
+- Use an additional badrcptto file list for external connections so
+ local only pseudonymes work as expected [SME: 9460] [SME: 4597]
+
+* Thu Apr 21 2016 Daniel Berteaud 2.6.0-15.sme
+- Call karma before earlytalker and add support for the new strikes param
+ [SME: 9462]
+
+* Wed Apr 20 2016 Daniel Berteaud 2.6.0-14.sme
+- Use the naughty plugin to defer rejections, leaving users an opportunity
+ to authenticate [SME: 5092]
+
+* Wed Apr 20 2016 Daniel Berteaud 2.6.0-13.sme
+- Use the helo plugin to check reverse DNS [SME: 2370]
+
+* Mon Apr 18 2016 Daniel Berteaud 2.6.0-12.sme
+- Add support for uribl plugin, disabled by default [SME: 9467]
+
+* Sun Apr 17 2016 Daniel Berteaud 2.6.0-11.sme
+- Change separator for SBList and RBLlist from : to , [SME: 8484]
+
+* Sun Apr 17 2016 Daniel Berteaud 2.6.0-10.sme
+- Allow setting the karma negative value from the KarmaNegative prop
+ [SME: 9462]
+
+* Sun Apr 17 2016 Daniel Berteaud 2.6.0-9.sme
+- Fix max_size param for the clamdscan plugin [SME: 9465]
+
+* Sun Apr 17 2016 Daniel Berteaud 2.6.0-8.sme
+- Use clamdscan plugin instead of clamav [SME: 9465]
+
+* Sat Apr 16 2016 Daniel Berteaud 2.6.0-7.sme
+- Enable the bogus_bounce plugin [SME: 9464]
+
+* Sat Apr 16 2016 Daniel Berteaud 2.6.0-6.sme
+- Enable the loadcheck plugin [SME: 9463]
+
+* Sat Apr 16 2016 Daniel Berteaud 2.6.0-5.sme
+- Add support for the karma plugin, but keep it disabled by default
+ [SME: 9462]
+
+* Sat Apr 16 2016 Daniel Berteaud 2.6.0-4.sme
+- Create a dhparam for qpsmtpd [SME: 9461]
+
+* Sat Apr 16 2016 Daniel Berteaud 2.6.0-3.sme
+- Adapt for qpsmtpd-0.96 (mainly plugin renamed) [SME: 9460]
+
+* Tue Mar 29 2016 Jean-Philippe Pialasse 2.6.0-2.sme
+- fix warning on spool_dir perms [SME: 9408]
+- smeserver-qpsmtpd-2.6.0-PERMS.patch
+
+* Sat Feb 06 2016 stephane de Labrusse 2.6.0-1.sme
+- Initial release to sme10
+
+* Wed Jan 13 2016 Daniel Berteaud 2.4.0-14.sme
+- Expand all ssl related conf in ssl-update [SME: 9152]
+
+* Tue Jan 12 2016 Daniel Berteaud 2.4.0-13.sme
+- Hook into a new ssl-update event [SME: 9152]
+
+* Thu Jan 7 2016 Daniel Berteaud 2.4.0-12.sme
+- Allow setting SSL protocols from DB [SME: 9162]
+
+* Thu Aug 6 2015 Daniel Berteaud 2.4.0-11.sme
+- Add domain part to bcc user if missing [SME: 8990]
+
+* Wed Dec 3 2014 stephane de Labrusse 2.4.0-10.sme
+- allow IP relayclient stored by DB [SME: 8704]
+- Code from Stefano ZAmboni
+- & Charlie Brady
+
+* Tue Dec 2 2014 stephane de Labrusse 2.4.0-9.sme
+- allow IP relayclient stored by DB [SME: 8704]
+- Code from Stefano ZAmboni
+
+* Tue May 6 2014 Ian Wells 2.4.0-8.sme
+- Remove dnsbl.ahbl.org RBL List [SME: 8368]
+
+* Tue Apr 15 2014 Ian Wells 2.4.0-7.sme
+- Remove the databytes file from qpsmtpd config [SME: 8329]
+
+* Tue Apr 15 2014 Ian Wells 2.4.0-6.sme
+- Update SBL and RBL Lists [SME: 8236]
+
+* Tue Jan 28 2014 Ian Wells 2.4.0-5.sme
+- Remove insecure ciphers [SME: 8138]
+
+* Fri Jun 14 2013 Daniel Berteaud 2.4.0-4
+- Fix size_limit initialization [SME: 7671]
+
+* Wed Apr 24 2013 Daniel Berteaud 2.4.0-3
+- reads MaxMessageSize prop of spamassassin and adds it
+ to the arguments of the plugin if defined [SME: 7559]
+
+* Wed Apr 10 2013 Daniel Berteaud 2.4.0-2
+- Requires e-smith-cvm-unix-local [SME: 7509]
+
+* Thu Feb 7 2013 Shad L. Lords 2.4.0-1
+- Roll new stream for sme9
+
+* Wed Jul 18 2012 Ian Wells 2.2.0-15
+- Revert the 2.2.0-14 change and fix properly in e-smith-base [SME: 7026]
+
+* Fri Jul 06 2012 Ian Wells 2.2.0-14
+- tls ciphers defaults to disallow SSLv2 [SME: 7026]
+
+* Thu Oct 14 2010 Daniel Berteaud 2.2.0-13
+- Read number of log files to keep from the DB [SME: 2862]
+
+* Fri Oct 8 2010 Daniel Berteaud 2.2.0-12
+- Log all the run script to stdout [SME: 5831]
+
+* Mon Oct 4 2010 Shad L. Lords 2.2.0-11.sme
+- Allow relay from all local 127.0.0.x addresses [SME: 5575]
+
+* Fri Oct 1 2010 Daniel Berteaud 2.2.0-10.sme
+- Fix RelayRequiresAuth for local network [SME: 5575]
+
+* Sat Sep 25 2010 Shad L. Lords 2.2.0-9.sme
+ Sun Sep 25 2010 --> Sun Sep 19 2010 or Sat Sep 25 2010 or Sun Sep 26 2010 or ....
+- Make tls ciphers configurable [SME: 6241]
+
+* Sat Sep 25 2010 Shad L. Lords 2.2.0-8.sme
+ Sun Sep 25 2010 --> Sun Sep 19 2010 or Sat Sep 25 2010 or Sun Sep 26 2010 or ....
+- Require auth for all relays (local too) [SME: 5575]
+
+* Sat Jun 5 2010 Ian Wells 2.2.0-7.sme
+- Add qpsmtpd template fragment for tls_before_auth [SME: 6004]
+
+* Sun Dec 27 2009 Jonathan Martens 2.2.0-6.sme
+- Enable qpsmtpd RequireResolvableFromHost plugin by default, remove
+ database entry and the database default value [SME: 5617]
+
+* Sat Nov 7 2009 Jonathan Martens 2.2.0-5.sme
+- Tie template fragment into event system to have it expanded [SME: 5031]
+
+* Fri Nov 6 2009 Jonathan Martens 2.2.0-4.sme
+- Add qpsmtpd template fragment for custom SPAM subject prefix [SME: 5031]
+
+* Thu Oct 29 2009 Shad L. Lords 2.0.0-3.sme
+- Add hooks cleanout back in in so auth works.
+
+* Thu Oct 29 2009 Shad L. Lords 2.2.0-2.sme
+- Add compatibility with qpsmtpd 0.83 [SME: 5543]
+- Add tls to base config [SME: 1076]
+
+* Tue Oct 7 2008 Shad L. Lords 2.2.0-1.sme
+- Roll new stream to separate sme7/sme8 trees [SME: 4633]
+
+* Sun Oct 5 2008 Shad L. Lords 1.2.1-57
+- Fix migrate fragment for zen.spamhaus.org [SME: 2116]
+
+* Sun Oct 5 2008 Shad L. Lords 1.2.1-56
+- Migrate sbl-xbl.spamhaus.org to zen.spamhaus.org [SME: 2116]
+- Remove blackhole.securitysage.com [SME: 4623]
+
+* Wed Jul 23 2008 Gavin Weight 1.2.1-55
+- Fix empty lines and add feature to specify disclaimer directory.
+ (thanks, Federico Simoncelli). [SME: 3244]
+
+* Thu Apr 17 2008 Gavin Weight 1.2.1-54
+- Migrate ordb.net entries away. [SME: 4214]
+
+* Tue Jan 29 2008 Filippo Carletti 1.2.1-53
+- Enable auth plugin for local connections. [SME: 2631]
+
+* Thu Jan 10 2008 Gavin Weight 1.2.1-52
+- Fix divide by zero error on log rotate. [SME: 3620]
+
+* Wed Jan 09 2008 Stephen Noble 1.2.1-51
+- check_smtp_forward changed from loginfo to logdebug [SME: 3471]
+
+* Mon Jan 7 2008 Stephen Noble 1.2.1-50
+- disable qplogsumm by deafult [SME: 3727]
+
+* Mon Jan 7 2008 Stephen Noble 1.2.1-49
+- rename template-begin fragments [SME: 2333]
+
+* Mon Oct 29 2007 Charlie Brady 1.2.1-48
+- Add badrcptto_pattern rule to block "null" recipient addresses.
+ [SME: 3476]
+
+* Thu Sep 6 2007 Charlie Brady 1.2.1-47
+- Add configurable timeouts during SMTP command parsing and message
+ body receipt. [SME: 3377]
+
+* Thu Sep 6 2007 Charlie Brady 1.2.1-46
+- Disconnect immediately if dnsbl plugin rejects recipient addresses
+ (and therefore would never accept the message). [SME: 3352]
+
+* Thu Sep 6 2007 Charlie Brady 1.2.1-45
+- Configure hosts_allow plugin, which use the pre_connection hook
+ and therefore needs to be done before the 'peers' plugin.
+ [SME: 3352]
+
+* Fri Aug 03 2007 Charlie Brady 1.2.1-44
+- Fix rbl migrate fragment (thanks, Mike McCarn). [SME: 3229]
+
+* Sun Jun 17 2007 Shad L. Lords 1.2.1-43
+- Updates for disclaimer plugin [SME: 2648]
+
+* Sat Jun 16 2007 Shad L. Lords 1.2.1-42
+- Add disclaimer plugin disabled by default [SME: 2648]
+
+* Thu Jun 14 2007 Shad L. Lords 1.2.1-41
+- Update for new features in qpsmtpd v0.40
+
+* Thu Jun 14 2007 Shad L. Lords 1.2.1-40
+- Remove conflicts qpsmtpd >= 0.33
+
+* Sat Jun 9 2007 Shad L. Lords 1.2.1-39
+- Update to correct version of qplogsumm.pl [SME: 2971]
+
+* Fri Jun 08 2007 Shad L. Lords 1.2.1-38
+- Add qplogsumm.pl to package for logging [SME: 2971]
+
+* Fri Jun 08 2007 Stephen Noble 1.2.1-37
+- Bump
+
+* Fri Jun 08 2007 Stephen Noble 1.2.1-36
+- Cumulative statistics for qpsmtpd using logterse [SME: 2971]
+
+* Sun Apr 29 2007 Shad L. Lords
+- Clean up spec so package can be built by koji/plague
+
+* Tue Apr 10 2007 Shad L. Lords 1.2.1-35
+- Add logterse plugin and reduce logging level [SME: 2875]
+
+* Fri Apr 06 2007 Shad L. Lords 1.2.1-34
+- Remove templates2events link for rcpthosts [SME: 2716]
+
+* Wed Mar 07 2007 Shad L. Lords 1.2.1-33
+- Add db entry for soft memory limits [SME: 2308]
+
+* Sat Jan 27 2007 Shad L. Lords 1.2.1-32
+- Keep TNEF attachment if contains special lookout stuff [SME: 2339]
+
+* Tue Jan 23 2007 Shad L. Lords 1.2.1-31
+- Add DomainKey and DKIM signing plugin
+
+* Thu Jan 18 2007 Shad L. Lords 1.2.1-30
+- Remove whitelist_soft plugin usage [SME: 2322]
+
+* Sat Jan 13 2007 Shad L. Lords 1.2.1-29
+- Rename badmailfrom template to 10sample [SME: 2279]
+
+* Thu Jan 11 2007 Shad L. Lords 1.2.1-28
+- Fix peers plugin to hook new methods [SME: 2091]
+
+* Thu Jan 11 2007 Shad L. Lords 1.2.1-27
+- Make smtp auth use local plugins [SME: 2091]
+
+* Wed Jan 10 2007 Shad L. Lords 1.2.1-26
+- Migrate ordb.org entries away. [SME: 2274]
+- Clean-up SBL and RBL lists to use be in the correct place and use
+ recognized lists.
+
+* Thu Dec 28 2006 Shad L. Lords 1.2.1-25
+- Reverse last change and fix correctly by passing peers/0 to
+ the inital peers plugin [SME: 2167]
+
+* Tue Dec 26 2006 Shad L. Lords 1.2.1-24
+- Update peers to exit gracefully if no config passed [SME: 2167]
+
+* Thu Dec 07 2006 Shad L. Lords
+- Update to new release naming. No functional changes.
+- Make Packager generic
+
+* Fri Dec 1 2006 Gordon Rowell 1.2.1-23
+- Re-enable these by default for local connections as they already
+ check for relayclient() for relevant sections: [SME: 1893]
+ 30check_badmailfrom
+ 33check_badrcptto_patterns
+ 34check_badrcptto
+ 38check_goodrcptto
+
+* Fri Dec 1 2006 Gordon Rowell 1.2.1-22
+- Replace config/peers/0 and config/peers/local template directory
+ symlinks with a tree of symlinks. Disable the following plugins
+ for local connections: [SME: 1893]
+ 10check_earlytalker
+ 12count_unrecognized_commands
+ 16require_resolvable_fromhost
+ 20rhsbl
+ 22dnsbl
+ 30check_badmailfrom
+ 33check_badrcptto_patterns
+ 34check_badrcptto
+ 38check_goodrcptto
+ 70spamassassin
+
+* Fri Nov 24 2006 Gordon Rowell 1.2.1-21
+- Fix last change to use SIGUSR1, not SIGHUP, and only for qpsmtpd.
+ The peers directories are shared between qpsmtpd and sqpsmtpd [SME: 1893]
+
+* Fri Nov 24 2006 Gordon Rowell 1.2.1-20
+- Regenerate peers directories in network-{create,delete} [SME: 1893]
+
+* Fri Nov 24 2006 Gordon Rowell 1.2.1-19
+- Update e-smith-lib requires to pick up configure_peers() change [SME: 1893]
+- Add control/1 script and call from run script to configure peers [SME: 1893]
+
+* Wed Nov 22 2006 Gordon Rowell 1.2.1-18
+- Ensure config directory resolves for sqpsmtpd service [SME: 1893]
+
+* Wed Nov 22 2006 Gordon Rowell 1.2.1-17
+- Create config/peers directory [SME: 1893]
+
+* Wed Nov 22 2006 Gordon Rowell 1.2.1-16
+- Expand config/peers/local in the relevant events [SME: 1893]
+- TODO: Generate peers links for local networks
+
+* Wed Nov 22 2006 Gordon Rowell 1.2.1-15
+- Remove peers/0 templates.metadata file
+- Create config/peers templates directories
+- Symlink config/peers/{0,local} to ../plugins
+- To override local qpsmtpd config, create custom template for
+ /var/service/qpsmtpd/config/peers/local [SME: 1893]
+
+* Wed Nov 22 2006 Gordon Rowell 1.2.1-14
+- Merge in smeserver-qpsmtpd-tnef2mime [SME: 2087]
+
+* Mon Nov 20 2006 Gavin Weight 1.2.1-13
+- Fix rcpthosts to regenerate on ip-change. [SME: 1926]
+
+* Fri Nov 17 2006 Gordon Rowell 1.2.1-12
+- Correct last patch (wrong templates.metadata file) [SME: 1893]
+- Expand config/peers/0 in the relevant events
+
+* Fri Nov 17 2006 Gordon Rowell 1.2.1-11
+- Enable Charlie's peers plugin [SME: 1893]
+ Use templates.metadata to provide backwards compatibility with
+ add-on template fragments (at least for the first pass)
+ config/peers/0 is generated from existing config/plugins template
+ config/plugins is now a static file which just loads the peers plugin
+- TODO: Generate local plugins file(s) with different config
+
+* Sun Oct 22 2006 Charlie Brady 1.2.1-10
+- Fix RE used to strip octets from IP address in peers plugin. [SME: 1893]
+
+* Fri Sep 08 2006 Charlie Brady 1.2.1-09
+- Add 'peers' plugin code. [SME: 1893]
+
+* Thu Aug 24 2006 Filippo Carletti 1.2.1-08
+- Add option for stealth mail logging. To enable:
+ - config setprop qpsmtpd BccMode bcc [SME: 1876]
+
+* Fri Aug 18 2006 Gordon Rowell 1.2.1-07
+- Enable check_smtp_forward if any domains are being forwarded
+ to internal mail servers [SME: 1850]
+
+* Fri Aug 18 2006 Gordon Rowell 1.2.1-06
+- Add check_smtp_forward plugin which contacts the internal mail
+ server(s) to determine whether the mail would be accepted. If
+ so, just let it queue normally
+- TODO: Add configuration to plugins file if required [SME: 1850]
+
+* Fri Aug 18 2006 Gordon Rowell 1.2.1-05
+- Revert last change. Enhancing the smtp-forward plugin to handle
+ multiple internal mail servers for different domains is too
+ complex. Let's let qmail do that work. [SME: 710]
+
+* Fri Aug 18 2006 Gordon Rowell 1.2.1-04
+- Re-enable smtp-forward plugin requiring version which declines if
+ the connection is from a relayclient, to allow fallthrough to standard
+ qmail-queue plugin.
+- Add default/failsafe queue/qmail-queue plugin [SME: 710]
+
+* Thu Jul 27 2006 Gordon Rowell 1.2.1-03
+- Remove hosts from badrcptto - we only handle domains [SME: 1777]
+
+* Sat Jul 1 2006 Gordon Rowell 1.2.1-02
+- Allow mail to [$ExternalIP] to support postmaster@[$ExternalIP] [SME: 1675]
+
+* Sat Jul 1 2006 Gordon Rowell 1.2.1-01
+- Roll tarball with patches to 1.2.0-10
+
+* Thu Jun 29 2006 Gordon Rowell 1.2.0-10
+- Change default smtpgreeting to $SystemName.$DomainName [SME: 1325]
+
+* Thu Jun 29 2006 Gordon Rowell 1.2.0-09
+- Template /var/service/qpsmtpd/config/smtpgreeting, defaulting to
+ $DomainName. To set a custom greeting, set $smtpd{Greeting} [SME: 1325]
+
+* Mon Jun 26 2006 Filippo Carletti 1.2.0-08
+- Expand badrcptto on group create/modifiy/delete events [SME: 1632]
+
+* Wed Jun 21 2006 Gordon Rowell 1.2.0-07
+- Remove configuration for klez_filter scanner as it duplicates
+ work of the pattern_filter [SME: 1620]
+
+* Tue Jun 20 2006 Filippo Carletti 1.2.0-06
+- Expand goodrcptto on group create/modifiy/delete events [SME: 1616]
+
+* Mon Jun 5 2006 Gordon Rowell 1.2.0-05
+- Improve peformance of pattern_filter plugin [SME: 1532]
+- TODO: Remove obsolete code and comments from that plugin
+
+* Wed May 17 2006 Gordon Rowell 1.2.0-04
+- Allow all mail for domains which are being forwarded to internal
+ mail servers [SME: 1253]
+
+* Thu Apr 6 2006 Gavin Weight 1.2.0-03
+- Revert back to loglevel 8 from 6. [SME: 503]
+
+* Thu Mar 23 2006 Charlie Brady 1.2.0-02
+- Disable use of smtp-forward plugin (probably temporarily) in
+ DelegateMailServer mode, to avoid mail looping problem. Always
+ use qmail-queue plugin (for now). [SME: 1121]
+
+* Wed Mar 15 2006 Charlie Brady 1.2.0-01
+- Roll stable stream version. [SME: 1016]
+
+* Fri Feb 17 2006 Charlie Brady 1.0.2-04
+- Exempt local networks from dnsbl lookup. [SME: 830]
+
+* Fri Feb 10 2006 1.0.2-03
+- Call queue/smtp-forward to connect to DelegateMailServer
+ instead of queueing locally when DelegateMailServer is set [SME: 710]
+
+* Mon Feb 6 2006 1.0.2-02
+- Enable resolvable_fromhost check by default, and add
+ whitelistsenders config for local domains. [SME: 638]
+
+* Sun Feb 5 2006 1.0.2-01
+- Roll new tarball. [SME: 651]
+
+* Sun Feb 5 2006 1.0.1-21
+- Remove unused patterns.default remnants. Ensure that all
+ templates2expand directories are populated only by createlinks
+ script. [SME: 651]
+
+* Sat Feb 4 2006 1.0.1-20
+- Expand badhelo template during ip-change event, and remove
+ bogus expansions /var/qmail/control/badhelo templates. [SME: 651]
+
+* Fri Feb 3 2006 Shad L. Lords 1.0.1-19
+- Add missing template-begin file in rhsbl directory [SME: 596]
+
+* Fri Feb 3 2006 1.0.1-18
+- Expand config/relayclients in network-(create|delete) events
+ [SME: 649]
+
+* Thu Feb 2 2006 1.0.1-17
+- Add template for invalid_resolvable_fromhost configuration file
+ [SME: 638]
+
+* Mon Jan 30 2006 Charlie Brady 1.0.1-16
+- Fix warnings during template expansion, if spamassassin and/or clamd
+ is not installed/configured. Remove dependencies on packages which
+ are optional. Ensure that clamav group exists before installation.
+ Remove one redundant template fragment (which consisted of only comments).
+ [SME: 606]
+
+* Sat Jan 28 2006 Shad L. Lords 1.0.1-15
+- Add support for rhsbl entries to db [SME: 596]
+
+* Thu Jan 26 2006 Charlie Brady 1.0.1-14
+- Remove remnant mailrules.default templates and template
+ expansions. [SME: 454]
+
+* Wed Jan 25 2006 Gordon Rowell 1.0.1-13
+- Add defaults qpsmtpd{Bcc} == disabled and qpsmtpd{BccUser} == maillog
+- To enable mail logging:
+ - Create maillog user
+ - config setprop qpsmtpd Bcc enabled
+ - signal-event email-update [SME: 13]
+
+* Wed Jan 18 2006 Gordon Rowell 1.0.1-12
+- Really reduce default qpsmtpd{LogLevel} to LOGINFO (6) [SME: 503]
+
+* Wed Jan 18 2006 Gordon Rowell 1.0.1-11
+- Reduce default qpsmtpd{LogLevel} to LOGINFO (7) [SME: 503]
+
+* Thu Jan 12 2006 Charlie Brady 1.0.1-10
+- Fix goodrcptto and mailrules templates for single domain
+ pseudonym entries. [SME: 368]
+
+* Thu Oct 13 2005 Gordon Rowell 1.0.1-09
+- Default RequireResolvableFromHost to "no" [SF: 1269382]
+
+* Thu Oct 13 2005 Gordon Rowell 1.0.1-08
+- SIGHUP [s]qpsmtpd to re-read config in email-update [SF: 1252072]
+
+* Mon Oct 10 2005 Gordon Rowell 1.0.1-07
+- And finally, the env directory [SF: 1313800]
+
+* Mon Oct 10 2005 Gordon Rowell 1.0.1-06
+- And the config directory [SF: 1313800]
+
+* Mon Oct 10 2005 Gordon Rowell 1.0.1-05
+- Need to create ssl directory to allow template expansion [SF: 1313800]
+
+* Fri Oct 7 2005 Gordon Rowell 1.0.1-04
+- And the path to the runenv directory [SF: 1313800]
+
+* Fri Oct 7 2005 Gordon Rowell 1.0.1-03
+- And fix up path to config directory [SF: 1313800]
+
+* Fri Oct 7 2005 Gordon Rowell 1.0.1-02
+- Remove symlinks from sqpsmtpd directory [SF: 1313800]
+
+* Fri Oct 7 2005 Gordon Rowell 1.0.1-01
+- Roll new tarball, including patches to 1.0.0-11
+
+* Fri Oct 7 2005 Gordon Rowell 1.0.0-11
+- Added missing = to max_size parameter for clamav plugin [SF: 1308976]
+
+* Thu Oct 6 2005 Gordon Rowell 1.0.0-10
+- Added db defaults for qpsmtpd{LogLevel}=='8' and
+ $qpsmtpd{RequireResolvableFromHost}=='yes' [SF: 1314202]
+
+* Thu Sep 22 2005 Gordon Rowell 1.0.0-09
+- Allow mail to root@domain. If you want to block it,
+ db accounts setprop root Visible internal [SF: 1252375]
+
+* Thu Sep 22 2005 Gordon Rowell 1.0.0-08
+- And pick correct value from clamav entry: [SF: 1245756]
+ $qpsmtpd{MaxScannerSize} || $clamav{StreamMaxLength} || "25M";
+
+* Thu Sep 22 2005 Gordon Rowell 1.0.0-07
+- Configure qpsmtpd{MaxScannerSize}, defaulting to 25MBytes [SF: 1245756]
+
+* Thu Sep 22 2005 Gordon Rowell 1.0.0-06
+- Set separate softlimit values for data/stack/locked [SF: 1298123]
+
+* Thu Sep 22 2005 Gordon Rowell 1.0.0-05
+- Set memory_threshold to 1 so that qpsmtpd writes all mail messages
+ to disk so that scanners can look at them. Default is 10K [SF: 1298343]
+
+* Mon Aug 29 2005 Gordon Rowell 1.0.0-04
+- Updated Requires for qpsmtpd to 0.31 [SF: 1231314]
+- Change paths to match Peter Holtzer's RPMs - /usr/share/qpsmtpd/
+ instead of /usr/lib/qpsmtpd [SF: 1231314]
+- Updated Requires for plugins to pick up new paths [SF: 1231314]
+- Remove symlinks from /var/service[s]qpsmtpd since they can
+ now be done with environment or qpsmtpd config variables [SF: 1231314]
+- Remove plugins auth/cvm_unix_local, check_norelay and
+ check_badrcptto_patterns which are now in the qpsmtpd tarball [SF: 1231314]
+
+* Mon Aug 29 2005 Gordon Rowell 1.0.0-03
+- Fix sqpsmtpd script to call sslio with -u and -U args [SF: 1257284]
+
+* Wed Aug 24 2005 Gordon Rowell 1.0.0-02
+- Configure qpsmtpd{RBLList} with comma separator, but allow
+ either since people are used to colons and we then don't have
+ to do a db migration for beta1 -> beta2 [SF: 1267737]
+
+* Fri Aug 19 2005 Gordon Rowell
+- [1.0.0-01]
+- Package renamed to smeserver-qpsmtpd
+
+* Thu Aug 18 2005 Shad L. Lords
+- [0.0.4-27sme01]
+- Change e-smith-clamav to smeserver-clamav
+
+* Thu Aug 18 2005 Gordon Rowell
+- [0.0.4-27]
+- Expand goodrcptto in domain-* events [SF: 1257199]
+
+* Tue Aug 16 2005 Charlie Brady
+- [0.0.4-26]
+- Fix uid/gid which sslio wrapper runs as for sqpsmtpd. [SF: 1257284]
+- Add Requires headers for e-smith-clamav and e-smith-spamassassin.
+
+* Mon Aug 15 2005 Charlie Brady
+- [0.0.4-25]
+- Change name of plugins RPM in Requires: header. [SF: 1242326]
+
+* Wed Jul 27 2005 Gordon Rowell
+- [0.0.4-24]
+- Enabled check_basicheaders, requiring a From and Date header.
+- Configure db default smtpd{MaxDateOffset}==0. Set it to a non-zero
+ value (e.g. 366) to reject mail with silly dates.
+ [SF: 1244977]
+
+* Tue Jul 19 2005 Charlie Brady
+- [0.0.4-23]
+- Remove explicit pathnames in db opens. [SF: 1216546 (Shad)]
+
+* Mon Jul 18 2005 Charlie Brady
+- [0.0.4-22]
+- Fix metadata OUTPUT_PATH to OUTPUT_FILENAME [SF: 1237193]
+
+* Mon Jul 18 2005 Charlie Brady
+- [0.0.4-21]
+- Fix up db default qpsmtpd{tnef2mime} -> smtpd{tnef2mime} so it is
+ actually enabled by default [SF:1227668 (Shad)]
+
+* Wed Jul 13 2005 Charlie Brady
+- [0.0.4-20]
+- Fix errors in SSL PEM file template expansion [SF: 1237193]
+
+* Tue Jul 12 2005 Charlie Brady
+- [0.0.4-19]
+- Added Michael Weinberger's smeserver-qpsmtpd-tnef2mime - [SF:1227668]
+- Added config db defaults to enable plugin
+
+* Thu Jun 16 2005 Charlie Brady
+- [0.0.4-18]
+- Remove bogus /var/service/qpsmtpd/peers/{0,local}
+ directories (this time for sure, Rocky!) [SF: 1210727]
+
+* Tue Jun 14 2005 Charlie Brady
+- [0.0.4-17]
+- Small patch from Gordon to fix cvs interaction.
+
+* Mon Jun 13 2005 Charlie Brady
+- [0.0.4-16]
+- Add Obsoletes header for e-smith-ssl-mailfront. [SF: 1219069]
+
+* Sun Jun 12 2005 Charlie Brady
+- [0.0.4-15]
+- Remove bogus /var/service/qpsmtpd/peers/{0,local}
+ directories, and fix typo. [SF: 1210727]
+
+* Tue May 31 2005 Charlie Brady
+- [0.0.4-14]
+- Fix location of templates-begin files. [SF: 1210727]
+
+* Tue May 24 2005 Charlie Brady
+- [0.0.4-13]
+- Add "access" default property for qpsmtpd and sqpsmtpd services.
+ [SF: 1205847]
+- Make sure that empty templates-begin files exist in peers/{0,local}
+ templates directories.
+
+* Wed May 11 2005 Gordon Rowell
+ Thu May 11 2005 --> Thu May 05 2005 or Wed May 11 2005 or Thu May 12 2005 or ....
+- [0.0.4-12]
+- Fix up config/relayclients - need a dot after network blocks
+
+* Wed May 11 2005 Gordon Rowell
+ Thu May 11 2005 --> Thu May 05 2005 or Wed May 11 2005 or Thu May 12 2005 or ....
+- [0.0.4-11]
+- Also regenerate goodrcptto in {user,pseudonym}-modify, since
+ details about the account may have changed
+
+* Wed May 11 2005 Gordon Rowell
+ Thu May 11 2005 --> Thu May 05 2005 or Wed May 11 2005 or Thu May 12 2005 or ....
+- [0.0.4-10]
+- Actually regenerate goodrcptto in the events mentioned in
+ 0.0.3-01 (typo in createlinks)
+
+* Fri May 06 2005 Charlie Brady
+- [0.0.4-09]
+- Add type and status defaults for qpsmtpd and sqpsmtpd services.
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-08
+- Fixed up SMTP Authentication status mismatch
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-07
+- Clean up configuration, using "runenv" file for each service
+- Check various properties to determine whether to enable plugins
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-06
+- Move mailpatterns defaults to e-smith-email
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-05
+- New arguments to auth_cvm_unix_local to allow AUTH to be
+ enabled/disabled for smtp or ssmtp:
+ enable_smtp no enable_ssmtpd yes
+- Checks config db defaults for [s]smtpd{Authentication}
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-04
+- Remove spurious return statement
+
+* Wed May 4 2005 Gordon Rowell 0.0.4-03
+- Fix auth_cvm_unix_local to actually check with CVM
+- TODO: auth-cram-md5 and auth-local (?)
+
+* Sat Apr 30 2005 Gordon Rowell 0.0.4-02
+- Check for relayclient in check_badrcptto_patterns
+- Actually check that the user exists in the prototype auth module
+
+* Sat Apr 30 2005 Gordon Rowell 0.0.4-01
+- Added Provides: e-smith-smtpd to ease migration from e-smith-mailfront
+
+* Sat Apr 30 2005 Gordon Rowell 0.0.3-04
+- Move badrcpto_patterns into a configuration file
+- Updated comment blocks in plugins
+- Parameterised a number of qpsmtpd config files
+- TODO: Database defaults, finalise parameterisation
+
+* Fri Apr 29 2005 Gordon Rowell 0.0.3-03
+- Renamed auth module to auth_cvm_unix_local
+
+* Fri Apr 29 2005 Gordon Rowell 0.0.3-02
+- Added auth_cvm-unix-local for AUTH LOGIN and AUTH PLAIN
+- TODO: Actually check with CVM - currently uses colon separated
+ plain text config/flat_auth_pw
+
+* Fri Apr 29 2005 Gordon Rowell 0.0.3-01
+- Regenerate goodrcptto in {user,pseudonym}-{create,delete}
+ - thanks Paul Nesbit
+- Split qpsmtpd-plugins-openfusion into separate RPM
+- Note: mailer-daemon now works due to change I suggested in
+ check_goodrcptto: match on full string, then match again on
+ string with extension stripped - thanks Gavin Carr
+- Unset RELAYCLIENT in check_norelay (probably not required)
+
+* Tue Apr 26 2005 Gordon Rowell
+- [0.0.2-03]
+- Pass correct parameter to check_goodrcptto
+- TODO: mailer-daemon is currently being denied due to goodrcptto
+ extension folding
+
+* Tue Apr 26 2005 Gordon Rowell
+- [0.0.2-02]
+- Added plugins/check_badrcptto_patterns to check for bang, shriek
+ and double at paths.
+- Added plugins/check_norelay to allow specific hosts to be denied relaying
+
+* Tue Apr 26 2005 Gordon Rowell
+- [0.0.2-01]
+- Added plugins/virus/patterns_filter, based on Gavin Carr's exe_filter,
+ but without the dependency on Email::MIME. This is a simple-minded
+ filter, which doesn't care about MIME boundaries (as per the
+ mailfront version).
+
+* Mon Apr 25 2005 Gordon Rowell
+- [0.0.1-03]
+- Fixed path to clamav socket in 80clamdscan (currently unused)
+- Parameterised many of the templates
+- TODO: Need to parameterise rshbl
+- Added a set of qpsmtpd plugins from Gavin Carr of OpenFusion:
+ http://www.openfusion.com.au/labs/qpsmtpd/
+- TODO: Need norelayclient setting (to deny relay from router)
+- TODO: sqpsmtpd needs testing - fails with (maybe just from stunnel client)
+ "421 See http://smtpd.develooper.com/barelf.html"
+
+* Thu Apr 21 2005 Gordon Rowell
+- [0.0.1-02]
+- Initial cut of sqpsmtpd
+
+* Thu Apr 21 2005 Gordon Rowell
+- [0.0.1-01]
+- Initial packaging
+
+%prep
+%setup
+rm -rf root/usr/lib/systemd/system-preset
+
+
+%build
+perl createlinks
+mkdir -p root/var/lib/qpsmtpd/karma
+mkdir -p root/var/lib/qpsmtpd/dmarc
+mkdir -p root/home/e-smith/dkim_keys/default
+mkdir -p root/var/service/qpsmtpd/config/dkim
+
+PEERS_CONFIG=root/etc/e-smith/templates/var/service/qpsmtpd/config/peers
+mkdir -p $PEERS_CONFIG/0
+mkdir -p $PEERS_CONFIG/local
+
+DISABLE_LOCAL="
+09karma
+10earlytalker
+12count_unrecognized_commands
+15helo
+16resolvable_fromhost
+19loadcheck
+20rhsbl
+22dnsbl
+221spf
+223dmarc
+23naughty
+34badrcptto_ext
+70spamassassin
+"
+
+for file in $DISABLE_LOCAL
+do
+ echo "# $file disabled for local connections" > $PEERS_CONFIG/local/$file
+done
+
+DISABLE_EXTERNAL="
+34badrcptto
+65disclaimer
+"
+
+for file in $DISABLE_EXTERNAL
+do
+ echo "# $file disabled for external connections" > $PEERS_CONFIG/0/$file
+done
+
+(
+ cd root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins
+ for file in *
+ do
+ [ -e ../peers/0/$file ] ||
+ ln -s ../../plugins/$file ../peers/0/$file
+ [ -e ../peers/local/$file ] ||
+ ln -s ../../plugins/$file ../peers/local/$file
+ done
+)
+
+%install
+rm -rf $RPM_BUILD_ROOT
+(cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT)
+rm -f %{name}-%{version}-%{release}-filelist
+/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
+ --dir /var/service/qpsmtpd "attr(1755,root,root)" \
+ --file /var/service/qpsmtpd/down "attr(0644,root,root)" \
+ --file /var/service/qpsmtpd/run "attr(0755,root,root)" \
+ --file /var/service/qpsmtpd/control/1 "attr(0755,root,root)" \
+ --dir /var/service/qpsmtpd/supervise "attr(0700,root,root)" \
+ --dir /var/service/qpsmtpd/env "attr(0755,root,root)" \
+ --file /var/service/qpsmtpd/env/PATH "attr(0644,root,root)" \
+ --dir /var/service/qpsmtpd/log "attr(1755,root,root)" \
+ --file /var/service/qpsmtpd/log/run "attr(0755,root,root)" \
+ --dir /var/service/qpsmtpd/log/supervise "attr(0700,root,root)" \
+ --dir /var/log/qpsmtpd "attr(2750,smelog,smelog)" \
+ \
+ --dir /var/service/sqpsmtpd "attr(1755,root,root)" \
+ --file /var/service/sqpsmtpd/down "attr(0644,root,root)" \
+ --file /var/service/sqpsmtpd/run "attr(0755,root,root)" \
+ --dir /var/service/sqpsmtpd/supervise "attr(0700,root,root)" \
+ --dir /var/service/sqpsmtpd/env "attr(0755,root,root)" \
+ --file /var/service/sqpsmtpd/env/PATH "attr(0644,root,root)" \
+ --dir /var/service/sqpsmtpd/log "attr(1755,root,root)" \
+ --file /var/service/sqpsmtpd/log/run "attr(0755,root,root)" \
+ --dir /var/service/sqpsmtpd/log/supervise "attr(0700,root,root)" \
+ --dir /var/log/sqpsmtpd "attr(2750,smelog,smelog)" \
+ \
+ --file /var/service/sqpsmtpd/sqpsmtpd "attr(0755,root,root)" \
+ --dir /var/spool/qpsmtpd "attr(2750,qpsmtpd,clamscan)" \
+ --dir /var/lib/qpsmtpd/karma "attr(2750,qpsmtpd,qpsmtpd)" \
+ --dir /var/lib/qpsmtpd/dmarc "attr(2750,qpsmtpd,qpsmtpd)" \
+ --dir /home/e-smith/dkim_keys "attr(2750,root,qpsmtpd)" \
+ --dir /var/service/qpsmtpd/config/dkim "attr(2750,qpsmtpd,qpsmtpd)" \
+ \
+ --file /usr/local/bin/qplogsumm.pl "attr(0755,root,root)" \
+ > %{name}-%{version}-%{release}-filelist
+
+%pre
+/sbin/e-smith/create-system-user qpsmtpd 453 \
+ 'qpsmtpd system user' /var/service/qpsmtpd /bin/false
+/usr/sbin/groupadd -r clamav 2>/dev/null || :
+
+TEMPLATES_DIR=/etc/e-smith/templates/var/service/qpsmtpd/config/peers
+
+[ -L $TEMPLATES_DIR/0 ] && rm -f $TEMPLATES_DIR/0
+[ -L $TEMPLATES_DIR/local ] && rm -f $TEMPLATES_DIR/local
+true
+
+%post
+
+#Fix spool perms on clam upgrade
+if [[ -d /var/spool/qpsmtpd ]]; then
+ chown qpsmtpd:clamscan /var/spool/qpsmtpd;
+fi
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files -f %{name}-%{version}-%{release}-filelist
+%defattr(-,root,root)