initial commit of file from CVS for qpsmtpd on Fri 14 Jul 16:16:28 BST 2023

master 0.96
Brian Read 10 months ago
parent 6dc6d5f185
commit 402a95f45e

1
.gitattributes vendored

@ -0,0 +1 @@
*.tar.gz filter=lfs diff=lfs merge=lfs -text

3
.gitignore vendored

@ -0,0 +1,3 @@
*.rpm
*.log
*spec-20*

@ -0,0 +1,21 @@
# Makefile for source rpm: qpsmtpd
# $Id: Makefile,v 1.1 2016/02/07 20:49:54 stephdl Exp $
NAME := 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)

@ -1,3 +1,11 @@
# qpsmtpd
3rd Party (Maintained by Koozali) git repo for qpsmtpd smeserver
3rd Party (Maintained by Koozali) git repo for qpsmtpd smeserver
## Description
<br />*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*
<br />
Qpsmtpd is an open-source software package that provides a high-performance, extensible, secure, and configurable SMTP server. It is designed to be a fast, robust, extensible, and reliable mail server for small to medium-sized businesses and organizations. It is written in Perl and its feature-set includes configurable SMTP extensions, access control, anti-spam/virus filtering, logging and reporting, SSL/TLS support, DKIM signing, DKIM verification, rate limiting, and more.

@ -0,0 +1,10 @@
If you run qpsmtpd-apache on a box with SELinux enabled, you'll need to
allow apache to listen to your SMTP port, typically port 25.
The following command allows apache to listen on port 25:
semanage port -m -t http_port_t -p tcp 25
Use the -d option to remove this permission:
semanage port -d -t http_port_t -p tcp 25

@ -0,0 +1 @@
sme10

@ -0,0 +1,3 @@
#!/bin/sh
export QPSMTPD_CONFIG=/etc/qpsmtpd
exec /usr/bin/qpsmtpd 2> /dev/null

