Gossamer Forum
Home : General : Perl Programming :

SMTP Test Problems

Quote Reply
SMTP Test Problems
I was wondering if anyone here has ever written an SMTP test using IO::Socket:INET and/or IO::Select? Basically, I'm trying to connect to my mail server, make sure I got a 220, send a HELO message, and make sure I got a 250 but I'm having trouble reading the response(s) and having the code timeout during a specified time interval if no response is given:

Code:
use IO::Socket::INET;
use IO::Select;

my $addr = 'XX.XX.XX.XX';#mail server ip
my $hostname = `hostname`;
#set our timeout to 30 sec
my $timeout = 30;
my $endtime = time + $timeout;

my $line;
my $socket;
eval {
# get a connection to the ip
$socket = IO::Socket::INET->new(
PeerAddr => inet_ntoa($addr),
PeerPort => 25,
Timeout => $timeout,
Proto => 'tcp',
);
};

# show message if we couldn't connect
$ipHash{'Message'} = 'Connection refused' unless $socket; # connection refused
# get a select object & add our socket so we can do read timeouts
my $sel = IO::Select->new($socket);

#make sure we got a 220 initially
my $hello;
while ( time < $endtime && ! $@ ) {
unless ($sel->can_read( $endtime-time )) {
# returns time out
$ipHash{'Message'} .= '<br>Connection timed out';
last;
}

$socket->sysread( $line, 4096, length($line) );
print "<b>connection response</b>: |$line|<br>";
if ($line !~ /^220/m && $line) {
$ipHash{'Message'} .= "<br>Connection error: $line";
last;
} else {
$hello = 1;
$ipHash{'Message'} .= "<br>Able to connect successfully";
last;
}
}

#send a HELO if we succesfully connected
if ($hello) {
#reset timeout
my $endtime = time + $timeout;

# return timeout if we timeout waiting to write
$ipHash{'Message'} .= '<br>Connection timed before HELO' unless $sel->can_write( $timeout ); # timeout

# send the hello message
$socket->syswrite("HELO $hostname", length("HELO $hostname"));

# read lines until we get a 250 or time out
my $line;
my $ableToConnect;
while ( time < $endtime && ! $@ ) {
# read a line - should time out when the endtime is here
unless ($sel->can_read( $endtime-time )) {
# returns time out
$ipHash{'Message'} .= '<br>HELO reesponse timed out';
last;
}

$socket->sysread( $line, 4096, length($line) );
print "<b>HELO response</b>: |$line|<br>";
# check the output
if ($line =~ /^250/m) {
# finish the connection, waiting up to 10 seconds
$socket->syswrite("QUIT\n", length("QUIT\n")) if $sel->can_write( 10 );

# return ok
$ipHash{'Message'} .= "<br>Replied to HELO";
$ableToConnect = 1;
last;
}
else {
$ipHash{'Message'} .= "<br>Connection error: $line";
last;
}
}

# if we didn't connect
unless($ableToConnect) {
$ipHash{'Message'} .= "<br>Did not reply to HELO";
}
}
else {
$ipHash{'Message'} .= "<br>Could not establish connection or response timed out";
}
$socket->close();

I've never written anything like this before so any suggestions on how to make this work or better ways to make this work would be greatly appreciated.
Quote Reply
Re: [aj_araujo] SMTP Test Problems In reply to
Hmm, you could take the easy way out and use Net::SMTP module:

[root@gossamer ]# perl -MNet::SMTP -le 'my $s = Net::SMTP->new("gossamer-threads.com", Timeout => 5) or die "Failed to connect.\n"; print $s->banner; $s->quit;'
gossamer-threads.com ESMTP

[root@gossamer ]#

Cheers,

Alex
--
Gossamer Threads Inc.