#!/usr/bin/perl
#
# expn -- convince smtp to divulge an alias expansion
# tchrist@perl.com     25-Jan-93
# updated for 5.004,   10-Sep-97
# updated for Net::DNS  3-Feb-98
#
# invoked as vrfy, will use VRFY, else use EXPN
#
# Here's my "expn" and "vrfy" program (it checks its name -- make two
# links to the same file) that tries to use the EXPN or VRFY command to
# figure out whether an address is going to work.  It's of limited use,
# but may be illustrative of coolness.  It will run with the standard
# distribution alone, but prefers to have Net::DNS handy.

use strict;
my $fetch_mx = 0;
eval {
    require Net::DNS;
    Net::DNS->import('mx');
    $fetch_mx = 1;
};
use IO::Socket;
use Sys::Hostname;

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

my $VERB = ($0 =~ /ve?ri?fy$/i)  ? 'VRFY' : 'EXPN';
my $multi = @ARGV > 1;
my $remote;

ADDR: 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);

	$remote->print("HELO $selfname\r\n");
	$remote->print("$VERB $name\r\nquit\r\n");
	while ($_ = $remote->getline) {
	    /^220\b/ && next;
	    /^221\b/ && last;
	    s/250\b[\-\s]+//;
	    print;
	} 
	close($remote) || die "can't close socket: $!";
	print "\n"; #  if @ARGV;
    }
} 

__END__