#!/usr/bin/env perl # Copyright (c) 2005 - 2008 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. # $Id: 040-transaction-log.t,v 1.2 2008/05/12 08:15:07 UltraDM Exp $ use strict; # check that by default the transaction log is disabled when SMTP_Success - ARG1 undefined # check that by default the transaction log is disabled when SMTP_Failure - ARG1 undefined # check that when enabled, you really get the transaction log when SMTP_Success - ARG1 # check that when enabled, you really get the transaction log when SMTP_Failure - ARG2 use lib q{../lib}; use Test::More tests => 9; # including use_ok use Data::Dumper; use Carp; BEGIN { use_ok(q{IO::Socket::INET}); } BEGIN { use_ok(q{POE}); } BEGIN { use_ok(q{POE::Wheel::ListenAccept}); } BEGIN { use_ok(q{POE::Component::Server::TCP}); } BEGIN { use_ok(q{POE::Component::Client::SMTP}); } # the tests we're running my %test = ( q{transaction_log_disabled_smtp_failure} => 0, q{transaction_log_disabled_smtp_success} => 0, q{transaction_log_enabled_smtp_failure} => 0, q{transaction_log_enabled_smtp_success} => 0, ); my $smtp_message; my @recipients; my $from; my $debug = 0; $smtp_message = create_smtp_message(); @recipients = qw( george@localhost, root@localhost, george.nistorica@localhost, ); $from = q{george@localhost}; ##### SMTP server vars my $port = 25252; my $EOL = qq{\015\012}; my @smtp_server_responses = ( q{220 localhost ESMTP POE::Component::Client::SMTP Test Server}, qq{250-localhost$EOL} . qq{250-PIPELINING$EOL} . qq{250-SIZE 250000000$EOL} . qq{250-VRFY$EOL} . qq{250-ETRN$EOL} . q{250 8BITMIME}, q{250 Ok}, # mail from q{250 Ok}, # rcpt to: q{250 Ok}, # rcpt to:, cc q{250 Ok}, # rctp to:, bcc q{354 End data with .}, # data q{250 Ok: queued as 549B14484F}, # end data q{221 Bye}, # quit ); # create the SMTP server session POE::Component::Server::TCP->new( q{Port} => $port, q{Address} => q{localhost}, q{Domain} => AF_INET, q{Alias} => q{smtp_server}, q{Error} => \&error_handler, # Optional. q{ClientInput} => \&handle_client_input, # Required. q{ClientConnected} => \&handle_client_connect, # Optional. q{ClientDisconnected} => \&handle_client_disconnect, # Optional. q{ClientError} => \&handle_client_error, # Optional. q{ClientFlushed} => \&handle_client_flush, # Optional. q{ClientFilter} => q{POE::Filter::Line}, # Optional. q{ClientInputFilter} => q{POE::Filter::Line}, # Optional. q{ClientOutputFilter} => q{POE::Filter::Line}, # Optional. q{ClientShutdownOnError} => 1, # ); # create the pococlsmtp master session # 4 of them :) foreach my $key ( keys %test ) { POE::Session->create( q{inline_states} => { q{_start} => \&start_session, q{_stop} => \&stop_session, q{send_mail} => \&spawn_pococlsmt, q{pococlsmtp_success} => \&smtp_send_success, q{pococlsmtp_failure} => \&smtp_send_failure, }, q{heap} => { q{test} => $key, } # store the test name for each session ); } POE::Kernel->run(); # run tests foreach my $key ( keys %test ) { my $name = $key; $name =~ s/_/ /g; is( $test{$key}, 1, $name ); } sub start_session { carp q{start_session} if ( $debug == 2 ); $_[KERNEL]->yield(q{send_mail}); } sub spawn_pococlsmt { carp q{spawn_pococlsmt} if ( $debug == 2 ); my $heap = $_[HEAP]; my %parameters = ( q{From} => $from, q{To} => \@recipients, q{SMTP_Success} => q{pococlsmtp_success}, q{SMTP_Failure} => q{pococlsmtp_failure}, q{Server} => q{localhost}, q{Port} => $port, q{Body} => $smtp_message, q{Context} => q{test context}, q{Debug} => 0, ); # depending on which test we're running there are some things to be # modified as well. look also for the Server how it does handle client connection if ( $heap->{q{test}} eq q{transaction_log_enabled_smtp_success} ) { $parameters{q{TransactionLog}} = 1; } if ( $heap->{q{test}} eq q{transaction_log_enabled_smtp_failure} ) { $parameters{q{TransactionLog}} = 1; $parameters{q{MyHostname}} = q{Fail}; } elsif ( $heap->{q{test}} eq q{transaction_log_disabled_smtp_failure} ) { $parameters{q{MyHostname}} = q{Fail}; } POE::Component::Client::SMTP->send(%parameters); } sub stop_session { # stop server carp q{stop_session} if ( $debug == 2 ); $_[KERNEL]->call( q{smtp_server} => q{shutdown} ); } sub smtp_send_success { my ( $arg0, $arg1, $heap ) = @_[ ARG0, ARG1, HEAP ]; print q{SMTP_Success: ARG0, }, Dumper($arg0), qq{\nARG1, }, Dumper($arg1), qq{\n} if $debug; if ( $heap->{q{test}} eq q{transaction_log_disabled_smtp_success} ) { if ( not defined $arg1 ) { $test{ $heap->{q{test}} } = 1; } } elsif ( $heap->{q{test}} eq q{transaction_log_enabled_smtp_success} ) { # do we have a transaction log? if ( defined $arg1 ) { # this is how it should be if ( compare_transaction_logs( $arg1, return_transaction_log() ) ) { $test{ $heap->{q{test}} } = 1; } } } } sub smtp_send_failure { my ( $arg0, $arg1, $arg2, $heap ) = @_[ ARG0, ARG1, ARG2, HEAP ]; print q{SMTP_Failure: ARG0, }, Dumper($arg0), qq{\nARG1, }, Dumper($arg1), qq{\n} if $debug; if ( $heap->{q{test}} eq q{transaction_log_disabled_smtp_failure} ) { if ( not defined $arg2 ) { $test{ $heap->{q{test}} } = 1; } } elsif ( $heap->{q{test}} eq q{transaction_log_enabled_smtp_failure} ) { if ( defined $arg2 ) { if ( compare_transaction_logs( $arg2, return_failed_transaction_log() ) ) { $test{ $heap->{q{test}} } = 1; } } } } sub create_smtp_message { my $body = < CC: Root Bcc: Alter Ego From: Charlie Root Subject: Email test Sent with $POE::Component::Client::SMTP::VERSION EOB return $body; } sub error_handler { my ( $syscall_name, $error_number, $error_string ) = @_[ ARG0, ARG1, ARG2 ]; die qq{SYSCALL: $syscall_name, ERRNO: $error_number, ERRSTR: $error_string}; } sub handle_client_input { my ( $heap, $input ) = @_[ HEAP, ARG0 ]; carp q{handle_client_input} if ( $debug == 2 ); if ( $input =~ /^ehlo fail/io or $input =~ /^helo fail/io ) { # this is for the error part $heap->{q{client}}->put(q{500 error}); } elsif ( $input =~ /^(ehlo|helo|mail from:|rcpt to:|data|\.|quit)/io ) { my $client = $heap->{q{client}}; $heap->{q{client}} ->put( shift @{ $heap->{q{smtp_server_responses}}->{$client} } ); } } sub handle_client_connect { my $heap = $_[HEAP]; my $client = $heap->{q{client}}; @{ $heap->{q{smtp_server_responses}}->{$client} } = @smtp_server_responses; $heap->{q{client}} ->put( shift @{ $heap->{q{smtp_server_responses}}->{$client} } ); } sub handle_client_disconnect { my $heap = $_[HEAP]; my $client = $heap->{q{client}}; delete $heap->{q{smtp_server_responses}}->{$client}; carp q{handle_client_disconnect} if ( $debug == 2 ); } sub handle_client_error { my $heap = $_[HEAP]; my $client = $heap->{q{client}}; delete $heap->{q{smtp_server_responses}}->{$client}; carp q{handle_client_error} if ( $debug == 2 ); } sub handle_client_flush { carp q{handle_client_flush} if ( $debug == 2 ); } sub return_failed_transaction_log { my @transaction_log = ( q{<- 220 localhost ESMTP POE::Component::Client::SMTP Test Server}, q{-> HELO Fail}, q{<- 500 error} ); return \@transaction_log; } sub return_transaction_log { my @transaction_log = ( q{<- 220 localhost ESMTP POE::Component::Client::SMTP Test Server}, q{-> HELO localhost}, q{<- 250-localhost}, q{<- 250-PIPELINING}, q{<- 250-SIZE 250000000}, q{<- 250-VRFY}, q{<- 250-ETRN}, q{<- 250 8BITMIME}, q{-> MAIL FROM: }, q{<- 250 Ok}, q{-> RCPT TO: }, q{<- 250 Ok}, q{-> RCPT TO: }, q{<- 250 Ok}, q{-> RCPT TO: }, q{<- 250 Ok}, q{-> DATA}, q{<- 354 End data with .}, q{-> To: George Nistorica CC: Root Bcc: Alter Ego From: Charlie Root Subject: Email test Sent with } . $POE::Component::Client::SMTP::VERSION . q{ } . qq{\r} . q{.}, q{<- 250 Ok: queued as 549B14484F}, q{-> QUIT}, q{<- 221 Bye} ); return \@transaction_log; } sub compare_transaction_logs { my $transaction_log = shift; my $expected_transaction_log = shift; my $same = 1; my ( @actual, @expected ); foreach my $line ( @{$transaction_log} ) { $line =~ s /(\r)|(\n)|(\r\n)//g; } foreach my $line ( @{$expected_transaction_log} ) { $line =~ s /(\r)|(\n)|(\r\n)//g; } if ( scalar @{$transaction_log} != scalar @{$expected_transaction_log} ) { warn q{Transaction logs differ!}; $same = 0; } else { for ( my $i = 0 ; $i < scalar @{$transaction_log} ; $i++ ) { if ( $transaction_log->[$i] ne $expected_transaction_log->[$i] ) { $same = 0; last; } } } return $same; }