|
ru.unix.bsd- RU.UNIX.BSD ------------------------------------------------------------------ From : Timur Khanjanov 2:5020/400 01 Mar 2006 13:00:45 To : Alexander Fatykhov Subject : Re: postfix vs. unsolicited bounces -------------------------------------------------------------------------------- В письме Wed, 01 Mar 2006 07:50:50 +0000, Alexander Fatykhov написал: > Hello, All! > > TK> у меня на цирусе я сделал через полиси > TK> демон который у цируса по smmap спрашивает > > о, а тут можно попродробней, а то через > local_recipient_maps = hash:/usr/local/etc/postfix/users, > hash:/usr/local/etc/postfix/aliases > как-то неитнеросно, надо и в cyrus добавить юзера и в файл прописать... smtpd_recipient_restrictions=...,check_policy_service inet:localhost:2505 в cyrus.conf smmapd cmd="smmapd" listen="140" prefork=0 и небольшой демон на 2505м порту использующий модуль SMMap SMMap.pm -- package SMMap; use strict; use IO::Socket; use Text::Netstring qw(netstring_read netstring_decode); use vars qw($VERSION @ISA @EXPORT_OK); require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw( smmap_connect smmap_query ); $VERSION = '0.01'; #die "usage: $0 <connection> <mapname> <key> [<key2> ...]" if (@ARGV < 3); sub smmap_connect { my $connection = shift @_; my $mapname = shift @_; my $sock; if ($connection =~ /tcp:(.+):([0-9]*)/) { $sock = new IO::Socket::INET ( PeerAddr => $1, PeerPort => $2, Proto => 'tcp', ); } elsif ($connection =~ /((unix)|(local)):(.+)/) { $sock = new IO::Socket::UNIX ( Type => SOCK_STREAM, Peer => $4 ); } else { die "unrecognized connection specification $connection"; } return $sock; } sub smmap_query { my ($sock,$mapname,$key)=@_; my $request = "$mapname $key"; print $sock length($request),':'.$request.','; $sock->flush(); my $response = netstring_decode(netstring_read($sock)); return $response; } - --- policyd.pl ---- #!/usr/bin/perl -Tw use Net::Server::PreForkSimple; @ISA = qw(Net::Server::PreForkSimple); use strict; use Data::Dumper; use POSIX; use DB_File; use DBI; use SMMap qw( smmap_connect smmap_query); $| = 1; delete $ENV{ENV}; $ENV{PATH} = '/bin:/usr/bin:'; my %thash; my %vhash; main->run(conf_file=>'policyd.conf'); exit; sub options { my $self = shift; my $prop = $self->{server}; my $ref = shift; $self->SUPER::options($ref); foreach ( qw( smmap smtransports transportfile transportsql virtualfile virtualsql ) ){ $prop->{$_} = undef unless exists $prop->{$_}; $ref->{$_} = \$prop->{$_}; } } sub child_init_hook { my $self=shift; $self->{'server'}->{'smsock'}=smmap_connect($self->{'server'}->{'smmap'}); $self->{'server'}->{'transports'}=\%thash; $self->{'server'}->{'virtuals'}=\%vhash; #$self->log(4, ); my ($sqlhost,$sqluser,$sqlpass,$sqldb,$sqlrequest)=parsesqlconf($self,$self->{'serv er'}->{'transportsql'}); $self->{'server'}->{'transportreq'}=$sqlrequest; $self->{'server'}->{'transportdb'}=dbconnect($sqlhost,$sqluser,$sqlpass,$sql db); ($sqlhost,$sqluser,$sqlpass,$sqldb,$sqlrequest)=parsesqlconf($self,$self->{' server'}->{'virtualsql'}); $self->{'server'}->{'virtualreq'}=$sqlrequest; $self->{'server'}->{'virtualdb'}=dbconnect($sqlhost,$sqluser,$sqlpass,$sqldb ); #$self->log(4, Dumper($self)); } sub parsesqlconf { my ($self,$conffile)=@_; my %conf; open(CONF,$conffile); while(<CONF>) { s/\#.*//; s/^\s+//g; s/\s+$//g; s/\s+/ /g; s/\s+=\s+/=/; if(/^([a-zA-Z_]+)=(.*)/){ $conf{$1}=$2; } } #$self->log(5,"sql config ". Dumper(\%conf)); my $request='select '.$conf{'select_field'}.' from '.$conf{'table'}.' where '.$conf{'where_field'}.'=? '.$conf{'additional_conditions'}; return ($conf{'hosts'},$conf{'user'},$conf{'password'},$conf{'dbname'},$request); } sub post_configure_hook { my $self=shift; } sub process_request{ my $self=shift; my %request; if(getrequest($self,\%request)){ if((my $result=process($self,\%request)) ne '') { $self->log(4,"action is $result"); print "action=".$result."\n\n"; } } } sub getrequest { my ($self,$request)=@_; while ((my $line=getline($self)) ne ''){ $line=~s/^\s+//; $line=~s/\s+$//; my ($key,$value)=split('=',$line); $$request{$key}=$value; }; return 1; } sub getline { my $self=shift; my $line=<STDIN>; $line=~s/[\r\n]//g; $self->log(4,"get policy line '$line'\n"); return $line; } sub process { my ($self,$request)=@_; #$self->log(5,Dumper($request)); my $smanswer=smmap_query($self->{'server'}->{'smsock'},'imap',$request->{'sender'}) ; $self->log(3,'Sender '.$request->{'sender'}.' answer is '.$smanswer); if($smanswer =~/^OK.*/) { }else { } foreach my $recipient(checklocal($self,$request->{'recipient'})){ $recipient=~s/@(online\.az|intrans\.az)//; $smanswer=smmap_query($self->{'server'}->{'smsock'},'imap',$recipient); $self->log(3,'Recipient '.$request->{'recipient'}.' answer is '.$smanswer); if($smanswer =~/^OK.*/) { }else { return 'REJECT '.$smanswer; } } return 'DUNNO'; } sub checklocal { my($self,$addr)=@_; $self->log(4,'Checking address '.$addr); my @localaddrs=(); $addr=virtualize($self,$addr); my @virtaddrs=split(',',$addr); foreach my $virt (@virtaddrs) { my $transport=gettransport($self,$virt); $self->log(4,'Address '.$addr.' has transport '.$transport); if(smtransport($self,$transport)){ push @localaddrs,$virt; } } return @localaddrs; } sub virtualize { my($self,$addr)=@_; my $virtaddr=$addr; if(defined ($self->{'server'}->{'virtuals'}->{$addr."\000"})) { $virtaddr= $self->{'server'}->{'virtuals'}->{$addr."\000"}; }elsif (defined ($self->{'server'}->{'virtuals'}->{'@'.domain($addr)."\000"})){ $virtaddr=$self->{'server'}->{'virtuals'}->{'@'.domain($addr)."\000"}; }else{ my $res=$self->{'server'}->{'virtualdb'}->selectcol_arrayref($self->{'server'}->{'v irtualreq'},undef,$addr); if(defined($$res[0])){ $virtaddr=$$res[0]; }else{ $res=$self->{'server'}->{'virtualdb'}->selectcol_arrayref($self->{'server'}->{'v irtualreq'},undef,'@'.domain($addr)); if(defined($$res[0])){ $virtaddr=$$res[0]; } } } if($addr ne $virtaddr){ my @virtaddrs=split(',',$virtaddr); foreach my $virt (@virtaddrs) { if($virt ne $addr){ $virt=virtualize($self,$virt); } } $virtaddr=join(',',@virtaddrs); } $self->log(4,'Address '.$addr.' was converted to '.$virtaddr); return $virtaddr; } sub dbconnect { my ($sqlhost,$sqluser,$sqlpass,$sqldb)=@_; my $db=DBI->connect("dbi:Pg:dbname=$sqldb;host=$sqlhost",$sqluser,$sqlpass); return $db; } sub domain { my($addr)=@_; $addr=~m/.*@(.*)/; return $1; } sub smtransport { my($self,$transport)=@_; my @transports=split(',',$self->{'server'}->{'smtransports'}); foreach (@transports) { if($transport eq $_){ return 1; } } return 0; } sub gettransport { my($self,$addr)=@_; my $trans=''; $self->log(4,'Get transport for '.$addr); my @variants=avariants($addr); foreach (@variants){ $self->log(4,'Check transport for '.$_); if(defined ($self->{'server'}->{'transports'}->{$_."\000"})) { $trans= $self->{'server'}->{'transports'}->{$_."\000"}; last; }else{ my $res=$self->{'server'}->{'transportdb'}->selectcol_arrayref($self->{'server'}->{ 'transportreq'},undef,$_); if(defined($$res[0])){ $trans=$$res[0]; last; } } } if($trans=~m/(^[a-z]+):.*/){ return $1; }else{ return 'UNKNOWN'; } } sub avariants { my ($addr)=@_; my @variants; push @variants ,$addr; push @variants ,domain($addr); my @domp=split('\.',domain($addr)); for(my $i=1;$i<=$#domp;$i++){ my $dpart='.'.join('.',@domp[$i..$#domp]); push @variants,$dpart; } return @variants; } ---- не слишком изячно но работает да - это придётся точить под себя в частности у меня транспорты и виртуалы из базы берутся -- Homo Homini domini est --- ifmail v.2.15dev5.3 * Origin: MTU-Intel ISP (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.unix.bsd/10169d0b5a58a.html, оценка из 5, голосов 10
|