Le 21/11/2017 à 16:15, Sébastien COUREAU a écrit :
Hello la liste,
Cela fait déjà quelques temps que certains de mes clients se plaignent (à plus ou moins juste titre) de ne pas recevoir certains de leurs mails.
En fait, ceux-ci sont ceux qui ont déclarés des emails forward, et qui se heurtent au SPF strict. Tout est normal et logique...
Par contre, l'alternative est de mettre en place un milter SRS ou équivalent par dessus le MX (perso, postfix, dovecot, mysql, etc.......)
Est-ce que certains d'entre vous se seraient intéressés à cette problématique d'implémentation sur du multi-domaines avec une granularité de l'ordre de l'adresse (parce que au sein d'un même domaine, toutes les boites ne sont pas forcément en forward....)
J'ai bien jeté un oeil à PostSRSd/PostForward et/ou srs-milter, mais aucun de ces 2 outils n'implémente de dictionnaire dynamique et vu l'augmentation des polices SPF strictes, cela comment à devenir presque urgent
Hello,
Nous utilisions un script perl basé sur http://dozzie.jarowit.net/blog-archive/2013/11/13/postfix-sender-rewriting-s... pour justement utiliser une DB.
Par contre, il regarde juste si le domaine est local au serveur pour définir s'il doit coder ou pas un SRS. Cela limite le nombre de requêtes SQL. Il pourrait être amélioré mais vu le travail qu'il fourni pour les 30 minutes que j'ai passé dessus, je ne vais pas me plaindre.
En gros, il suffit de définir les XXXX, de vérifier la requête SQL et de suivre le blog.
Je suis preneur de toute information et/ou conseil et/ou retour d'expérience !
#!/usr/bin/perl # # Sender Rewriting Scheme daemon suitable for Postfix TCP lookup table. # # This code was written by dozzie and is available on MIT license. #
use warnings; use strict;
use Mail::SRS; use Getopt::Long;
use DBI;
use Sys::Syslog; use Sys::Syslog qw(:standard :macros);
use Sys::Hostname::Long;
use constant { DB_HOST => '127.0.0.1', DB_USER => 'XXXXXX', DB_PASS => 'XXXXXXX', DB_DB => "XXXXXXXX", SRS_SECRET => "XXXXXXXXX", }; #-----------------------------------------------------------------------------
my $help = 0; my $rewrite_forward = 1;
my $srs_secret; my $srs_secret_file;
my $srs_max_age = 60; my $srs_hash_len = 4;
my $srs_local_domain = "xxxxx.xxx";
# when forwarding, this is the envelope sender domain my $srs_map_to_domain; # defaults to "srs.$srs_local_domain"
my $opt_status = GetOptions( "help|h" => $help, "forward" => $rewrite_forward, "reverse" => sub { $rewrite_forward = 0 }, "max-age=i" => $srs_max_age, "hash-length=i" => $srs_hash_len, "domain=s" => $srs_local_domain, "srs-domain=s" => $srs_map_to_domain, "secret-file=s" => $srs_secret_file, );
if ($help || !$opt_status) { printf "Usage: %s [--forward | --reverse] [options]\n\n", (split m[/], $0)[-1]; printf "Available options:\n"; printf " --hash-length=%d\n", $srs_hash_len; printf " Length of authentication hash added to rewritten address\n"; printf " --domain=... (required)\n"; printf " Domain served locally\n"; printf " --srs-domain=...\n"; printf " Rewritten addresses will have this as domain part.\n"; printf " Defaults to "srs.$domain".\n"; printf " --secret-file=... (required)\n"; printf " Text file with a secret used for generating authentication" . " hash.\n"; printf " Just a single line of random text.";
exit ($opt_status ? 0 : 1); }
$srs_map_to_domain = hostname_long() if not defined $srs_map_to_domain; #$srs_secret_file = "/etc/postfix/srs.secret" if not defined $srs_secret_file; #$srs_secret = do { # open my $f, $srs_secret_file or die "Can't open secret file: $!"; # $srs_secret = <$f>; #}; $srs_secret = SRS_SECRET; chomp $srs_secret;
#-----------------------------------------------------------------------------
openlog("srs", "pid", LOG_MAIL);
$| = 1;
my $srs = new Mail::SRS( Secret => $srs_secret, MaxAge => $srs_max_age, HashLength => $srs_hash_len, HashMin => $srs_hash_len, );
#-----------------------------------------------------------------------------
while (<STDIN>) { my ($op, $address) = /^(get|put) (.*)\n/;
if ($op ne 'get') { printf "500 not implemented\n"; next; }
if (not $address =~ /^(.+)@([^@]+)$/) { printf "500 not an e-mail address\n"; next; }
my ($local_part, $domain_part) = ($1, $2); my ($rewritten_address, $reason) = $rewrite_forward ? srs_forward_rewrite($address, $local_part, $domain_part) : srs_reverse_rewrite($address, $local_part, $domain_part);
if ($rewritten_address) { # TODO: encoding (`man 5 tcp_table') printf "200 %s\n", $rewritten_address; } else { printf "500 %s\n", $reason; } }
#-----------------------------------------------------------------------------
sub srs_forward_rewrite { my ($address, $user, $domain) = @_;
my $dbh = DBI->connect("DBI:mysql:".DB_DB.":".DB_HOST, DB_USER, DB_PASS, {'RaiseError' => 1}); if ( not $dbh ) { #die $DBI::errstr; #logEntry($DBI::errstr); die $DBI::errstr; } $dbh->{mysql_auto_reconnect} = 1;
my $have_aliases = $dbh->selectall_hashref( "SELECT 1 AS count FROM virtual_domains WHERE name=?", 'count', undef, $domain ); my $have_alias = 0 ;
foreach my $count ( keys %$have_aliases ) { $have_alias = $count ; }
$dbh->disconnect();
if ( $have_alias ) { return ( undef, "db local domain, skipped"); } else { if ($domain eq $srs_local_domain || $domain eq $srs_map_to_domain) { return (undef, "local domain, skipped"); } else { my $result = $srs->forward($address, $srs_map_to_domain); syslog("info", "$address -> $result"); return $result; } } }
sub srs_reverse_rewrite { my ($address, $user, $domain) = @_;
if ($domain ne $srs_map_to_domain) { return (undef, "not an SRS address"); }
local $SIG{__WARN__} = sub {}; # ignore warnings from Mail::SRS
my $result = eval { $srs->reverse($address) }; if (not $@) { syslog("info", "reverse $address -> $result"); return $result; } else { return (undef, "invalid SRS address"); } }
#----------------------------------------------------------------------------- # vim:ft=perl