The current postfix-queue plugin allows the administrator to set a
single path to a local postfix cleanup socket file from the plugin
'command line'.  This adds a 'cleanup_sockets' configuration directive
that can contain a list of paths as well as host/port combinations
pointing to postfix cleanup services, which will be tried in the order
that they appear.  Not yet tested.
---
 lib/Qpsmtpd/Postfix.pm      |   29 ++++++++++++++++++++++-------
 plugins/queue/postfix-queue |   16 ++++++++++------
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/lib/Qpsmtpd/Postfix.pm b/lib/Qpsmtpd/Postfix.pm
index 4e69157..5b2c4f0 100644
--- a/lib/Qpsmtpd/Postfix.pm
+++ b/lib/Qpsmtpd/Postfix.pm
@@ -14,6 +14,7 @@ details.
 
 use strict;
 use IO::Socket::UNIX;
+use IO::Socket::INET;
 use vars qw(@ISA);
 @ISA = qw(IO::Socket::UNIX);
 
@@ -92,12 +93,22 @@ sub print_rec_time {
 sub open_cleanup {
   my ($class, $socket) = @_;
 
-  $socket = "/var/spool/postfix/public/cleanup"
-    unless defined $socket;
-
-  my $self = IO::Socket::UNIX->new(Type => SOCK_STREAM,
-                                  Peer => $socket);
-  die qq(Couldn't open unix socket "$socket": $!) unless ref $self;
+  my $self;
+  if ($socket =~ m#^(/.+)#) {
+    $socket = $1; # un-taint socket path
+    $self = IO::Socket::UNIX->new(Type => SOCK_STREAM,
+                                  Peer => $socket) if $socket;
+    
+  } elsif ($socket =~ /(.*):(\d+)/) {
+    my ($host,$port) = ($1,$2); # un-taint address and port
+    $self = IO::Socket::INET->new(Proto => 'tcp',
+                                  PeerAddr => $host,PeerPort => $port)
+      if $host and $port;
+  }
+  unless (ref $self) {
+    warn "Couldn't open \"$socket\": $!";
+    return;
+  }
   # allow buffered writes
   $self->autoflush(0);
   bless ($self, $class);
@@ -163,7 +174,11 @@ $transaction is supposed to be a Qpsmtpd::Transaction 
object.
 sub inject_mail {
   my ($class, $transaction) = @_;
 
-  my $strm = $class->open_cleanup($transaction->notes('postfix-queue-socket'));
+  my @sockets = @{$transaction->notes('postfix-queue-sockets')
+                  // ['/var/spool/postfix/public/cleanup']};
+  my $strm;
+  $strm = $class->open_cleanup($_) and last for @sockets;
+  die "Unable to open any cleanup sockets!" unless $strm;
 
   my %at = $strm->get_attr;
   my $qid = $at{queue_id};
diff --git a/plugins/queue/postfix-queue b/plugins/queue/postfix-queue
index 8b3a3c0..28fa44f 100644
--- a/plugins/queue/postfix-queue
+++ b/plugins/queue/postfix-queue
@@ -11,7 +11,10 @@ This plugin passes mails on to the postfix cleanup daemon.
 
 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).
-If set, the environment variable POSTFIXQUEUE overrides this setting.
+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
@@ -133,9 +136,6 @@ sub register {
             $self->{_queue_socket} = $1;
             shift @args;
         }
-        else {
-            $self->{_queue_socket} = "/var/spool/postfix/public/cleanup";
-        }
 
         foreach (@args) {
             if ($self->can("CLEANUP_".$_) and /^(FLAG_[A-Z0-9_]+)$/) {
@@ -152,14 +152,18 @@ sub register {
         $self->{_queue_socket} = "/var/spool/postfix/public/cleanup";
     }
 
-    $self->{_queue_socket} = $ENV{POSTFIXQUEUE} if $ENV{POSTFIXQUEUE};
+    $self->{_queue_socket_env} = $ENV{POSTFIXQUEUE} if $ENV{POSTFIXQUEUE};
 
 }
 
 sub hook_queue {
     my ($self, $transaction) = @_;
     $transaction->notes('postfix-queue-flags', $self->{_queue_flags});
-    $transaction->notes('postfix-queue-socket', $self->{_queue_socket});
+    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);
-- 
1.5.6.3

Reply via email to