#!/usr/bin/perl =for comment 1. add to master.cf: delaypol unix - n n - - spawn user=nobody argv=/usr/local/libexec/delaypol.pl 2. add to main.cf: smtpd_helo_restrictions = check_policy_service unix:private/delaypol smtpd_sender_restrictions = check_policy_service unix:private/delaypol smtpd_client_restrictions = check_policy_service unix:private/delaypol smtpd_recipient_restrictions = check_policy_service unix:private/delaypol smtpd_data_restrictions = check_policy_service unix:private/delaypol smtpd_end_of_data_restrictions = check_policy_service unix:private/delaypol =cut ### no buffered descriptors $| = 1; ### see RFC2821 $DELAY{"CONNECT"} = 5; # smtpd_client_restrictions $DELAY{"EHLO"} = 0; # smtpd_helo_restrictions $DELAY{"HELO"} = 0; # smtpd_helo_restrictions $DELAY{"MAIL"} = 5; # smtpd_sender_restrictions $DELAY{"RCPT"} = 5; # smtpd_recipient_restrictions $DELAY{"DATA"} = 2; # smtpd_data_restrictions $DELAY{"END-OF-MESSAGE"} = 10; # smtpd_end_of_data_restrictions $DELAY{"VRFY"} = 0; # - $DELAY{"ETRN"} = 0; # smtpd_etrn_restrictions ### suck in parameters while (<>) { s/\r|\n//sgio; if (/^$/o) { ### empty line, end of parameters $stage = $h{protocol_state}; $client = $h{client_address}; %h = (); ### load clients %CLIENTS = (); if (open(FH, "/usr/local/etc/postfix/delayed_clients.cidr")) { while () { next if /^#/o; ($ip, $mask) = split(/\//, $_, 2); $mask = 32 unless defined $mask; $bitmask = 0xffffffff << (32 - $mask); $CLIENTS{&calc_addr($ip, $bitmask)} = $bitmask; } close(FH); } ### sleep if (exists $DELAY{$stage} && &check_client($client)) { sleep($DELAY{$stage} * 59); } ### report success print "action=dunno\n\n"; } else { ### save parameter ($key, $value) = split(/=/, $_, 2); $h{$key} = $value; } } ### subroutines sub check_client () { my $client = shift; while (my ($addr, $bitmask) = each %CLIENTS) { return 1 if ($addr == &calc_addr($client, $bitmask)); } return 0; } sub calc_addr () { my $ip = shift; my $bitmask = shift; my $addr = 0; foreach (split(/\./, $ip, 4)) { $addr = ($addr << 8) + $_; } return ($addr & $bitmask); } sub mylog { open(FH,">>/tmp/delaypol.log"); print FH localtime(time()), "\n", join("", map { "$_:\t$h{$_}\n" } sort keys %h), "===\n"; close(FH); }