@ -0,0 +1,56 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.95/plugins/tls mezzanine_patched_qpsmtpd-0.95/plugins/tls
--- qpsmtpd-0.95/plugins/tls 2016-01-07 19:14:45.099736554 +0100
+++ mezzanine_patched_qpsmtpd-0.95/plugins/tls 2016-01-07 19:14:30.152736181 +0100
@@ -62,6 +62,14 @@
and put a suitable string in config/tls_ciphers (e.g. "DEFAULT" or
"HIGH:MEDIUM")
+=head1 SSL/TLS protocols versions
+
+By default, SSLv2 and SSLv3 are not accepted, leaving only TLSv1,
+TLSv1.1 or TLSv1.2 enabled. You can customize this in config/tls_protocols
+For example, this will also disabled TLSv1, leaving only TLSv1.1 and TLSv1.2
+
+SSLv23:!SSLv2:!SSLv3:!TLSv1
+
=cut
use strict;
@@ -94,6 +102,7 @@
$self->tls_ca($ca);
$self->tls_dhparam($dhparam);
$self->tls_ciphers($self->qp->config('tls_ciphers') || 'HIGH');
+ $self->tls_protocols($self->qp->config('tls_protocols') || 'SSLv23:!SSLv2:!SSLv3');
$self->log(LOGDEBUG, "ciphers: " . $self->tls_ciphers);
@@ -102,7 +111,7 @@
IO::Socket::SSL::SSL_Context->new(
# Disable SSLv2 and SSLv3 to avoid POODLE attacks. This is already
# the default in sufficiently recent versions of IO::Socket::SSL
- SSL_version => 'SSLv23:!SSLv3:!SSLv2',
+ SSL_version => $self->tls_protocols,
SSL_use_cert => 1,
SSL_cert_file => $self->tls_cert,
SSL_key_file => $self->tls_key,
@@ -226,6 +235,7 @@
my $tlssocket =
IO::Socket::SSL->new_from_fd(
fileno(STDIN), '+>',
+ SSL_version => $self->tls_protocols,
SSL_use_cert => 1,
SSL_cert_file => $self->tls_cert,
SSL_key_file => $self->tls_key,
@@ -286,6 +296,12 @@
$self->{_tls_ciphers};
}
+sub tls_protocols {
+ my $self = shift;
+ @_ and $self->{_tls_protocols} = shift;
+ $self->{_tls_protocols};
+}
+
sub ssl_context {
my $self = shift;
@_ and $self->{_ssl_ctx} = shift;

@ -0,0 +1,56 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.95/lib/Qpsmtpd/SMTP.pm mezzanine_patched_qpsmtpd-0.95/lib/Qpsmtpd/SMTP.pm
--- qpsmtpd-0.95/lib/Qpsmtpd/SMTP.pm 2015-02-11 23:00:25.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.95/lib/Qpsmtpd/SMTP.pm 2015-12-16 22:37:30.919445045 +0100
@@ -241,7 +241,8 @@
}
my $offer_auth = 1;
- if ($self->transaction->notes('tls_enabled') && ($self->config('tls_before_auth'))[0]) {
+ if (($self->transaction->notes('tls_enabled') || $self->transaction->notes('tls_force_disabled')) &&
+ ($self->config('tls_before_auth'))[0]) {
$offer_auth = 0;
}
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.95/plugins/tls mezzanine_patched_qpsmtpd-0.95/plugins/tls
--- qpsmtpd-0.95/plugins/tls 2015-02-11 23:00:25.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.95/plugins/tls 2015-12-16 22:33:23.603427932 +0100
@@ -133,9 +133,15 @@
}
sub hook_ehlo {
- my ($self, $transaction) = @_;
+ my ($self, $transaction, $host) = @_;
return DECLINED unless $self->can_do_tls;
return DECLINED if $self->connection->notes('tls_enabled');
+ return DECLINED unless $host;
+ if ($self->_is_in_notls($host)) {
+ $self->log(LOGINFO, "Disabling TLS as host matches one of the notls config file");
+ $self->connection->notes('tls_force_disabled', 1);
+ return DECLINED;
+ }
return DENY, "Command refused due to lack of security"
if $transaction->notes('ssl_failed');
my $cap = $transaction->notes('capabilities') || [];
@@ -197,6 +203,22 @@
return DECLINED;
}
+sub _is_in_notls {
+ my ($self, $host) = @_;
+
+ $host = lc $host;
+ foreach my $line ($self->qp->config('notls')) {
+ # If line is a regex
+ if ($line =~ /[\{\}\[\]\(\)\^\$\|\*\+\?\\\!]/ && $host =~ /$line/) {
+ return 1;
+ }
+ if ($host eq lc $line) {
+ return 1;
+ }
+ }
+ return;
+}
+
sub _convert_to_ssl {
my ($self) = @_;

@ -0,0 +1,11 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.95/qpsmtpd-forkserver mezzanine_patched_qpsmtpd-0.95/qpsmtpd-forkserver
--- qpsmtpd-0.95/qpsmtpd-forkserver 2015-02-11 23:00:25.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.95/qpsmtpd-forkserver 2015-12-16 22:09:28.782321968 +0100
@@ -246,6 +246,7 @@
my ($client, $hisaddr) = $server->accept;
next if !$hisaddr;
+ $client->sockopt(SO_KEEPALIVE,1);
IO::Handle::blocking($client, 1);
# get local/remote hostname, port and ip address

@ -0,0 +1,13 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.95/plugins/spamassassin mezzanine_patched_qpsmtpd-0.95/plugins/spamassassin
--- qpsmtpd-0.95/plugins/spamassassin 2015-02-11 23:00:25.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.95/plugins/spamassassin 2015-12-16 22:07:17.554311238 +0100
@@ -172,7 +172,8 @@
return DECLINED if $self->is_immune();
- if ($transaction->data_size > 500_000) {
+ my $limit = $self->{_args}->{size_limit} || 500_000;
+ if ($transaction->data_size > $limit) {
$self->log(LOGINFO,
"skip, too large (" . $transaction->data_size . ")");
return DECLINED;

@ -0,0 +1,23 @@
diff -Nur qpsmtpd-0.96.old/plugins/headers qpsmtpd-0.96/plugins/headers
--- qpsmtpd-0.96.old/plugins/headers 2016-02-16 17:52:02.000000000 -0500
+++ qpsmtpd-0.96/plugins/headers 2017-03-08 11:59:48.411000000 -0500
@@ -18,6 +18,8 @@
If the remote IP is whitelisted, header validation is skipped.
+As per March 2017 it has been reported some well known senders are putting multiple Message-Id. As a result we removed Message-Id from the singular_headers array. See https://bugs.contribs.org/show_bug.cgi?id=9773
+
=head1 CONFIGURATION
The following optional settings exist:
@@ -106,8 +108,8 @@
#my @should_headers = qw/ Message-ID /;
my @singular_headers = qw/ Date From Sender Reply-To To Cc Bcc
- Message-Id In-Reply-To References
- Subject /;
+ In-Reply-To References
+ Subject /; # <- to be RFC 5322 complient add Message-Id here
sub register {
my ($self, $qp) = (shift, shift);

@ -0,0 +1,11 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/dmarc mezzanine_patched_qpsmtpd-0.96/plugins/dmarc
--- qpsmtpd-0.96/plugins/dmarc 2016-05-03 09:10:34.624577605 +0200
+++ mezzanine_patched_qpsmtpd-0.96/plugins/dmarc 2016-05-03 09:10:14.160581205 +0200
@@ -154,6 +154,7 @@
};
};
+ $transaction->notes('dmarc_result', $dmarc->result);
my $disposition = $dmarc->result->disposition;
my $result = $dmarc->result->result;
my $auth_str = "dmarc=$result";

@ -0,0 +1,12 @@
diff -Nur qpsmtpd-0.96/lib/Qpsmtpd.pm qpsmtpd-0.96_bz9460/lib/Qpsmtpd.pm
--- qpsmtpd-0.96/lib/Qpsmtpd.pm 2016-02-16 23:52:02.000000000 +0100
+++ qpsmtpd-0.96_bz9460/lib/Qpsmtpd.pm 2016-05-16 11:52:07.041152848 +0200
@@ -448,7 +448,7 @@
sub address {
my $self = shift;
my $addr = Qpsmtpd::Address->new(@_);
- $addr->qp($self);
+ $addr->qp($self) if $addr;
return $addr;
}

@ -0,0 +1,29 @@
--- qpsmtpd-0.96.old/plugins/whitelist 2017-02-22 23:45:00.000000000 +0100
+++ qpsmtpd-0.96/plugins/whitelist 2017-02-24 02:16:08.000000000 +0100
@@ -175,6 +175,8 @@
for my $h ($self->qp->config('whitelisthelo', $config_arg)) {
if ($helo and lc $h eq lc $helo) {
$self->qp->connection->notes('whitelisthelo', 1);
+ $self->is_naughty(0); # see plugins/naughty
+ $self->adjust_karma(5);
$self->log(2, "helo host $helo in whitelisthelo");
return OK;
}
@@ -202,6 +204,8 @@
if ($addr eq $h or $host eq $h) {
$transaction->notes('whitelistsender', 1);
+ $self->is_naughty(0); # see plugins/naughty
+ $self->adjust_karma(5);
$self->log(2, "envelope sender $addr in whitelistsenders");
return OK;
}
@@ -223,6 +227,8 @@
if ($addr eq $h or $host eq $h) {
my $note = $transaction->notes('whitelistrcpt');
$transaction->notes('whitelistrcpt', ++$note);
+ $self->is_naughty(0); # see plugins/naughty
+ $self->adjust_karma(5);
$self->log(2, "recipient $addr in whitelistrcpt");
return OK;
}

@ -0,0 +1,63 @@
diff -Nur qpsmtpd-0.96.old/plugins/spamassassin qpsmtpd-0.96/plugins/spamassassin
--- qpsmtpd-0.96.old/plugins/spamassassin 2018-03-11 00:31:05.427000000 -0500
+++ qpsmtpd-0.96/plugins/spamassassin 2018-03-11 00:40:36.117000000 -0500
@@ -121,6 +121,11 @@
If the X-Spam-User header is present, the LDA should submit the message to
spamd for re-processing with the recipients address.
+=head 1 Force SPAM Check even if is_immune
+You can fill a file with a list of exception that will go under SPMA check even
+if qpsmtpd flag the connection as immune. The file is forcespamcheck. Enter an ip
+per line. As an example if you have fetchmail running on 127.0.0.200, simply add
+this ip on a line in forcespamcheck file.
=head1 CHANGES
@@ -134,7 +139,10 @@
config. Subverting their changes there is unexpected. Making them read
code to figure out why is an unnecessary hurdle.
* added assemble_message, so we can calc content size which spamd wants
-
+2018.03.11 - Jean-Philippe Pialasse
+ * added an exception list forcespamcheck to is_immune. This is useful if you are
+ running a local deamon such as fetchmail, which connection should still go through
+ spamassassin testing, even if considered immune because connect as local.
=cut
use strict;
@@ -170,7 +178,7 @@
sub data_post_handler {
my ($self, $transaction) = @_;
- return DECLINED if $self->is_immune();
+ return DECLINED if $self->is_immune() and ! $self->is_in_forcespamcheck() ;
my $limit = $self->{_args}->{size_limit} || 500_000;
if ($transaction->data_size > $limit) {
@@ -193,6 +201,26 @@
return $self->reject($transaction);
}
+sub is_in_forcespamcheck {
+ my $self = shift;
+
+ my %forcespamcheck = map { $_ => 1 } $self->qp->config('forcespamcheck');
+
+ my $ip = $self->qp->connection->local_ip;
+
+ while ($ip) {
+ if (exists $forcespamcheck{$ip}) {
+ $self->log(LOGINFO, "$ip in force spam check");
+ return 1;
+ }
+ $ip =~ s/(\d|\w)+(:|\.)?$// or last; # strip off another octet
+ }
+
+ $self->log(LOGDEBUG, "no match in forcespamcheck");
+ return;
+}
+
+
sub select_spamd_username {
my ($self, $transaction) = @_;

@ -0,0 +1,12 @@
diff -Nur --no-dereference qpsmtpd-0.96.old/qpsmtpd-forkserver qpsmtpd-0.96/qpsmtpd-forkserver
--- qpsmtpd-0.96.old/qpsmtpd-forkserver 2021-11-15 11:59:33.048000000 -0500
+++ qpsmtpd-0.96/qpsmtpd-forkserver 2021-11-15 12:00:46.276000000 -0500
@@ -193,7 +193,7 @@
POSIX::setuid($quid) or die "unable to change uid: $!\n";
$> = $quid;
-#$qpsmtpd->load_plugins;
+$qpsmtpd->load_plugins;
foreach my $addr (@LISTENADDR) {
::log(LOGINFO, "Listening on $addr->{addr}:$addr->{port}");

@ -0,0 +1,12 @@
diff -Nur qpsmtpd-0.96/plugins/karma qpsmtpd-0.96_bz9462/plugins/karma
--- qpsmtpd-0.96/plugins/karma 2016-05-09 23:56:51.145450697 +0200
+++ qpsmtpd-0.96_bz9462/plugins/karma 2016-05-09 23:57:34.484446254 +0200
@@ -449,7 +449,7 @@
my $history = ($nice || 0) - $naughty;
my $log_mess = '';
- if ($karma <= $self->{_args}{strikes}) { # Enough negative strikes ?
+ if ($karma <= -$self->{_args}{strikes}) { # Enough negative strikes ?
$history--;
my $negative_limit = 0 - $self->{_args}{negative};
if ($history <= $negative_limit) {

@ -0,0 +1,12 @@
diff -Nur qpsmtpd-0.96/plugins/dmarc qpsmtpd-0.96_bz9206/plugins/dmarc
--- qpsmtpd-0.96/plugins/dmarc 2016-05-28 10:29:34.469470149 +0200
+++ qpsmtpd-0.96_bz9206/plugins/dmarc 2016-05-28 10:33:36.482470978 +0200
@@ -145,7 +145,7 @@
my $pol;
eval { $pol = $dmarc->result->published; };
if ( $self->{_args}{reporting} && $pol ) {
- if ( $dmarc->has_valid_reporting_uri($pol->rua) ) {
+ if ( $pol->rua && $dmarc->has_valid_reporting_uri($pol->rua) ) {
eval { $dmarc->save_aggregate(); };
$self->log(LOGERROR, $@ ) if $@;
}

@ -0,0 +1,38 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/dkim mezzanine_patched_qpsmtpd-0.96/plugins/dkim
--- qpsmtpd-0.96/plugins/dkim 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/dkim 2016-04-27 17:48:41.616230753 +0200
@@ -99,19 +99,6 @@
As of this writing, most mail servers do not reject messages that fail DKIM policy, unless they also fail SPF, and no DMARC policy is published. The same holds true for SPF. There are technical reasons for this. See DMARC for more information, how you can control change that behavior, as well as receiving feedback from remote servers about messages they have accepted and rejected from senders claiming the identity of your domain(s).
-=head2 Sign for others
-
-Following the directions above will configure QP to DKIM sign messages from authenticated senders of example.org. Suppose you host client.com and would like to DKIM sign their messages too? Do that as follows:
-
- cd ~smtpd/config/dkim
- ln -s example.org client.com
-
-QP will follow the symlink target and sign client.com emails with the example.org DKIM key and set d=example.org.
-
-This is B<not> necessary for hosts or subdomains. If the DKIM key for host.example.com does not exist, and a key for example.com does exist, the parent DKIM key will be used to sign the message. So long as your DKIM and DMARC policies are set to relaxed alignment, these signed messages for subdomains will pass.
-
-CAUTION: just because you can sign for other domains, doesn't mean you should. Even with a relaxed DKIM policy, signing client.com's email with d=example.org causes an alignment error, and they may encounter deliverability problems. It is better to have keys generated and published for each domain, or at least to make a copy of config/dkim/example.org rather than linking to it.
-
=head1 SEE ALSO
http://www.dkim.org/
@@ -430,13 +417,7 @@
}
}
- if (-l $dir) {
- $dir = readlink($dir);
- $dir = "config/dkim/$dir" if $dir !~ /\//; # no /, relative path
- ($domain) = (split /\//, $dir)[-1];
- }
-
- if (!-d $dir) {
+ if (!-d $dir && !-l $dir) {
$self->log(LOGINFO, "skip, DKIM not configured for $domain");
return;
}

@ -0,0 +1,15 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/lib/Qpsmtpd/TcpServer.pm mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/TcpServer.pm
--- qpsmtpd-0.96/lib/Qpsmtpd/TcpServer.pm 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/TcpServer.pm 2016-04-15 19:13:13.873874838 +0200
@@ -120,7 +120,10 @@
while (<STDIN>) {
alarm 0;
$_ =~ s/\r?\n$//s; # advanced chomp
- $self->log(LOGINFO, "dispatching $_");
+ my $log = $_;
+ $log =~ s/AUTH PLAIN (.*)/AUTH PLAIN <hidden credentials>/
+ unless ($self->config('loglevel') || '6') >= 7;
+ $self->log(LOGINFO, "dispatching $log");
$self->connection->notes('original_string', $_);
defined $self->dispatch(split / +/, $_, 2)
or $self->respond(502, "command unrecognized: '$_'");

@ -0,0 +1,14 @@
diff -Nur qpsmtpd-0.96/plugins/dkim qpsmtpd-0.96_bz9480/plugins/dkim
--- qpsmtpd-0.96/plugins/dkim 2016-07-05 22:08:55.700102610 +0200
+++ qpsmtpd-0.96_bz9480/plugins/dkim 2016-07-05 22:11:51.485075880 +0200
@@ -262,7 +262,9 @@
push @data, "selector: " . $dkim->signature->selector if $dkim->signature;
push @data, "result: " . $dkim->result_detail if $dkim->result_detail;
- foreach my $policy ($dkim->policies) {
+ my @policies = eval { $dkim->policies };
+
+ foreach my $policy (@policies) {
next if !$policy;
push @data, "policy: " . $policy->as_string;
push @data, "name: " . $policy->name;

@ -0,0 +1,62 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/docs/hooks.md mezzanine_patched_qpsmtpd-0.96/docs/hooks.md
--- qpsmtpd-0.96/docs/hooks.md 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/docs/hooks.md 2016-05-03 21:56:38.216306190 +0200
@@ -343,26 +343,20 @@
The `data_post_headers` hook is called after the client sends the final .\r\n of
a message and before the message is processed by `data_post`. This hook is
-primarily used by plugins that insert new headers (ex: Received-SPF) and/or
+used by plugins that insert new headers (ex: Received-SPF) and/or
modify headers such as appending to Authentication-Results (SPF, DKIM, DMARC).
When it is desirable to have these header modifications evaluated by filtering
software (spamassassin, dspam, etc.) running on `data_post`, this hook should be
used instead of `data_post`.
-Allowed return codes are
-
-- DENY
-
- Return a hard failure code
+Note that you cannot reject in this hook, use the data_post hook instead
-- DENYSOFT
-
- Return a soft failure code
+Allowed return codes are
-- DENY\_DISCONNECT / DENYSOFT\_DISCONNECT
+- DECLINED
- as above but with disconnect
+ Do nothing
## hook\_data\_post
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/dmarc mezzanine_patched_qpsmtpd-0.96/plugins/dmarc
--- qpsmtpd-0.96/plugins/dmarc 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/dmarc 2016-05-03 21:57:11.943312651 +0200
@@ -102,6 +102,7 @@
else {
$self->{_dmarc} = Mail::DMARC::PurePerl->new();
$self->register_hook('data_post_headers', 'check_dmarc');
+ $self->register_hook('data_post', 'reject_dmarc');
};
}
@@ -189,6 +190,13 @@
return DECLINED if $self->is_immune;
$self->adjust_karma(-3);
-# at what point do we reject?
- return $self->get_reject("failed DMARC policy");
+ # Add a mark now so the data_post hook can do the real reject
+ $transaction->notes('reject_dmarc', '1');
+}
+
+sub reject_dmarc {
+ my ($self, $transaction) = @_;
+ return $self->get_reject("failed DMARC policy")
+ if ($transaction->notes('reject_dmarc'));
+ return DECLINED;
}

@ -0,0 +1,12 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/karma_tool mezzanine_patched_qpsmtpd-0.96/plugins/karma_tool
--- qpsmtpd-0.96/plugins/karma_tool 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/karma_tool 2016-05-04 22:22:03.913868169 +0200
@@ -63,7 +63,7 @@
my ( $self ) = @_;
return $self->{db} if $self->{db};
$self->{db} = Qpsmtpd::DB->new( name => 'karma' );
- $self->{db}->dir(
+ $self->{db}->candidate_dirs(
$self->{args}{db_dir},
qw( /var/lib/qpsmtpd/karma ./var/db ./config . ) );
my $path = $self->{db}->path;

@ -0,0 +1,46 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/karma mezzanine_patched_qpsmtpd-0.96/plugins/karma
--- qpsmtpd-0.96/plugins/karma 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/karma 2016-04-20 18:39:43.299979947 +0200
@@ -50,6 +50,16 @@
penalize a "mostly good" sender. Raising it to 2 reduces that possibility to
improbable.
+=head2 strikes <integer>
+
+How many strikes is needed to consider the mail nice or naughty.
+Various plugins can adjust the karma (see USING KARMA IN OTHER PLUGINS).
+For example, with the default value of 3, if the karma of this message is 3
+or above, the mail is considered to be a nice one. If it's -3 or less, it's
+considered a naughty one. Between -2 and +2 it's neutral
+
+Default: 3
+
=head2 penalty_days <days>
The number of days a naughty sender is refused connections. Use a decimal
@@ -238,6 +248,7 @@
$self->log(LOGERROR, "Bad arguments") if @_ % 2;
$self->{_args} = {@_};
$self->{_args}{negative} ||= 1;
+ $self->{_args}{strikes} ||= 3;
$self->{_args}{penalty_days} ||= 1;
$self->{_args}{reject_type} ||= 'disconnect';
@@ -428,7 +439,7 @@
my $history = ($nice || 0) - $naughty;
my $log_mess = '';
- if ($karma < -2) { # they achieved at least 2 strikes
+ if ($karma <= $self->{_args}{strikes}) { # Enough negative strikes ?
$history--;
my $negative_limit = 0 - $self->{_args}{negative};
if ($history <= $negative_limit) {
@@ -445,7 +456,7 @@
$log_mess = "negative";
}
}
- elsif ($karma > 2) {
+ elsif ($karma >= $self->{_args}{strikes}) {
$nice++;
$log_mess = "positive";
}

@ -0,0 +1,86 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/config.sample/karma_tlds mezzanine_patched_qpsmtpd-0.96/config.sample/karma_tlds
--- qpsmtpd-0.96/config.sample/karma_tlds 1970-01-01 01:00:00.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/config.sample/karma_tlds 2016-04-20 20:44:35.881444632 +0200
@@ -0,0 +1,14 @@
+# Karma to apply depending on the tld of the envelope sender
+# Used by the karma plugin
+# Warning: setting karma too low can blacklist the entire tld
+work:-4
+rocks:-3
+ninja:-3
+info:-2
+biz:-2
+pw:-2
+me:-1
+us:-5
+eu:-4
+link:-3
+science:-6
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/karma mezzanine_patched_qpsmtpd-0.96/plugins/karma
--- qpsmtpd-0.96/plugins/karma 2016-04-20 20:44:38.326444593 +0200
+++ mezzanine_patched_qpsmtpd-0.96/plugins/karma 2016-04-20 19:18:31.922041433 +0200
@@ -102,6 +102,20 @@
Adjust the quantity of logging for this plugin. See docs/logging.pod
+=head1 CONFIG FILES
+
+This plugin uses the following configuration files. All are optional.
+
+=head2 karma_tlds
+
+This file can contain semicolon separated tld and the corresponding
+karma adjustment to apply when the envelope sender match. It can be used to
+penalize "spammy" tlds, or to raise the karma from (mostly) good tlds.
+
+jp:-4
+ch:-3
+fr:+1
+
=head1 BENEFITS
Karma reduces the resources wasted by naughty mailers. When used with
@@ -352,18 +366,14 @@
my $full_from = $self->connection->notes('envelope_from');
$self->illegal_envelope_format( $full_from );
- my %spammy_tlds = (
- map { $_ => 4 } qw/ info pw /,
- map { $_ => 3 } qw/ tw biz /,
- map { $_ => 2 } qw/ cl br fr be jp no se sg /,
- );
- foreach my $tld ( keys %spammy_tlds ) {
+ my $karma_tlds = $self->get_karma_tlds() or return DECLINED;
+ foreach my $tld ( keys %$karma_tlds ) {
my $len = length $tld;
- my $score = $spammy_tlds{$tld} or next;
+ my $score = $karma_tlds->{$tld} or next;
$len ++;
if ( $sender->host && ".$tld" eq substr($sender->host,-$len,$len) ) {
- $self->log(LOGINFO, "penalizing .$tld envelope sender");
- $self->adjust_karma(-$score);
+ $self->log(LOGINFO, "adjusting karma for .$tld envelope sender");
+ $self->adjust_karma($score);
}
}
@@ -479,6 +489,19 @@
}
}
+sub get_karma_tlds {
+ my $self = shift;
+
+ my %karma_tlds =
+ map { (split /:/, $_, 2)[0, 1] } $self->qp->config('karma_tlds');
+ if (!%karma_tlds) {
+ $self->log(LOGDEBUG, "no specific karma for tlds defined");
+ return;
+ }
+
+ return \%karma_tlds;
+}
+
sub parse_db_record {
my ($self, $value) = @_;

@ -0,0 +1,40 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/badrcptto mezzanine_patched_qpsmtpd-0.96/plugins/badrcptto
--- qpsmtpd-0.96/plugins/badrcptto 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/badrcptto 2016-04-22 10:27:18.648307689 +0200
@@ -12,6 +12,13 @@
a complete email address, a host entry that starts with an @ symbol, or a
regular expression. For regexp pattern matches, see PATTERNS.
+=head1 CONFIG FILES
+
+=head2 more_badrcptto
+
+Optional additional file to look for badrcptto in I<config>. Same syntax
+as the default badrcptto
+
=head1 PATTERNS
This allows special patterns to be denied (e.g. percent hack, bangs,
@@ -46,6 +53,11 @@
use Qpsmtpd::Constants;
use Qpsmtpd::DSN;
+sub register {
+ my ($self, $qp, %arg) = @_;
+ $self->{_more_badrcptto} = $arg{more_badrcptto} if $arg{more_badrcptto};
+}
+
sub hook_rcpt {
my ($self, $transaction, $recipient, %param) = @_;
@@ -58,6 +70,10 @@
$self->log(LOGINFO, "skip, empty config");
return DECLINED;
};
+ if (defined $self->{_more_badrcptto}){
+ $self->log(LOGDEBUG, 'Loading additional badrcptto from ' . $self->{_more_badrcptto});
+ push @badrcptto, $self->qp->config($self->{_more_badrcptto});
+ }
for my $line (@badrcptto) {
$line =~ s/^\s+//g; # trim leading whitespace

@ -0,0 +1,56 @@
diff -Nur qpsmtpd-0.96/plugins/karma qpsmtpd-0.96_bz9462/plugins/karma
--- qpsmtpd-0.96/plugins/karma 2016-06-15 22:06:13.483902705 +0200
+++ qpsmtpd-0.96_bz9462/plugins/karma 2016-06-15 22:11:15.371747989 +0200
@@ -274,7 +274,6 @@
#$self->prune_db(); # keep the DB compact
$self->register_hook('connect', 'connect_handler');
$self->register_hook('mail', 'from_handler');
- $self->register_hook('rcpt', 'rcpt_handler');
$self->register_hook('data', 'data_handler');
$self->register_hook('data_post', 'data_handler');
$self->register_hook('disconnect', 'disconnect_handler');
@@ -380,44 +379,6 @@
return DECLINED;
}
-sub rcpt_handler {
- my ($self,$transaction, $recipient, %args) = @_;
-
- $self->illegal_envelope_format(
- $self->connection->notes('envelope_rcpt'),
- );
-
- my $count = $self->connection->notes('recipient_count') || 0;
- $count++;
- if ( $count > 1 ) {
- $self->log(LOGINFO, "recipients c: $count ($recipient)");
- $self->connection->notes('recipient_count', $count);
- }
-
- return DECLINED if $self->is_immune();
-
- my $recipients = scalar $self->transaction->recipients or do {
- $self->log(LOGDEBUG, "info, no recipient count");
- return DECLINED;
- };
- $self->log(LOGINFO, "recipients t: $recipients ($recipient)");
-
- my $history = $self->connection->notes('karma_history');
- if ( $history > 0 ) {
- $self->log(LOGINFO, "info, good history");
- return DECLINED;
- }
-
- my $karma = $self->connection->notes('karma');
- if ( $karma > 0 ) {
- $self->log(LOGINFO, "info, good connection");
- return DECLINED;
- }
-
- # limit # of recipients if host has negative or unknown karma
- return DENY, "too many recipients for karma $karma (h: $history)";
-}
-
sub data_handler {
my ($self, $transaction) = @_;

@ -0,0 +1,38 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm
--- qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm 2016-04-15 17:08:29.174840108 +0200
@@ -10,7 +10,7 @@
our @hooks = qw(
logging config user_config post-fork pre-connection connect ehlo_parse ehlo
helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5
- rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre
+ valid_auth set_hooks rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre
data data_headers_end data_post_headers data_post queue_pre queue queue_post vrfy noop
quit reset_transaction disconnect post-connection
unrecognized_command deny ok received_line help
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/lib/Qpsmtpd/SMTP.pm mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/SMTP.pm
--- qpsmtpd-0.96/lib/Qpsmtpd/SMTP.pm 2016-04-15 17:08:57.630842467 +0200
+++ mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/SMTP.pm 2016-04-15 17:07:45.577836505 +0200
@@ -96,6 +96,11 @@
# this should maybe be called something else than "connect", see
# lib/Qpsmtpd/TcpServer.pm for more confusion.
+ my ($rc, $msg) = $self->run_hooks("set_hooks");
+ if ($rc == DENY) {
+ $self->respond(550, ($msg || 'Connection from you denied, bye bye.'));
+ return $rc;
+ }
$self->run_hooks("connect");
return DONE;
}
@@ -309,7 +314,9 @@
&& $self->transaction->notes('tls_enabled'));
if (exists $auth_mechanisms{uc($mechanism)}) {
- return $self->{_auth} = Qpsmtpd::Auth::SASL($self, $mechanism, @stuff);
+ $self->{_auth} = Qpsmtpd::Auth::SASL( $self, $mechanism, @stuff );
+ $self->run_hooks("valid_auth") if $self->{_auth} == OK;
+ return $self->{_auth};
}
# no plugin implementing this auth mechanism

@ -0,0 +1,104 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/sender_permitted_from mezzanine_patched_qpsmtpd-0.96/plugins/sender_permitted_from
--- qpsmtpd-0.96/plugins/sender_permitted_from 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/sender_permitted_from 2016-05-04 18:33:37.510387152 +0200
@@ -37,6 +37,37 @@
SPF levels above 4 are for crusaders who don't mind rejecting some valid mail when the sending server administrator hasn't dotted his i's and crossed his t's. May the deities bless their obsessive little hearts.
+=head2 no_dmarc_policy
+
+When used with the dmarc plugin, you don't want sender_permitted_from to reject anything, because dmarc needs to check the sender's domain policy.
+So you'll most likely have reject 1.
+But then, if the sender's domain has no dmarc policy, you might want to reject solely based on SPF result. This is what this setting is for. A first hook runs at the mail stage and evaluate SPF. Then a second hook runs at the data_post stage (after dmarc), so you have a second chance to reject.
+
+Like reject, you can set a value to indicate how agressive you want to be:
+
+ 0 do not reject (default)
+ 1 reject if SPF record says 'fail'
+ 2 stricter reject. Also rejects 'softfail'
+ 3 reject 'neutral'
+ 4 reject if no SPF records, or a syntax error
+
+Just like reject, the recommanded value is 1. 2 will be a bit more agressive. 3 and 4 will most likely reject some valid emails.
+
+So, for example, you can use something like this:
+
+sender_permetted_from reject 1 no_dmarc_policy 1
+dkim reject 0
+dmarc reject 1 reporting 1
+
+Note this setting will only have effect if:
+
+ * dmarc plugin is used, and loaded after sender_permetted_from in your plugin's config
+ * the reject value is either 1 or 2 (meaning, no reject at the mail stage)
+ * dmarc ran with no error
+ * the sender's domain has no dmarc policy published (that means, no _dmarc DNS entry)
+
+Note that if a domain has a dmarc "p=none" policy, then this setting has no effect. Only if there's no dmarc policy at all it'll be used.
+
=head1 SEE ALSO
http://spf.pobox.com/
@@ -82,8 +113,10 @@
if (!$self->{_args}{reject} && $self->qp->config('spfbehavior')) {
$self->{_args}{reject} = $self->qp->config('spfbehavior');
}
+ $self->{_args}{no_dmarc_policy} ||= 0;
$self->register_hook('mail', 'evaluate_spf');
$self->register_hook('data_post_headers', 'add_spf_header');
+ $self->register_hook('data_post', 'no_dmarc_policy') if $self->{_args}{no_dmarc_policy} > 0;
}
sub evaluate_spf {
@@ -202,6 +235,51 @@
return DECLINED;
}
+sub no_dmarc_policy {
+ my ($self, $transaction) = @_;
+ return DECLINED if $self->is_immune;
+ unless ($self->{_args}{no_dmarc_policy}){
+ return DECLINED;
+ }
+ if ($transaction->notes('spfquery') && $transaction->notes('dmarc_result')){
+ my $spf_result = $transaction->notes('spfquery')->code;
+ my $why = $transaction->notes('spfquery')->local_explanation;
+ my $dmarc_dispo = $transaction->notes('dmarc_result')->disposition;
+ return DECLINED unless $dmarc_dispo eq 'none';
+ my $comment = '';
+ if ($transaction->notes('dmarc_result')->reason &&
+ $transaction->notes('dmarc_result')->reason->[0] &&
+ $transaction->notes('dmarc_result')->reason->[0]->comment){
+ $comment = $transaction->notes('dmarc_result')->reason->[0]->comment;
+ }
+ return DECLINED unless $comment eq 'no policy';
+ # No SPF or syntaxe error: reject if no_dmarc_policy is at least 4
+ if ((!$spf_result || $spf_result =~ m/(?:permerror|error|none)/) && $self->{_args}{no_dmarc_policy} >= 4){
+ $self->log(LOGINFO, "fail, $spf_result, $why");
+ return DENY, "SPF - $spf_result: $why";
+ }
+ # All other reject levels require an SPF code
+ return DECLINED unless $spf_result;
+ # Neutral
+ if ($spf_result eq 'neutral' && $self->{_args}{no_dmarc_policy} >= 3){
+ $self->log(LOGINFO, "fail, $spf_result, $why");
+ return DENY, "SPF - $spf_result: $why";
+ }
+ # Softfail
+ if ($spf_result eq 'softfail' && $self->{_args}{no_dmarc_policy} >= 2){
+ $self->log(LOGINFO, "fail, $spf_result, $why");
+ return DENY, "SPF - $spf_result: $why";
+ }
+ # Fail
+ if ($spf_result eq 'fail' && $self->{_args}{no_dmarc_policy} >= 1){
+ $self->log(LOGINFO, "fail, $spf_result, $why");
+ return DENY, "SPF - $spf_result: $why";
+ }
+ }
+ $self->log(LOGINFO, 'pass');
+ return DECLINED;
+}
+
sub handle_code_none {
my ($self, $reject, $why) = @_;

@ -0,0 +1,12 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm
--- qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm 2016-04-25 18:16:52.626824508 +0200
+++ mezzanine_patched_qpsmtpd-0.96/lib/Qpsmtpd/Plugin.pm 2016-04-25 18:16:24.785825492 +0200
@@ -228,7 +228,7 @@
# the naughty plugin will reject later
if ($reject eq 'naughty') {
$self->log(LOGINFO, "fail, NAUGHTY" . $log_mess);
- return $self->store_deferred_reject($smtp_mess);
+ return $self->store_deferred_reject('(' . $self->plugin_name . ') ' . $smtp_mess);
}
# they asked for reject, we give them reject

@ -0,0 +1,20 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/uribl mezzanine_patched_qpsmtpd-0.96/plugins/uribl
--- qpsmtpd-0.96/plugins/uribl 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/uribl 2016-04-18 22:10:13.565072798 +0200
@@ -271,6 +271,7 @@
if ($l =~ /(.*)=$/) {
push @qp_continuations, $1;
+ next;
}
elsif (@qp_continuations) {
$l = join('', @qp_continuations, $l);
@@ -498,7 +499,7 @@
return \@matches;
}
-sub hook_data {
+sub hook_data_post {
my ($self, $transaction) = @_;
return DECLINED if $self->is_immune();

@ -0,0 +1,31 @@
diff -Nur qpsmtpd-0.96/plugins/uribl qpsmtpd-0.96_bz9467/plugins/uribl
--- qpsmtpd-0.96/plugins/uribl 2016-07-11 22:28:55.105488861 +0200
+++ qpsmtpd-0.96_bz9467/plugins/uribl 2016-07-11 22:32:14.607442677 +0200
@@ -96,6 +96,9 @@
use Time::HiRes qw(time);
use IO::Select;
+use Data::Validate::Domain;
+
+my $v = Data::Validate::Domain->new;
# ccTLDs that allocate domain names within a strict two-level hierarchy,
# as in *.co.uk
@@ -348,7 +351,7 @@
museum|name|net|org|pro|tel|travel|
[a-zA-Z]{2})
)(?!\w)
- }gix
+ }gix && $v->is_domain($1)
)
{
my $host = lc $1;
@@ -393,7 +396,7 @@
museum|name|net|org|pro|tel|travel|
[a-zA-Z]{2})
)
- }gix
+ }gix && $v->is_domain($1)
)
{
my $host = lc $1;

@ -0,0 +1,13 @@
diff -Nur -x '*.orig' -x '*.rej' qpsmtpd-0.96/plugins/helo mezzanine_patched_qpsmtpd-0.96/plugins/helo
--- qpsmtpd-0.96/plugins/helo 2016-02-16 23:52:02.000000000 +0100
+++ mezzanine_patched_qpsmtpd-0.96/plugins/helo 2016-04-15 19:25:32.953870666 +0200
@@ -521,7 +521,8 @@
my ($dns_name, $helo_name) = @_;
return if !$dns_name;
- return if split(/\./, $dns_name) < 2; # not a FQDN
+ my @dots = split(/\./, $dns_name);
+ return if scalar @dots < 2; # not a FQDN
if ($dns_name eq $helo_name) {
$self->log(LOGDEBUG, "reverse name match");

BIN
qpsmtpd-0.96.tar.gz (Stored with Git LFS)

Binary file not shown.

@ -0,0 +1,122 @@
#! /bin/bash
#
# qpsmtpd-forkserver Start/Stop the qpsmtpd forking server
#
# chkconfig: 2345 90 60
# description: qpsmtpd is a flexible smtpd daemon written in Perl. \
# Apart from the core SMTP features, all functionality is \
# implemented in small "extension plugins" using the easy \
# to use object oriented plugin API.
# processname: qpsmtpd-forkserver
# config: /etc/qpsmtpd
# pidfile: /var/run/qpsmtpd-forkserver.pid
# Source function library.
. /etc/init.d/functions
. /etc/sysconfig/qpsmtpd-forkserver
RETVAL=0
# See how we were called.
prog="qpsmtpd-forkserver"
start() {
# cleanup environment a bit.
unset PERL_UNICODE
unset LANG
unset LC_TIME
unset LC_ALL
unset BASH_ENV
unset ENV
unset CDPATH
unset IFS
echo -n $"Starting $prog: "
trap "" 1
daemon $prog --detach $QPSMTPD_OPTIONS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
return $RETVAL
}
# functions status() uses pidof, which doesn't work with (?) scripts
qpstatus() {
local base=${1##*/}
local pid
# Test syntax.
if [ "$#" = 0 ] ; then
echo $"Usage: status {program}"
return 1
fi
# Use "/var/run/*.pid" file for pid
if [ -f /var/run/${base}.pid ] ; then
read pid < /var/run/${base}.pid
if [ -n "$pid" ]; then
/bin/ps -p $pid >/dev/null
if [ $? -eq 0 ]; then
echo $"${base} (pid $pid) is running..."
return 0
else
echo $"${base} dead but pid file exists"
return 1
fi
fi
fi
# See if /var/lock/subsys/${base} exists
if [ -f /var/lock/subsys/${base} ]; then
echo $"${base} dead but subsys locked"
return 2
fi
echo $"${base} is stopped"
return 3
}
restart() {
stop
start
}
reload() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
qpstatus qpsmtpd-forkserver
;;
condrestart)
[ -f /var/lock/subsys/$prog ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}"
exit 1
esac
exit $?

@ -0,0 +1,3 @@
QPSMTPD_OPTIONS="-p 25 -l 127.0.0.1 --pid-file /var/run/qpsmtpd-forkserver.pid"
export QPSMTPD_CONFIG=/etc/qpsmtpd
export HOME=~smtpd

@ -0,0 +1,19 @@
# default: on
# description: The telnet server serves telnet sessions; it uses \
# unencrypted username/password pairs for authentication.
service smtp
{
flags = REUSE
socket_type = stream
wait = no
user = smtpd
groups = yes
server = /usr/sbin/in.qpsmtpd
log_on_failure += USERID
disable = yes
rlimit_as = 128M
instances = 40
per_source = 10
cps = 50 10
}

@ -0,0 +1,16 @@
Listen 0.0.0.0:25 smtp
AcceptFilter smtp none
## "smtp" and the AcceptFilter are required for Linux, FreeBSD
## with apache >= 2.1.5, for others it doesn't hurt. See also
## http://httpd.apache.org/docs/2.2/mod/core.html#acceptfilter
## and http://httpd.apache.org/docs/2.2/mod/mpm_common.html#listen
<Perl>
use Apache::Qpsmtpd;
$ENV{QPSMTPD_CONFIG} = "/etc/qpsmtpd";
</Perl>
<VirtualHost _default_:25>
PerlModule Apache::Qpsmtpd
PerlProcessConnectionHandler Apache::Qpsmtpd
</VirtualHost>

@ -0,0 +1,533 @@
# $Id: qpsmtpd.spec,v 1.30 2021/11/16 23:13:14 jpp Exp $
Name: qpsmtpd
Version: 0.96
Release: 21%{?dist}
Summary: qpsmtpd + qpsmtpd-apache
License: MIT
Group: System Environment/Daemons
URL: http://smtpd.develooper.com/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: perl >= 0:5.00503
BuildRequires: perl(ExtUtils::MakeMaker)
BuildRequires: perl(ExtUtils::ParseXS)
BuildRequires: perl(ExtUtils::Manifest)
BuildArch: noarch
Requires: perl(Mail::Header), perl(Net::DNS) perl(Net::IP)
Requires: perl(IO::Socket::SSL) >= 1.70
Requires: perl(Data::Validate::Domain)
Requires(pre): coreutils, shadow-utils, perl
Source0: %{name}-%{version}.tar.gz
Source1: qpsmtpd-forkserver.rc
Source2: qpsmtpd-forkserver.sysconfig
Source3: qpsmtpd-xinetd
Source4: in.qpsmtpd
Source5: qpsmtpd.conf
Source6: README.selinux
Patch1: qpsmtpd-0.95-spamassassin_size_limit.patch
Patch2: qpsmtpd-0.95-qpsmtpd_forserver_keepalive.patch
Patch3: qpsmtpd-0.95-notls_conf.patch
Patch4: qpsmtpd-0.95-allow_tls_proto_from_conf.patch
Patch5: qpsmtpd-0.96-set_hooks.patch
Patch6: qpsmtpd-0.96-warn_implicit_split.patch
Patch7: qpsmtpd-0.96-dont_log_credentials_except_in_debug.patch
Patch8: qpsmtpd-0.96-uribl_data_post.patch
Patch9: qpsmtpd-0.96-karma_strikes.patch
Patch10: qpsmtpd-0.96-more_badrcptto.patch
Patch11: qpsmtpd-0.96-karma_tlds_conf.patch
Patch12: qpsmtpd-0.96-store_original_plugin_name.patch
Patch13: qpsmtpd-0.96-fix_karma_tool_dir_path.patch
Patch14: qpsmtpd-0.96-dkim_no_sign_for_others_on_symlinks.patch
Patch15: qpsmtpd-0.96-fix_dmarc_reject.patch
Patch16: qpsmtpd-0.96-add_dmarc_result_notes.patch
Patch17: qpsmtpd-0.96-spf_on_no_dmarc_policy.patch
Patch18: qpsmtpd-0.96-check_negative_karma_strikes.patch
Patch19: qpsmtpd-0.96-addr_defined_before_use.patch
Patch20: qpsmtpd-0.96-check_rua_is_defined.patch
Patch21: qpsmtpd-0.96-remove_karma_rcpt_handler.patch
Patch22: qpsmtpd-0.96-eval_dkim_policies.patch
Patch23: qpsmtpd-0.96-uribl_validate_domains.patch
Patch24: qpsmtpd-0.96-bz10112-whitelist.patch
Patch25: qpsmtpd-0.96-SME10139-Message-Id.patch
Patch26: qpsmtpd-0.96-bz10290-spamassassin-fetchmail.patch
Patch27: qpsmtpd-0.96-bz10387-load_plugins-on-start.patch
%description
qpsmtpd is a flexible smtpd daemon written in Perl. Apart from the core
SMTP features, all functionality is implemented in small "extension
plugins" using the easy to use object oriented plugin API.
qpsmtpd was originally written as a drop-in qmail-smtpd replacement, but
now it also includes a smtp forward and a postfix "backend".
%package apache
Requires: perl(mod_perl2)
Summary: mod_perl-2 connection handler for qpsmtpd
Group: System Environment/Daemons
%description apache
This module implements a mod_perl/apache 2.0 connection handler
that turns Apache into an SMTP server using Qpsmtpd.
%prep
%setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%build
CFLAGS="$RPM_OPT_FLAGS" perl Makefile.PL INSTALLDIRS="vendor" PREFIX="%{buildroot}%{_prefix}"
make
%clean
rm -rf $RPM_BUILD_ROOT
%install
rm -rf $RPM_BUILD_ROOT
find blib/lib -name '*.pm.*' -exec rm -f {} \;
make pure_install
mkdir -p %{buildroot}%{_datadir}/%{name}
rm -f %{buildroot}%{_datadir}/%{name}/plugins/*.*
cp -r plugins %{buildroot}%{_datadir}/%{name}/plugins
mkdir -p %{buildroot}%{_sysconfdir}/%{name}
rm -f %{buildroot}%{_sysconfdir}/%{name}/*.*
cp -r config.sample/* %{buildroot}%{_sysconfdir}/%{name}/
echo %{_datadir}/%{name}/plugins > %{buildroot}%{_sysconfdir}/%{name}/plugin_dirs
echo %{_localstatedir}/spool/qpsmtpd > %{buildroot}%{_sysconfdir}/%{name}/spool_dir
echo logging/file_connection loglevel LOGINFO %{_localstatedir}/log/qpsmtpd/%Y-%m-%d > %{buildroot}%{_sysconfdir}/%{name}/logging
mkdir -p %{buildroot}%{_initrddir}
cp %{SOURCE1} %{buildroot}%{_initrddir}/qpsmtpd-forkserver
mkdir -p %{buildroot}%{_sysconfdir}/sysconfig
cp %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/qpsmtpd-forkserver
mkdir -p %{buildroot}%{_localstatedir}/spool/qpsmtpd
mkdir -p %{buildroot}%{_localstatedir}/log/qpsmtpd
mkdir -p %{buildroot}%{_sysconfdir}/xinetd.d
cp %{SOURCE3} %{buildroot}%{_sysconfdir}/xinetd.d/smtp
mkdir -p %{buildroot}%{_sbindir}
cp %{SOURCE4} %{buildroot}%{_sbindir}/in.smtp
mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d
cp %{SOURCE5} %{buildroot}%{_sysconfdir}/httpd/conf.d
mkdir -p %{buildroot}%{_docdir}/%{name}-apache-%{version}
cp %{SOURCE6} %{buildroot}%{_docdir}/%{name}-apache-%{version}
[ -x /usr/lib/rpm/brp-compress ] && /usr/lib/rpm/brp-compress
find %{buildroot}%{_prefix} \( -name perllocal.pod -o -name .packlist \) -exec rm {} \;
find %{buildroot}%{_prefix} -type f -print | \
sed "s@^%{buildroot}@@g" | \
grep -v [Aa]sync | \
grep -v packaging | \
grep -v README.selinux | \
grep -v /Apache | \
grep -v /Danga | \
grep -v Qpsmtpd/PollServer.pm > %{name}-%{version}-%{release}-filelist
if [ "$(cat %{name}-%{version}-%{release}-filelist)X" = "X" ] ; then
echo "ERROR: EMPTY FILE LIST"
exit -1
fi
%files -f %{name}-%{version}-%{release}-filelist
%defattr(-,root,root)
%doc CREDITS Changes LICENSE README.md README.plugins.md STATUS
%{_initrddir}/qpsmtpd-forkserver
%config(noreplace) %{_sysconfdir}/qpsmtpd/*
%config(noreplace) %{_sysconfdir}/xinetd.d/smtp
%config(noreplace) %{_sysconfdir}/sysconfig/qpsmtpd-forkserver
%files apache
%defattr(-,root,root)
%{_prefix}/share/perl5/vendor_perl/Apache/Qpsmtpd.pm
%{_mandir}/man3/Apache::Qpsmtpd.3pm.gz
%config(noreplace) %{_sysconfdir}/httpd/conf.d/*
%doc %{_docdir}/%{name}-apache-%{version}/README.selinux
%pre
%changelog
* Fri Jul 14 2023 BogusDateBot
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
by assuming the date is correct and changing the weekday.
Tue Nov 30 2005 --> Tue Nov 29 2005 or Wed Nov 30 2005 or Tue Dec 06 2005 or ....
* Tue Nov 16 2021 Jean-Philippe Pialasse <tests@pialasse.com> 0.96-21.sme
- fix fetchmail patch to check local_ip [SME: 11763]
* Mon Nov 15 2021 Jean-Philippe Pialasse <tests@pialasse.com> 0.96-20.sme
- fix configuration not honoured on initial start [SME: 10387]
commented out load_plugins see https://github.com/smtpd/qpsmtpd/issues/288.
* Sun Mar 11 2018 Jean-Philippe Pialasse <tests@pialasse.com> 0.96-19.sme
- add support to force spamcheck on specific IP for fetchmail [SME: 10290]
* Tue Mar 07 2017 Jean-Philippe Pialasse <tests@pialasse.com> 0.96-18.sme
- Removed Message-Id validation, as it rejects MS account validation email [SME: 10139]
* Mon Feb 27 2017 Jean-Philippe Pialasse <tests@pialasse.com> 0.96-17.sme
- fix whitelist plugin to support helo with naughty rejecting at mail stage [SME: 10112]
* Mon Jul 11 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-16.sme
- Validate domains found in uribl with Data::Validate::Domain [SME: 9467]
* Tue Jul 5 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-15.sme
- Use eval to fetch dkim policies, prevent fatal errors in case of DNS
timeout [SME: 9480]
* Wed Jun 15 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-14.sme
- Remove karma rcpt handling (buggy and doesn't make a lot of sense)
[SME: 9462]
* Sat May 28 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-13.sme
- Check rua is defined before trying to parse it to prevent an error
if a domain has a DMARC entry published with no rua [SME: 9206]
* Mon May 16 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-12.sme
- Fix error when RCPT TO is not valid [SME: 9460]
* Mon May 9 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-11.sme
- Fix karma logic by checking negative strikes [SME: 9462]
* Sun May 8 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-10.sme
- Remove previous patch, it was already applied [SME: 9462]
* Sun May 8 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-9.sme
- Backport a fix for karma_tool so it can find its database [SME: 9462]
* Fri May 6 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-8.sme
- Support dkim signing with symlinks [SME: 9496]
- Fix DMARC rejects not working [SME: 9202]
- Add DMARC results notes so further plugin can check it [SME: 9202]
- Add possibility to reject solely on SPF result if no DMARC policy is published
[SME: 9479]
* Fri May 6 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-7.sme
- Backport some minor patches from git head [SME: 9460]
* Fri Apr 22 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-6.sme
- badrcptto can now read another file container bad addresses [SME: 9460]
[SME: 4597]
* Thu Apr 21 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-5.sme
- Fix a typo in previous patch [SME: 9462]
* Thu Apr 21 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-4.sme
- Backport the karma strikes param patch [SME: 9462]
* Mon Apr 18 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-3.sme
- hook uribl in data_post so it has access to the body [SME: 9467]
* Sun Apr 17 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-2.sme
- Don't log user credentials except when using the higher log level
[SME: 9466]
* Sat Apr 16 2016 Daniel Berteaud <daniel@firewall-services.com> 0.96-1.sme
- Update to 0.96 [SME: 9460]
* Fri Mar 25 2016 Charlie Brady <charlieb@charliebrady.org> 0.84-20.sme
- Fix startup warnings due to Socket6 symbol import. [SME: 9386]
* Sun Feb 7 2016 stephane de labrusse <stephdl@de-labrusse.fr> 0.84-19.sme
- Build new rpm for sme10
* Thu Jan 7 2016 Daniel Berteaud <daniel@firewall-services.com> 0.84-18.sme
- Allow reading SSL_version from the tls_protocols config file (and turn
TLSv1 back on by default) [SME: 9162]
* Wed Jan 6 2016 Daniel Berteaud <daniel@firewall-services.com> 0.84-17.sme
- Correctly log login attempts with nulls in login name [SME: 9167]
* Wed Jan 6 2016 Daniel Berteaud <daniel@firewall-services.com> 0.84-16.sme
- Disable TLSv1 [SME: 9162]
* Fri Sep 11 2015 stephane de Labrusse <stephdl@de-labrusse.fr> 0.84-15.sme
- Modify whitelist_soft transaction to interact with dnsbl filter [SME: 8747]
- by John Crisp <jcrisp@safeandsoundit.co.uk>
- Added qpsmtpd-0.84-make-dnsbl-more-whitelist_soft-aware.patch
* Tue May 19 2015 Daniel Berteaud <daniel@firewall-services.com> 0.84-14.sme
- Disable SSLv3 [SME: 8926]
* Fri May 15 2015 Daniel Berteaud <daniel@firewall-services.com> 0.84-13.sme
- New notls conf to set hosts you dont want to advertize STARTTLS to [SME: 8863]
* Sun Feb 15 2015 Daniel Berteaud <daniel@firewall-services.com> 0.84-12.sme
- Revert forcing TLSv1 patch as it breaks some inbound delivery [SME: 8851]
- Revert whitelist_soft dnsbl as it hasn't been verified yet and we need to
push the fix for TLSv1 [SME: 8747]
* Fri Dec 26 2014 stephane de Labrusse <stephdl@de-labrusse.fr> 0.84-11.sme
- Modify whitelist_soft transaction to interact with dnsbl filter [SME: 8747]
- by John Crisp <jcrisp@safeandsoundit.co.uk>
* Mon Dec 22 2014 Daniel Berteaud <daniel@firewall-services.com> 0.84-10.sme
- Force usage of TLSv1 [SME: 8726]
* Thu Mar 13 2014 Daniel Berteaud <daniel@firewall-services.com> 0.84-9.sme
- Remove DENYSOFT on SPF softfail [SME: 8273]
* Mon Dec 9 2013 Daniel Berteaud <daniel@firewall-services.com> 0.84-8.sme
- Fix handling of messages with no body and no trailing \n after headers (eq was
used in attempted assignment). [SME: 8051, see SME: 7754]
* Fri Jul 5 2013 Ian Wells <esmith@wellsi.com> 0.84-7.sme
- Accept messages with no body and no trailing \n after headers [SME: 7754]
* Thu Apr 25 2013 chris burnat <devlist@burnat.com> 0.84-6.sme
- Fix Net::DNS update breaks qpsmtpd, codes suggested by Ian [SME: 7561]
* Wed Apr 24 2013 Daniel Berteaud <daniel@firewall-services.com> 0.84-5.sme
- allows the spamassassin plugin to read the size limit from its
arguments [SME: 7559]
* Fri Feb 1 2013 Shad L. Lords <slords@mail.com> 0.84-4.sme
- Update spec so building on rhel6 works [SME: 7263]
* Fri May 04 2012 Charlie Brady <charlie_brady@mitel.com> 0.84-3.sme
- Set SO_KEEPALIVE option on client socket - to detect dead
connections. [SME: 6924]
* Sun Nov 14 2010 <slords@mail.com> 0.84-2.sme
- Sync with upstream git repo.
- Fix require_resolvable_fromhost doesn't work [SME: 6369]
- Fix TLS security defaults [SME: 6241]
- Fix fatal errors when mail has no headers [SME: 6345]
* Wed Apr 14 2010 <slords@mail.com> 0.84-0.1.sme
- Update to 0.84
- add sme specific patches
- Perl module rpms moved to /usr/share/perl5/vendor_perl [SME: 7223]
* Wed Mar 3 2010 <filippo.carletti@gmail.com> 0.83-0.7.sme
- Remove spool and log dir from package (in smeserver-qpsmtpd)
- Don't create smtpd user (unused in sme) [SME: 5815]
* Thu Nov 5 2009 <smeserver-contribs@snetram.nl> 0.83-0.6.sme
- Apply qpsmtpd git changesets to implement custom SPAM
subject prefix [SME: 5031]
* Tue Nov 3 2009 <slords@mail.com> 0.83-0.5.sme
- Update pre requires so scripts don't fail on install [SME: 5558]
* Sat Oct 31 2009 <slords@mail.com> 0.83-0.4.sme
- Rebase bad_rcptto patch to remove orig file [SME: 5548]
- Change logging in tls init to prevent warnings [SME: 5551]
* Thu Oct 29 2009 <slords@mail.com> 0.83-0.3.sme
- Only run/initialize plugins once [SME: 5533]
* Mon Oct 26 2009 <filippo.carletti@gmail.com> 0.83-0.2.sme
- Change spool dir permissions and owner to qpsmtpd:clamav
- Change log dir permissions and owner to smelog:smelog
* Tue Sep 22 2009 <filippo.carletti@gmail.com> 0.83-0.1.sme
- add sme specific patches
* Fri Sep 18 2009 <rpmbuild@robinbowes.com> 0.83-0.1
- Update to 0.83
* Sun Jul 12 2009 <rpmbuild@robinbowes.com> 0.82-0.1
- Update to latest release
- don't add qpsmtpd to start-up by default
- add apache config file to qpsmtpd-apache package
- remove all patches
- use rpm macros for dirs
- use a filelist for main package instead of a long list of files
* Tue Jul 15 2008 <rpmbuild@robinbowes.com> 0.43-0.7
- Removed SelectServer.pm from .spec file
* Tue Mar 18 2008 <rpmbuild@robinbowes.com> 0.43-0.6
- moved config files back to /etc/qpsmtpd following some changes
to the qpsmtpd src
* Tue Mar 18 2008 <rpmbuild@robinbowes.com> 0.43-0.5
- moved config files to /etc/qpsmtpd/config
* Tue Mar 18 2008 <rpmbuild@robinbowes.com> 0.43-0.4
- Moved qpsmtpd-async to /usr/bin
- Added qpsmtpd-async man page to async package
- Added async smtproute plugin to async package
* Wed Mar 12 2008 <rpmbuild@robinbowes.com> 0.43-0.3
- Makefile.PL now updated in svn, so remove hack
* Wed Mar 12 2008 <rpmbuild@robinbowes.com> 0.43-0.2
- Added qpsmtpd-prefork to qpsmtpd RPM, inc. hack to work round
deficiency in Makefile.PL
* Mon Mar 10 2008 <rpmbuild@robinbowes.com> 0.43-0.1
- Updated to work with Makefile to build from svn
* Wed Sep 12 2007 <rpmbuild@robinbowes.com> 0.40-2.0
- Updated to build trunk-r790
* Tue Jun 12 2007 <hjp@hjp.at> 0.40-1.0
- updated to 0.40 - no code change.
* Thu Jun 07 2007 <hjp@hjp.at> 0.40-0.2
- unset environment variables which are normally tainted in perl.
- updated to 0.40rc1
- added dependency on Net::IP (needed by some plugins)
* Sat May 05 2007 <hjp@hjp.at> 0.33-0.5
- moved environment cleanup into start() function, otherwise
LANG just gets reinitialized.
* Sat May 05 2007 <hjp@hjp.at> 0.33-0.4
- split qpsmtpd-async into a separate package to avoid dependency
on ParaDNS.
* Sat May 05 2007 <hjp@hjp.at> 0.33-0.3
- also unset LANG, LC_ALL and LC_TIME in startup script to prevent
locale specific Received headers (bug reported by Dominik Meyer)
* Sun Feb 25 2007 <hjp@hjp.at> 0.33-0.2
- 0.3x branch has been merged back to trunk.
Got current snapshot (r715) from trunk.
* Sun Feb 25 2007 <hjp@hjp.at> 0.33-0.1
- Start forkserver via "daemon" (Gavin Carr)
- Fixed 'service qpsmtpd-forkserver status' (Gavin Carr)
- Changed policy for config files to noreplace (Gavin Carr)
* Sun Nov 05 2006 <hjp@hjp.at> 0.33-0.0
- Upgraded to current snapshot from 0.3x branch (which should become
0.33 soon-ish)
- included xinetd-support again.
* Sat Mar 18 2006 <hjp@hjp.at> 0.32-2
- fix dnsbl to check whether answer fits query.
- randomize Net::DNS ids for qpsmtpd-forkserver child processes.
* Wed Mar 08 2006 <hjp@hjp.at> 0.32-1
- New upstream 0.32
- rc-file unsets PERL_UNICODE (bug #38397)
* Sat Jan 28 2006 <hjp@hjp.at> 0.31.1-3
- Use ${SOURCE*} macros to refer to source files
- Avoid invoking rpm and other cleanup in %pre section
- Invoke chkconfig in %post.
- (Thanks to Josko Plazonic for the reporting these problems and
suggesting fixes)
* Wed Nov 30 2005 <hjp@hjp.at> 0.31.1-2
Tue Nov 30 2005 --> Tue Nov 29 2005 or Wed Nov 30 2005 or Tue Dec 06 2005 or ....
- Revision 170 of plugins/loggin/file_connection:
Return DECLINED from open_log.
Open log in write_log if it isn't already open.
* Tue Nov 29 2005 <hjp@hjp.at> 0.31.1-1
- Commented out queue plugins from sample config
- Added dependencies
- Create smtpd user if it doesn't exist
- Added /var/log/qpsmtpd and /var/spool/qpsmtpd
* Sat Nov 26 2005 <hjp@hjp.at>
- Added file_connection plugin
- Startup file for qpsmtpd-forkserver now uses --detach and assumes that
a suitable logging module is configured (file_connection by default)
* Wed Nov 23 2005 <hjp@hjp.at>
- Forkserver drops privileges before loading plugins now.
* Sun Nov 20 2005 <hjp@hjp.at>
- New upstream 0.31.1
* Mon Nov 14 2005 <hjp@hjp.at> 0.31-8
- New upstream 0.31rc3.
- pre-connection patch slightly simplified since upstream fixed one of
the bugs.
* Tue Aug 23 2005 <hjp@hjp.at>
- forced INSTALLSITELIB=/usr/lib/perl5/site_perl as suggested by
Charlie Brady.
* Sat Aug 20 2005 <hjp@hjp.at> 0.31-7
- RC2 from upstream.
- Removed patches which aren't applied from spec file.
* Fri Jul 22 2005 <hjp@hjp.at> 0.31-6
- New upstream snapshot from 0.31 branch: svn revision 509.
* Sun Jul 17 2005 <hjp@hjp.at> 0.31-5
- include only /etc/init.d/qpsmtpd-forkserver, not /etc/init.d
it conflicts with old initscripts packages.
* Sun Jul 17 2005 <hjp@hjp.at> 0.31-4
- removed tabs from forkserver
* Sun Jul 17 2005 <hjp@hjp.at> 0.31-3
- added startup script for forkserver
- changed BuildArchitectures to noarch.
* Sat Jul 16 2005 <hjp@hjp.at> 0.31-2
- pre-connection hook is now actually called, not just defined.
* Fri Jul 15 2005 <hjp@hjp.at> 0.31-1
- merged with 0.31. Most of my patches are now in the official release.
- merged Gavin's per-user-config patch with my dirs patch, since the
latter needs a way to turn off logging.
- added /etc/qpsmtpd/plugin_dir to package.
* Mon Jun 13 2005 <hjp@hjp.at> 0.29-6
- fixed removal of patch backup files
- fixed option --pid-file
* Sun Jun 12 2005 <hjp@hjp.at>
- avoid installing patch backup files
- split Apache::Qpsmtpd into separate package to avoid dependency hell.
- fixed URL
- changed group to Daemons.
- Fixed installation for newer versions of ExtUtils::MakeMaker
* Wed Jun 1 2005 <hjp@hjp.at> 0.29-5
- Really don't reap children in signal handler.
* Tue May 31 2005 <hjp@hjp.at> 0.29-4
- Return 421 for DENYSOFT_DISCONNECT
- Don't reap children in signal handler.
* Thu May 19 2005 <hjp@hjp.at> 0.29-3
- removed code to accept paths without <>.
* Thu May 19 2005 <hjp@hjp.at> 0.29-2
- added QPSMTPD_CONFIG env variable and plugin_dir config.
- added supplemental groups and support for pid file
- added shared_connect hook
- changed log level for SMTP dialog from DEBUG to INFO
* Thu Apr 21 2005 hjp@hjp.at
- added plugins, /etc and docs.
* Mon Apr 18 2005 hjp@hjp.at
- Specfile autogenerated
Loading…
Cancel
Save