#!/usr/bin/perl -w
# expn -- convince smtp to divulge an alias expansion
use strict;
use IO::Socket;
use Sys::Hostname;

my $fetch_mx = 0;
# try loading the module, but don't blow up if missing
eval {    
    require Net::DNS;
    Net::DNS->import('mx');
    $fetch_mx = 1;
};

my $selfname = hostname();
die "usage: $0 address\@host ...\n" unless @ARGV;

# Find out whether called as "vrfy" or "expn".
my $VERB = ($0 =~ /ve?ri?fy$/i)  ? 'VRFY' : 'EXPN';
my $multi = @ARGV > 1;
my $remote;

# Iterate over addresses give on command line.
foreach my $combo (@ARGV) {
    my ($name, $host) = split(/\@/, $combo);
    my @hosts;
    $host ||= 'localhost';
    @hosts = map { $_->exchange } mx($host)     if $fetch_mx;
    @hosts = ($host)   unless @hosts;

    foreach my $host (@hosts) { 
        print $VERB eq 'VRFY' ? "Verify" : "Expand", 
            "ing $name at $host ($combo):";

        $remote = IO::Socket::INET->new(
    		       Proto    => "tcp",
    		       PeerAddr => $host,
    		       PeerPort => "smtp(25)",
    		   ); 

        unless ($remote) { 
            warn "cannot connect to $host\n";
            next;
        }
        print "\n";

        $remote->autoflush(1);

        # use CRLF network line terminators
        print $remote "HELO $selfname\015\012";
        print $remote "$VERB $name\015\012";
        print $remote "quit\015\012";
        while (<$remote>) {
    	        /^220\b/ && next;
    	        /^221\b/ && last;
    	        s/250\b[\-\s]+//;
    	        print;
        } 
        close($remote)			or die "can't close socket: $!";
        print "\n"; #  if @ARGV;
    }
}