#!/usr/local/bin/perl -w
# Copyright (c) 2007 George Nistorica
# All rights reserved.
# This file is part of POE::Component::Client::SMTP
# POE::Component::Client::SMTP is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself. See the LICENSE
# file that comes with this distribution for more details.
# Test PLAIN AUTH
use strict;
use lib '../lib';
use Test::More tests => 13; # including use_ok
# use Test::More qw(no_plan);
use Data::Dumper;
use Carp;
BEGIN { use_ok("IO::Socket::INET"); }
BEGIN { use_ok("POE"); }
BEGIN { use_ok("POE::Wheel::ListenAccept"); }
BEGIN { use_ok("POE::Component::Server::TCP"); }
BEGIN { use_ok("POE::Component::Client::SMTP"); }
my $smtp_message;
my @recipients;
my $from;
my $debug = 0;
$smtp_message = create_smtp_message();
@recipients = qw(
george@localhost
);
$from = 'george@localhost';
my $myhostname = 'george';
my $poco_said_hostname = undef;
my $plain_auth_string = 'AGdlb3JnZQBhYnJhY2FkYWJyYQ==';
##### SMTP server vars
my $port = 25252;
my $EOL = "\015\012";
# tests:
my %test = (
test_auth => 0,
test_no_user => 0,
test_no_pass => 0,
test_mechanism_takes_precedence_over_wrong_host => 0,
test_wrong_host => 0,
test_no_user_takes_precedence_over_wrong_port => 0,
test_invalid_mechanism_takes_precedence_over_no_user => 0,
);
my @smtp_server_responses = (
"220 localhost ESMTP POE::Component::Client::SMTP Test Server",
"250-localhost$EOL"
. "250-STARTTLS$EOL"
. "250-PIPELINING$EOL"
. "250-8BITMIME$EOL"
. "250-SIZE 32000000$EOL"
. "250-AUTH=CRAM-MD5 DIGEST-MD5 LOGIN PLAIN NTLM$EOL"
. # support broken clients
"250 AUTH=CRAM-MD5 DIGEST-MD5 LOGIN PLAIN NTLM"
, # don't want to break my unbroken client :D
"235 ok, go ahead (#2.0.0)",
"250 ok",
"250 ok",
"354 go ahead",
"250 ok 1173791708 qp 32453",
"221 localhost"
);
POE::Component::Server::TCP->new(
Port => $port,
Address => "localhost",
Domain => AF_INET,
Alias => "smtp_server",
Error => \&error_handler, # Optional.
ClientInput => \&handle_client_input, # Required.
ClientConnected => \&handle_client_connect, # Optional.
ClientDisconnected => \&handle_client_disconnect, # Optional.
ClientError => \&handle_client_error, # Optional.
ClientFlushed => \&handle_client_flush, # Optional.
ClientFilter => "POE::Filter::Line", # Optional.
ClientInputFilter => "POE::Filter::Line", # Optional.
ClientOutputFilter => "POE::Filter::Line", # Optional.
ClientShutdownOnError => 1, #
);
POE::Session->create(
inline_states => {
_start => \&start_session,
_stop => \&stop_session,
send_mail => \&spawn_pococlsmt,
pococlsmtp_success => \&smtp_send_success,
pococlsmtp_failure => \&smtp_send_failure,
},
);
POE::Kernel->run();
is( $test{test_auth}, 1, "Auth OK" );
is( $test{test_no_user}, 1, "No User" );
is( $test{test_no_pass}, 1, "No Pass" );
is( $test{test_mechanism_takes_precedence_over_wrong_host},
1, "Mech precedes wrong host" );
is( $test{test_wrong_host}, 1, "Wrong host" );
is( $test{test_no_user_takes_precedence_over_wrong_port},
1, "No User precedes wrong port" );
is( $test{test_invalid_mechanism_takes_precedence_over_no_user},
1, "Invalid Mech precedes no User" );
is( $poco_said_hostname, $myhostname, "MyHostname" );
diag("Test PLAIN AUTH");
sub start_session {
$_[KERNEL]->yield("send_mail");
}
sub spawn_pococlsmt {
# $from, $recipients, $server, $port, $smtp_message, $myhostname, $alias_append, $mech, $user, $pass
# Auth OK
pococlsmtp_create(
$from, \@recipients, 'localhost', $port,
$smtp_message, "Auth OK", $myhostname, "auth_ok",
'PLAIN', 'george', 'abracadabra',
);
# No User
pococlsmtp_create(
$from, \@recipients, 'localhost', $port,
$smtp_message, "No User", $myhostname, "No_User",
'PLAIN',, 'abracadabra',
);
# No Pass
pococlsmtp_create(
$from, \@recipients, 'localhost', $port,
$smtp_message, "No Pass", $myhostname, "no_pass",
'PLAIN', 'george',,
);
# Mech precedes wrong host
pococlsmtp_create(
$from, \@recipients,
'thereisnosuchserverthere', $port,
$smtp_message, "Mech precedes wrong host",
$myhostname, "Mech_precedes_wrong_host",
'PLAIN1', 'george',
'abracadabra',
);
# Wrong host
pococlsmtp_create(
$from, \@recipients,
'thereisnosuchserverthere', $port,
$smtp_message, "Wrong host",
$myhostname, "Wrong_host",
'PLAIN', 'george',
'abracadabra',
);
# No User precedes wrong port
pococlsmtp_create(
$from, \@recipients,
'localhost', ( $port + 1 ),
$smtp_message, "No User precedes wrong port",
$myhostname, "No_User_precedes_wrong_port",
'PLAIN',,
'abracadabra',
);
# Invalid Mech precedes no User
pococlsmtp_create(
$from, \@recipients,
'localhost', $port,
$smtp_message, "Invalid Mech precedes no User",
$myhostname, "Invalid_Mech_precedes_no_User",
'PLAIN1', '',
'abracadabra',
);
}
sub stop_session {
# stop server
$_[KERNEL]->call( smtp_server => "shutdown" );
}
sub smtp_send_success {
my ( $kernel, $arg0, $arg1 ) = @_[ KERNEL, ARG0, ARG1 ];
print "ARG0, ", Dumper($arg0), "\nARG1, ", Dumper($arg1), "\n" if $debug;
if ( $arg0 eq 'Auth OK' ) {
$test{test_auth} = 1;
}
elsif ( $arg0 eq 'No User'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_user} = 0;
}
elsif ( $arg0 eq 'No Pass'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_pass} = 0;
}
elsif ( $arg0 eq 'Mech precedes wrong host'
and $arg1->{'Configure'} eq
'ERROR: Method unsupported by Component version: '
. $POE::Component::Client::SMTP::VERSION )
{
$test{test_mechanism_takes_precedence_over_wrong_host} = 0;
}
elsif ( $arg0 eq 'Wrong host'
and exists( $arg1->{'POE::Wheel::SocketFactory'} ) )
{
$test{test_wrong_host} = 0;
}
elsif ( $arg0 eq 'No User precedes wrong port'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_user_takes_precedence_over_wrong_port} = 0;
}
elsif ( $arg0 eq 'Invalid Mech precedes no User'
and $arg1->{'Configure'} eq
'ERROR: Method unsupported by Component version: '
. $POE::Component::Client::SMTP::VERSION )
{
$test{test_invalid_mechanism_takes_precedence_over_no_user} = 0;
}
else {
warn "What the hell! $arg0\/$arg1";
}
}
sub smtp_send_failure {
my ( $kernel, $arg0, $arg1 ) = @_[ KERNEL, ARG0, ARG1 ];
print "\nARG0, ", $arg0, "\nARG1, ", Dumper($arg1) if $debug;
if ( $arg0 eq 'Auth OK' ) {
$test{test_auth} = 0;
}
elsif ( $arg0 eq 'No User'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_user} = 1;
}
elsif ( $arg0 eq 'No Pass'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_pass} = 1;
}
elsif ( $arg0 eq 'Mech precedes wrong host'
and $arg1->{'Configure'} eq
'ERROR: Method unsupported by Component version: '
. $POE::Component::Client::SMTP::VERSION )
{
$test{test_mechanism_takes_precedence_over_wrong_host} = 1;
}
elsif ( $arg0 eq 'Wrong host'
and exists( $arg1->{'POE::Wheel::SocketFactory'} ) )
{
$test{test_wrong_host} = 1;
}
elsif ( $arg0 eq 'No User precedes wrong port'
and $arg1->{'Configure'} eq
'ERROR: You want AUTH but no USER/PASS given!' )
{
$test{test_no_user_takes_precedence_over_wrong_port} = 1;
}
elsif ( $arg0 eq 'Invalid Mech precedes no User'
and $arg1->{'Configure'} eq
'ERROR: Method unsupported by Component version: '
. $POE::Component::Client::SMTP::VERSION )
{
$test{test_invalid_mechanism_takes_precedence_over_no_user} = 1;
}
else {
warn "What the hell! $arg0\/$arg1";
}
}
sub create_smtp_message {
my $body = <<EOB;
To: George Nistorica <george\@localhost>
Bcc: George Nistorica <george\@localhost>
CC: Alter Ego <root\@localhost>
From: Charlie Root <root\@localhost>
Subject: Email test
Sent with $POE::Component::Client::SMTP::VERSION
EOB
return $body;
}
sub error_handler {
carp "Something nasty happened";
exit 100;
}
sub handle_client_input {
my ( $heap, $input ) = @_[ HEAP, ARG0 ];
if ( $input =~ /^(helo|ehlo|mail from:|rcpt to:|data|\.|quit|auth)/i ) {
if ( $input =~ /^(ehlo|helo)\s(.*)$/i ) {
$poco_said_hostname = $2 if defined $2;
}
elsif ( $input eq 'PLAIN AGdlb3JnZQBhYnJhY2FkYWJyYQ==' ) {
$test{test_auth} = 1;
}
print "CLIENT SAID: $input\n" if $debug;
$heap->{'client'}->put( shift @smtp_server_responses );
}
}
sub handle_client_connect {
$_[HEAP]->{'client'}->put( shift @smtp_server_responses );
}
sub handle_client_disconnect {
}
sub handle_client_error {
}
sub handle_client_flush {
}
sub pococlsmtp_create {
my (
$from, $recipients, $server, $port,
$smtp_message, $context, $myhostname, $alias_append,
$mech, $user, $pass
) = @_;
POE::Component::Client::SMTP->send(
From => $from,
To => $recipients,
SMTP_Success => 'pococlsmtp_success',
SMTP_Failure => 'pococlsmtp_failure',
Server => $server,
Port => $port,
Body => $smtp_message,
Context => $context,
Timeout => 20,
MyHostname => $myhostname, # to test
Alias => 'poco_smtp_alias_' . $alias_append,
# Debug => 1,
Auth => {
mechanism => $mech,
user => $user,
pass => $pass,
}
);
}
syntax highlighted by Code2HTML, v. 0.9.1