LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-19-2003, 05:16 PM   #1
aj_araujo
LQ Newbie
 
Registered: Aug 2003
Posts: 1

Rep: Reputation: 0
Exclamation IO::Socket Test Difficulties


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 address
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;
	}
	
	my $bytes = $socket->sysread( $line, 4096, length($line) ); 

	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 $ableToSend;
	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 response timed out';
#						last;
#					}

		my $bytes = $socket->sysread( $line, 4096, length($line) );

			# 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";
			$ableToSend = 1;
			last;
		}
		else {
			$ipHash{'Message'} .= "<br>HELO error: $line";
			last;
		}
	}
	
	# if we didn't connect
	unless($ableToSend) {
		$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.
 
Old 08-21-2003, 07:57 AM   #2
TheLinuxDuck
Member
 
Registered: Sep 2002
Location: Tulsa, OK
Distribution: Slack, baby!
Posts: 349

Rep: Reputation: 33
I don't know about the timeout part, but here is the connection part of a working script that I use inner-office on a machine that doesn't have sendmail running on it. I basically use our email server to act as it's message gate for system messages and such.

Code:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;

my($peeraddr) = "mydomain.com";

my($answer);
my($socket) = IO::Socket::INET->new(
    PeerAddr => "mail.$peeraddr",
    PeerPort => 25,
    Proto    => "tcp",
    Type     => SOCK_STREAM
) or die "$0: Socket connect failed: $!\n";

$answer = <$socket>;
if($answer !~ /^220/) {
  print "open failed: got '$answer'\n";
  close $socket;
  exit;
}

print $socket "HELO $peeraddr\n";
$answer = <$socket>;
if($answer !~ /^250/) {
  print "HELO failed: got '$answer'\n";
  close $socket;
  exit;
}
#... rest of script clipped
I hope that helps!
 
Old 08-21-2003, 08:00 AM   #3
TheLinuxDuck
Member
 
Registered: Sep 2002
Location: Tulsa, OK
Distribution: Slack, baby!
Posts: 349

Rep: Reputation: 33
You might also consider looking into the 'alarm' function for handling timeouts and such. I've never used it, but maybe it could work well for what you're wanting to do?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
getpeername: Socket operation on non-socket KevStA Linux - General 6 08-25-2020 12:40 PM
socket: Socket type not supported monindra Fedora - Installation 4 01-14-2008 07:25 AM
cannot read data at server socket, though client socket sends it jacques83 Linux - Networking 0 11-15-2005 01:58 PM
AMD socket A, socket 754 darkangel29 Linux - Hardware 1 10-11-2005 09:56 AM
Unable to connect to UNIX socket /tmp/.esd/socket error while using grip dr_zayus69 Linux - Software 4 08-23-2005 07:28 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:22 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration