203 lines
6.3 KiB
Perl
203 lines
6.3 KiB
Perl
#!perl -w
|
|
|
|
=head1 NAME
|
|
|
|
postfix-queue
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This plugin passes mails on to the postfix cleanup daemon.
|
|
|
|
=head1 CONFIG
|
|
|
|
The first optional parameter is the location of the cleanup socket. If it does
|
|
not start with a ``/'', it is treated as a flag for cleanup (see below).
|
|
The 'postfix_queue' plugin can also contain a list of cleanup socket paths
|
|
and/or remote postfix cleanup service hosts specified in the form of
|
|
'address:port'. If set, the environment variable POSTFIXQUEUE overrides both
|
|
of these settings.
|
|
|
|
All other parameters are flags for cleanup, no flags are enabled by default.
|
|
See below in ``POSTFIX COMPATIBILITY'' for flags understood by your postfix
|
|
version. Supported by all postfix versions E<gt>= 2.1 are:
|
|
|
|
=over 4
|
|
|
|
=item FLAG_FILTER
|
|
|
|
Set the CLEANUP_FLAG_FILTER for cleanup. This enables the use of
|
|
I<header_filter>, I<body_filter> or I<content_filter> in postfix' main.cf.
|
|
|
|
=item FLAG_BCC_OK
|
|
|
|
Setting this flag enables (for example) the I<recipient_bcc_maps> parameter
|
|
|
|
=item FLAG_MAP_OK
|
|
|
|
This flag enables the use of other recipient mappings (e.g.
|
|
I<virtual_alias_maps>) in postfix' cleanup.
|
|
|
|
=item FLAG_MASK_EXTERNAL
|
|
|
|
This flag mask combines FLAG_FILTER, FLAG_MILTER (only in postfix >= 2.3)
|
|
FLAG_BCC_OK and FLAG_MAP_OK and is used by postfix for external messages.
|
|
This is probably what you want to use.
|
|
|
|
=back
|
|
|
|
For more flags see below in ``POSTFIX COMPATIBILITY'', your postfix version
|
|
(grep _FLAG_ src/global/cleanup_user.h) and/or lib/Qpsmtpd/Postfix/Constants.pm
|
|
|
|
=head1 POSTFIX COMPATIBILITY
|
|
|
|
The first version of this plugin was written for postfix 1.x.
|
|
|
|
The next step for Postfix 2.1 (and later) was to add the FLAG_FILTER,
|
|
FLAG_BCC_OK and FLAG_MAP_OK flags for submission to the cleanup deamon.
|
|
|
|
This version can use all flags found in Postfix 2.x (up to 2.4 currently).
|
|
Unknown flags are ignored by the cleanup daemon (just tested with postfix
|
|
2.1), so it should be safe to set flags just understood by later versions
|
|
of postfix/cleanup.
|
|
|
|
Even if all known flags can be set, some are not that useful when feeding
|
|
the message from qpsmtpd, e.g.
|
|
|
|
=head2 FLAG_NONE
|
|
|
|
no effect
|
|
|
|
=head2 FLAG_DISCARD
|
|
|
|
DON'T USE, use another plugin which hooks the I<hook_queue()> and returns
|
|
B<OK> just for the messages you want to drop. As long as this plugin does
|
|
not support setting queue flags on the fly from other modules, this flag
|
|
would drop ALL messages. Don't use!
|
|
|
|
=head2 FLAG_BOUNCE
|
|
|
|
Qpsmtpd should be configured not to accept bad messages...
|
|
|
|
=head2 FLAG_HOLD
|
|
|
|
Not useful in production setup, maybe in testing environment (untested, what
|
|
real effects this has).
|
|
|
|
=over 4
|
|
|
|
=item Flags known by postfix 1.1:
|
|
|
|
FLAG_NONE - No special features
|
|
FLAG_BOUNCE - Bounce bad messages
|
|
FLAG_FILTER - Enable content filter
|
|
|
|
=item Flags known by postfix 2.1, 2.2
|
|
|
|
all flags from postfix 1.1, plus the following:
|
|
FLAG_HOLD - Place message on hold
|
|
FLAG_DISCARD - Discard message silently
|
|
FLAG_BCC_OK - Ok to add auto-BCC addresses
|
|
FLAG_MAP_OK - Ok to map addresses
|
|
FLAG_MASK_INTERNAL - alias for FLAG_MAP_OK
|
|
FLAG_MASK_EXTERNAL - FILTER, BCC_OK and MAP_OK
|
|
|
|
=item Flags known by postfix 2.3
|
|
|
|
all flags from postfix 2.1, up to FLAG_MASK_INTERNAL. New or changed:
|
|
FLAG_MILTER - Enable Milter applications
|
|
FLAG_FILTER_ALL - FILTER and MILTER
|
|
FLAG_MASK_EXTERNAL - FILTER_ALL, BCC_OK, MAP_OK
|
|
|
|
=item Flags known by postfix 2.4
|
|
|
|
currently (postfix-2.4-20061019) the same as 2.3
|
|
|
|
=back
|
|
|
|
=head1 MAYBE IN FUTURE
|
|
|
|
Settings the (additional) queue flags from another plugin. Currently at the
|
|
beginning of I<hook_queue()> all flags are reset to the flags given as plugin
|
|
parameters.
|
|
|
|
=cut
|
|
|
|
use Qpsmtpd::Postfix;
|
|
use Qpsmtpd::Postfix::Constants;
|
|
|
|
sub register {
|
|
my ($self, $qp, @args) = @_;
|
|
|
|
$self->log(LOGDEBUG,
|
|
"using constants generated from Postfix" . "v$postfix_version");
|
|
$self->{_queue_flags} = 0;
|
|
if (@args > 0) {
|
|
if ($args[0] =~ m#^(/.+)#) {
|
|
|
|
# untaint socket path
|
|
$self->{_queue_socket} = $1;
|
|
shift @args;
|
|
}
|
|
|
|
foreach (@args) {
|
|
if ($self->can("CLEANUP_" . $_) and /^(FLAG_[A-Z0-9_]+)$/) {
|
|
$_ = $1;
|
|
$self->{_queue_flags} |= (eval "CLEANUP_$_;" || 0);
|
|
|
|
#print STDERR "queue flag: $_: ".$self->{_queue_flags}."\n";
|
|
}
|
|
else {
|
|
$self->log(LOGWARN, "Ignoring unkown cleanup flag $_");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
$self->{_queue_socket} = "/var/spool/postfix/public/cleanup";
|
|
}
|
|
|
|
$self->{_queue_socket_env} = $ENV{POSTFIXQUEUE} if $ENV{POSTFIXQUEUE};
|
|
|
|
}
|
|
|
|
sub hook_queue {
|
|
my ($self, $transaction) = @_;
|
|
$transaction->notes('postfix-queue-flags', $self->{_queue_flags});
|
|
my @queue;
|
|
@queue = ($self->{_queue_socket_env}) if $self->{_queue_socket_env};
|
|
@queue = $self->qp->config('cleanup_sockets') unless @queue;
|
|
@queue = ($self->{_queue_socket} // ()) unless @queue;
|
|
$transaction->notes('postfix-queue-sockets', \@queue) if @queue;
|
|
|
|
# $self->log(LOGDEBUG, "queue-flags=".$transaction->notes('postfix-queue-flags'));
|
|
my ($status, $qid, $reason) = Qpsmtpd::Postfix->inject_mail($transaction);
|
|
if ($status) {
|
|
|
|
# this split is needed, because if cleanup returns
|
|
# CLEANUP_STAT_MASK_INCOMPLETE we might return DENY (CLEANUP_STAT_SIZE)
|
|
# instead of DENYSOFT (CLEANUP_STAT_WRITE, CLEANUP_STAT_BAD,
|
|
# CLEANUP_STAT_DEFER) ... n.b. this is the behaviour of 667.
|
|
foreach my $key (keys %cleanup_soft) {
|
|
my $stat = eval $key # keys have the same names as the constants
|
|
or next;
|
|
if ($status & $stat) {
|
|
return DENYSOFT, $reason || $cleanup_soft{$key};
|
|
}
|
|
}
|
|
foreach my $key (keys %cleanup_hard) {
|
|
my $stat = eval $key # keys have the same names as the constants
|
|
or next;
|
|
if ($status & $stat) {
|
|
return DENY, $reason || $cleanup_hard{$key};
|
|
}
|
|
}
|
|
|
|
# we have no idea why we're here.
|
|
return DECLINED, $reason || "Unable to queue message ($status, $reason)";
|
|
}
|
|
|
|
my $msg_id = $transaction->header->get('Message-Id') || '';
|
|
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
|
|
return OK, "Queued! $msg_id (Queue-Id: $qid)";
|
|
}
|
|
|