#!/usr/bin/perl use Sendmail::Milter; use Net::DNS; use Socket; my %my_milter_callbacks = ( 'connect' => \&connect_callback, 'helo' => \&helo_callback, 'envfrom' => \&envfrom_callback, ); my $res = Net::DNS::Resolver->new; $| = 1; sub connect_callback { my $ctx = shift; # Some people think of this as $self my $hostname = shift; my $sockaddr_in = shift; if ($hostname eq localhost) { return SMFIS_ACCEPT; } #return SMFIS_CONTINUE; print "my_connect: hostname($hostname)"; if (defined $sockaddr_in) { my ($port, $iaddr) = sockaddr_in($sockaddr_in); print " port($port)"; print " iaddr(" . inet_ntoa($iaddr) . ")"; } print "\n"; return SMFIS_CONTINUE; } sub helo_callback { my $ctx = shift; my @args = @_; printf "helo: '%s'\n",$args[0]; return SMFIS_CONTINUE; } sub envfrom_callback { my $ctx = shift; my @args = @_; #printf "envfrom: %s\n",$args[0]; # if addr is of the form <>... strip 'em. # then look for the domain part return SMFIS_CONTINUE if $args[0] !~ /\@([^>]*)(\>|$)/; $domain = $1; my @mx = mx($domain); if (@mx) { foreach $mx (@mx) { my ($name,$aliases,$type,$len,@addrs) = gethostbyname($mx->exchange); foreach $ip (@addrs) { $ipstr = join('.',unpack("C4",$ip)); if ($ipstr eq "127.0.0.1") { printf("%s MX %s %s %s\n",$domain,$mx->preference, $mx->exchange, $ipstr); $ctx->setreply("551","5.7.1","invalid loopback MX detected in return address"); return SMFIS_REJECT; } } } } else { my ($name,$aliases,$type,$len,@addrs) = gethostbyname($domain); foreach $ip (@addrs) { $ipstr = join('.',unpack("C4",$ip)); if ($ipstr eq "127.0.0.1") { printf("%s A %s\n",$domain,$ipstr); $ctx->setreply("551","5.7.1","invalid loopback A detected in return address"); return SMFIS_REJECT; } } } return SMFIS_CONTINUE; } BEGIN: { # Get myfilter's connection information # from /etc/mail/sendmail.cf Sendmail::Milter::auto_setconn("mxmilter"); Sendmail::Milter::register("mxmilter", \%my_milter_callbacks, SMFI_CURR_ACTS); Sendmail::Milter::main(); # Never reaches here, callbacks are called from Milter. }