Postfix: Como usar um script simples para mapear os endereços dos destinatários 'virtual_alias_maps'-style?

1

Eu gostaria que o postfix consultasse um script simples (bash / python) para descobrir (virtual_alias_maps - style) antes da fila se o endereço do destinatário é legítimo ou não. Por exemplo. Eu gostaria de usar endereços de e-mail como

[email protected]

para ser aceito como $ USER se $ EXIPRYDATE ainda não tiver passado e se $ CHECKSUM for aprovado ou se for rejeitado de outra forma.

Se simplificar a solução, eu ficaria bem em fazer isso para um usuário único e constante, então o postfix só precisaria observar True / False de algum script de verificação de endereço.

Não estou interessado em soluções que exijam que o postfix aceite primeiro um e-mail e, em seguida, retorne mais tarde se o endereço do destinatário for considerado inválido ("pós-fila"). Eu preciso de postfix para rejeitar durante a sessão SMTP inicial ("antes da fila").

    
por Nils Toedtmann 08.08.2014 / 16:08

1 resposta

2

Eu tenho um problema parecido com o seu. Requisito pré-fila nos deixou com três opções

Como só estamos verificando o destinatário, a delegação de política de acesso SMTP seria suficiente. O Milter e o Proxy SMTPD foram usados se precisarmos de acesso ao cabeçalho e ao corpo também.

Meu script verificador foi fornecido pelo desenvolvedor. O uso do programa só estava chamando ./myscript recipient_address qual recipient_address pelo postfix. Para fazer isso, eu uso uma versão modificada do script perl . Esse script perl me permite ler stdin, dividir a string por linha e dividir a linha com o mesmo sinal = .

Em seguida, declaro o daemon do spawn em master.cf

policy  unix    -       n             n     -     -      spawn  user=mydedicateduser argv=/path/to/perl/script.pl

Em seguida, defina-o em main.cf

smtpd_recipient_restrictions =
    ...
    reject_unauth_destination
    check_policy_service unix:private/policy
    ...

Este script abaixo pode ser substituído por outra linguagem de programação. Aqui o pseudo-código para explicar como funciona.

while True:

    get the stdin    

    if stdin = ''  # ---> the end of parameter
        call the external script with recipient parameter

        get the return code

        if recipient valid 
            print "dunno"
        else if recipient not valid
            print "reject"
        else            # ---> command error
            print "defer if permit"

        break

    else
        validate the stdin, the proper format is 'parameter=value'

        if valid
            put it in array

Para código python , você pode modificar o código deste snippet . Não há necessidade de definir o daemon de spawn.

Para completar, aqui o código-fonte completo de /path/to/perl/script.pl

#!/usr/bin/perl -w

use strict;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Getopt::Long;

#
# Syslogging options for verbose mode and for fatal errors.
# NOTE: comment out the $syslog_socktype line if syslogging does not
# work on your system.
#
my $syslog_socktype = 'unix'; # inet, unix, stream, console
my $syslog_facility = 'mail';
my $syslog_options  = 'pid';
my $syslog_priority = 'info';

# Configuration

my $executable_path = '/my/execute/script.sh';

# 
# Procedures
#

#
# Log an error and abort.
#
sub fatal_exit {
        my $first = shift @_;
        syslog "err", "fatal: $first", @_;
        exit 1;
}

# SMTPD access policy routine. The result is an action just like
# it would be specified on the right-hand side of a Postfix access
# table.    Request attributes are available via the %attr hash.
sub smtpd_access_policy() {
    system($executable_path, $attr{'recipient'});

    # -1 command error
    # 0 user isn't valid
    # else user valud
    if ( $? == -1 ) {
        # command error
        return "defer_if_permit Something error"
    }

    if ( $? == 0 ) {
        return "reject user not found";
    }

    return "dunno";
}


#
# Main program
#

#
# This process runs as a daemon, so it can't log to a terminal. Use
# syslog so that people can actually see our messages.
#
setlogsock $syslog_socktype;
openlog $0, $syslog_options, $syslog_facility;

unless(GetOptions('v:+' => \$verbose)) {
    syslog $syslog_priority, "Invalid option. Usage: %s [-v] [-v] ...", $0;
    exit 1;
}

#
# Unbuffer standard output.
#
select((select(STDOUT), $| = 1)[0]);

#
# Receive a bunch of attributes, evaluate the policy, send the result.
#
while (<STDIN>) {
    chomp;
    if (/^([^=]+)=(.*)$/) {
        $attr{substr($1, 0, 512)} = substr($2, 0, 512);
    } elsif ($_ eq '') {
        if ($verbose>2) {
            for (keys %attr) {
                syslog $syslog_priority, "Attribute: %s=%s", $_, $attr{$_};
            }
        }
        fatal_exit "unrecognized request type: '%s'", $attr{'request'}
            unless $attr{'request'} eq 'smtpd_access_policy';
        my $action = smtpd_access_policy();
        syslog $syslog_priority, "Action: %s", $action if $verbose>1;
        print STDOUT "action=$action\n\n";
        %attr = ();
    } else {
        syslog $syslog_priority, "warning: ignoring garbage: %.100s", $_;
    }
}

exit 0;
    
por 29.12.2014 / 01:21

Tags