#!/usr/local/bin/perl

# send bare LF to smtp server

use strict;
use IO::Select;
use IO::Socket::INET;

my $host = shift; # smtp server to test
my $addr = shift; # envelope sender and recipient, must be valid
my $timeout = 2;


my $sock = IO::Socket::INET->new(Proto => 'tcp',
                                 PeerAddr => $host,
                                 PeerPort => 25,
                                 Timeout => $timeout);

if($sock){
	my $select = IO::Select->new;
	$select->add($sock);

	my @banner = _getlines($select,$timeout);
	if($banner[-1] =~ /^220\s/){
		print $sock "HELO barelf.tester\n";
	}else{
		die "$host misbehaving, did not get valid banner\n";
	}

	my @helo = _getlines($select,$timeout);
	if($helo[-1] =~ /^250\s/){
		print $sock "MAIL FROM:<$addr>\n";
	}else{
		die "$host misbehaving, did not give 250 to my helo\n";
	}

	my @mf = _getlines($select,$timeout);
	if($mf[-1] =~ /^250\s/){
		print $sock "RCPT TO:<$addr>\n";
	}else{
		die "$host misbehaving, did not give 250 to my mail from\n";
	}

	my @rt = _getlines($select,$timeout);
	if($rt[-1] =~ /^250\s/){
		print $sock "DATA\n";
	}else{
		die "$host misbehaving, did not give 250 to my rcpt to\n";
	}

	my @data = _getlines($select,$timeout);
	if($data[-1] =~ /^354\s/){
		print $sock "From: <$addr>\n",
		            "To: <$addr>\n",
		            "Subject: BareLF SMTP test\n\n",
		            "body\n",
		            ".\n";
	}else{
		die "$host misbehaving, did not give 354 to my DATA: ($data[-1])\n";
	}

	my @body = _getlines($select,$timeout);
	foreach(@body){
		print "body: $_\n";
	}
	close $sock;
}else{
	die "could not make a socket on $host port 25/tcp\n";
}

sub _getlines {
	my $select = shift || die "_getlines syntax error 1";
	my $timeout = shift || die "_getlines syntax error 2";
	my @lines;
	if(my ($pending) = $select->can_read($timeout)){
		while(<$pending>){
			if(/^\d+\s/){
				chomp;
				push @lines, $_;
				last;
			}else{
				push @lines, $_;
			}
		}
	}
	return(@lines);
}

