OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
Subject: PIPELINING problem?
From: Claus Assmann (ca+postfix-usersesmtp.org)
Date: Fri Dec 22 2000 - 19:58:10 CST


Ok, at the risk of embarassing myself, I'll ask here... I've
implemented SMTP PIPELINING in an MTA and test it against two other
MTAs. This test revealed an interoperability problem between my MTA
and Postfix. Now I'm trying to figure out what's going wrong. The
test is as follows: send one e-mail with two recipients to a postfix
MTA, the first of which is a non-existent user such that postfix
returns 550 for it. The problem is that my MTA now hangs after
reading that line, select() on the socket doesn't show readable
data. To figure out what's going on I wrote a Perl program which
exhibits the same behaviour as my MTA. However, I almost never write
Perl programs, so it might be that both my MTA and the Perl program
are wrong. I'm looking for help... (BTW: MTA and Perl program work
fine when testing against qmail, the only other MTA I tried).

The Perl program is down below, it does a select() in a loop
to read character after character. I know this isn't a valid
SMTP client, but it's good enough for testing (IMHO).
Any help is very welcome!

#!/usr/bin/perl
# socket library
use IO::Socket;
use IO::Select;

$host="HOST"; # REPLACE this
$port = 25;
$sock = IO::Socket::INET->new(PeerAddr => $host,
        PeerPort => 'smtp(25)', Proto => 'tcp');

$sock->autoflush(1);
$sel = IO::Select->new();
$sel->add($sock);

print "Waiting for 220\n";
&reply(2);
&smtpmsg("HELO CLIENT\r\n");
&reply(2);
&smtpmsg("MAIL From:<>\r\n");
print "try to read reply for MAIL\n";
&reply(2);

# REPLACE here
&smtpmsg("RCPT To:<nonexistent\HOST>\r\nRCPT To:<user\HOST>\r\nDATA\r\n");

print "try to read reply for RCPT\n";
&reply(30);
print "try to read reply for RCPT\n";
&reply(5);
print "try to read reply for DATA\n";
&reply(5);

&smtpmsg("Subject: test\r\n\r\n1\r\n.\r\n");
print "try to read reply for .\n";
&reply(5);

&smtpmsg("QUIT\r\n");
print "try to read reply for QUIT\n";
&reply(5);

close S;

exit;

sub smtpmsg()
{
 local($msg) = _;
 print $msg;
 $res = $sock->print($msg);
}

sub reply()
{
 my($lto) = _;
 my $buf, $msg, $len;

 $buf ='';
 $msg ='';
 do {
   ready = $sel->can_read($lto);
   $nfound = ready;
   if (ready > 0)
   {
     $ret = $sock->sysread($msg,1);
     $buf .= $msg;
     $len = length($buf);
   }
   else
   {
     print "timeout? nfound: $nfound\n";
   }
 } while (length($buf) == 0 || $msg ne "\n");
 printf("read \"%s\"\n", $buf);
}

__END__