#!/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__