]> git.proxmox.com Git - pmg-api.git/commitdiff
add support for before queue filtering
authorStoiko Ivanov <s.ivanov@proxmox.com>
Thu, 14 Nov 2019 16:35:07 +0000 (17:35 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 15 Nov 2019 07:58:26 +0000 (08:58 +0100)
Support for rejecting mails during the SMTP-dialog with 550 (permanent failure)
instead of seemingly accepting the mail (250 OK) and dropping it if it is
rejected by the rule-system is also known as 'before queue filtering' [0].

This patch adds minimal support for before queue filtering to pmg-smtp-filter.

Since pmg-smtp-filter is currently called via LMTP (and the 'scan' service in
'master.cf') we can adapt the already existing branch dealing with SMTP to
send a 550 selectively.

We can reply with 554 (permfail) if all recepients are blocked.

In the case that some accept the mail, we reply with 250 OK.
Depending on the setting of 'ndr_on_block' we generate ndrs
for all blocking recepients. (This is also the behavior that postfix
has when not enabling receiver verification and the downstream server rejects
recepients).

Configuration of before-queue filtering is done via the
'before_queue_filtering' boolean in the 'mail' section of 'pmg.conf':

the before_queue_filtering flag is used when rendering '/etc/postfix/master.cf'
to adapt the needed config-options for both, inbound and outbound, smtpd
servers. The settings were adapted from [0].

[0] http://www.postfix.org/SMTPD_PROXY_README.html

Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
src/PMG/Config.pm
src/PMG/SMTP.pm
src/templates/master.cf.in

index e1a9cd45af8a1bb1e27ae141cfe6513e7524e16f..ed4a6651059592d782f15f2782785ec273816dbe 100755 (executable)
@@ -627,6 +627,11 @@ sub properties {
            minimum => 0,
            default => 1
        },
+       before_queue_filtering => {
+           description => "Enable before queue filtering by pmg-smtp-filter",
+           type => 'boolean',
+           default => 0
+       },
        ndr_on_block => {
            description => "Send out NDR when mail gets blocked",
            type => 'boolean',
@@ -666,6 +671,7 @@ sub options {
        verifyreceivers => { optional => 1 },
        dnsbl_sites => { optional => 1 },
        dnsbl_threshold => { optional => 1 },
+       before_queue_filtering => { optional => 1 },
        ndr_on_block => { optional => 1 },
     };
 }
index 00a448ef8204bb17d48ea78bc529d35c8a104b70..544d0a505d37052181fd8261141614e17e64c01a 100644 (file)
@@ -154,16 +154,21 @@ sub loop {
                        }
                    }
                } else {
-                   my $all_done = 1;
-
-                   foreach $a (@{$self->{to}}) {
-                       if (!($self->{queue}->{status}->{$a} eq 'delivered' ||
-                             $self->{queue}->{status}->{$a} eq 'blocked')) {
-                           $all_done = 0;
+                   my $queueid = $self->{queue}->{logid};
+                   my $qstat = $self->{queue}->{status};
+                   my @rec = keys %$qstat;
+                   my @success_rec = grep { $qstat->{$_} eq 'delivered' } @rec;
+                   my @reject_rec = grep { $qstat->{$_} eq 'blocked' } @rec;
+
+                   if (scalar(@reject_rec) == scalar(@rec)) {
+                       $self->reply ("554 5.7.1 Rejected for policy reasons");
+                       syslog('info', "reject mail $queueid");
+                   } elsif ((scalar(@reject_rec) + scalar(@success_rec)) == scalar(@rec)) {
+                       $self->reply ("250 2.5.0 OK ($queueid)");
+                       if ($cfg->get('mail', 'ndr_on_block')) {
+                           my $dnsinfo = $cfg->get_host_dns_info();
+                           generate_ndr($self->{from}, [ @reject_rec ], $dnsinfo->{fqdn}, $queueid) if scalar(@reject_rec);
                        }
-                   }
-                   if ($all_done) {
-                       $self->reply ("250 2.5.0 OK ($self->{queue}->{logid})");
                    } else {
                        $self->reply ("451 4.4.0 detected undelivered mail");
                    }
index cbf4677f8e7de6a11e05b3d6b5293ad241659692..b7761ea821dba16183b5ea145a23e62daf3750ad 100644 (file)
 #               (yes)   (yes)   (yes)   (never) (100)
 # ==========================================================================
 
+[% IF ! pmg.mail.before_queue_filtering -%]
 scan      unix  -       -       n       -       [% pmg.mail.max_filters %]      lmtp
   -o lmtp_send_xforward_command=yes
   -o lmtp_connection_cache_on_demand=no
   -o disable_dns_lookups=yes
+[% END -%]
 
 [% pmg.mail.int_port %]       inet  n -       -       -       [% pmg.mail.max_smtpd_out %]      smtpd
+[% IF pmg.mail.before_queue_filtering -%]
+  -o smtpd_proxy_filter=127.0.0.1:10023
+  -o smtpd_proxy_options=speed_adjust
+  -o smtpd_client_connection_count_limit=[% pmg.mail.conn_count_limit div 5 %]
+[%- ELSE -%]
   -o content_filter=scan:127.0.0.1:10023
+[%- END %]
   -o smtpd_recipient_restrictions=permit_mynetworks,reject_unauth_destination
   -o smtpd_helo_restrictions=
   -o smtpd_client_restrictions=
@@ -87,7 +95,13 @@ scan      unix  -       -       n       -       [% pmg.mail.max_filters %]
 [% pmg.mail.ext_port %]       inet  n -       -       -       1 postscreen
 
 smtpd       pass  - -       -       -       [% pmg.mail.max_smtpd_in %]      smtpd
+[% IF pmg.mail.before_queue_filtering -%]
+  -o smtpd_proxy_filter=127.0.0.1:10024
+  -o smtpd_proxy_options=speed_adjust
+  -o smtpd_client_connection_count_limit=[% pmg.mail.conn_count_limit div 5 %]
+[%- ELSE -%]
   -o content_filter=scan:127.0.0.1:10024
+[%- END %]
   -o receive_override_options=no_address_mappings
   -o smtpd_discard_ehlo_keywords=silent-discard,dsn
   -o mynetworks=127.0.0.0/8,[% postfix.int_ip %]