From 252f2b72f9dbfcd1f6549d3ba148a83aa224e45c Mon Sep 17 00:00:00 2001 From: Oleg G Date: Thu, 31 Aug 2017 23:21:08 +0700 Subject: [PATCH] Handle exceptions throwed by the user from callback --- lib/Mojo/SMTP/Client.pm | 13 ++++--- lib/Mojo/SMTP/Client/Response.pm | 3 +- t/02_smtp.t | 24 ++++++++++++ t/03_smtp_nb.t | 66 ++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) diff --git a/lib/Mojo/SMTP/Client.pm b/lib/Mojo/SMTP/Client.pm index a8a5171..3b19228 100644 --- a/lib/Mojo/SMTP/Client.pm +++ b/lib/Mojo/SMTP/Client.pm @@ -146,7 +146,8 @@ sub send { $delay->on(finish => sub { if ($cb) { my $r = $_[1]; - if ($r->isa('Mojo::SMTP::Client::Exception')) { + unless ($r->isa('Mojo::SMTP::Client::Response')) { + # some error occured, which throwed an exception $r = Mojo::SMTP::Client::Response->new('', error => $r); } @@ -238,7 +239,7 @@ sub _make_cmd_steps { sub { eval { $self->{resp_checker}->(@_); $_[1]->{checked} = 1 }; if (my $e = $@) { - die $e unless $e->error->isa('Mojo::SMTP::Client::Exception::Response'); + die $e unless $e->isa('Mojo::SMTP::Client::Response'); my $delay = shift; $self->{stream}->start if !$prepend && $mi == $#cmd; # XXX: _read_response may stop stream @@ -588,7 +589,8 @@ C inherits all events from L and can emi $smtp->inactivity_timeout(5*60); }); -Emitted whenever a new connection is about to start. +Emitted whenever a new connection is about to start. You can interrupt sending by dying or throwing an exception +from this callback, C attribute of the response will contain corresponding error. =head2 response @@ -601,7 +603,8 @@ Emitted whenever a new connection is about to start. }); Emitted for each SMTP response from the server. C<$cmd> is a command L for which this -response was sent. C<$resp> is L object. +response was sent. C<$resp> is L object. You can interrupt sending by dying or +throwing an exception from this callback, C attribute of the response will contain corresponding error. =head1 ATTRIBUTES @@ -751,7 +754,7 @@ C<$resp-Emessage> (string). For blocking usage C<$resp> will be returned as result of C<$smtp-Esend> call. C<$resp> is the same as for non-blocking result. If L attribute has true value C will throw an exception on any error. -Which will be one of C. +Which will be one of C or an error throwed by the user inside or L callback. B. For SMTP protocol it is important to send commands in certain order. Also C will send all commands in order you are specified. So, it is important to pass arguments to C in right order. For basic usage this will always be: diff --git a/lib/Mojo/SMTP/Client/Response.pm b/lib/Mojo/SMTP/Client/Response.pm index d4b95d1..86b4e0c 100644 --- a/lib/Mojo/SMTP/Client/Response.pm +++ b/lib/Mojo/SMTP/Client/Response.pm @@ -87,7 +87,8 @@ C implements the following attributes =head2 error Error for this response. Should be one of C -defined in L. Default is C. +defined in L or error throwed by the user from callback. +Default is C. =head1 METHODS diff --git a/t/02_smtp.t b/t/02_smtp.t index 2eb9e16..543636e 100644 --- a/t/02_smtp.t +++ b/t/02_smtp.t @@ -1,6 +1,7 @@ use strict; use Test::More; use Mojo::SMTP::Client; +use Mojo::Exception; use Socket 'CRLF'; use lib 't/lib'; use Utils; @@ -60,4 +61,27 @@ isa_ok($e, 'Mojo::SMTP::Client::Exception::Response'); close $sock; kill 15, $pid; +# 4 +($pid, $sock, $host, $port) = Utils::make_smtp_server(); +$smtp = Mojo::SMTP::Client->new(address => $host, port => $port, autodie => 1); +syswrite($sock, join(CRLF, '220 host.net', '220 hello ok', '220 from ok', '220 to ok', '220 quit ok').CRLF); + +$smtp->on(response => sub { + my $cmd = $_[1]; + + if ($cmd == Mojo::SMTP::Client::CMD_EHLO) { + Mojo::Exception->throw("Throwed from response callback"); + } +}); + +eval { + $smtp->send(hello => 'mymail.host', from => '', to => 'jorik@gmail.com', quit => 1); +}; +my $e = $@; +is(ref $e, 'Mojo::Exception', 'got right exception'); +is($e->message, 'Throwed from response callback', 'with right message'); + +close $sock; +kill 15, $pid; + done_testing; diff --git a/t/03_smtp_nb.t b/t/03_smtp_nb.t index d794719..7ada9eb 100644 --- a/t/03_smtp_nb.t +++ b/t/03_smtp_nb.t @@ -459,6 +459,72 @@ $loop->reactor->remove($sock); close $sock; kill 15, $pid; +# 7 +($pid, $sock, $host, $port) = Utils::make_smtp_server(); +$smtp = Mojo::SMTP::Client->new(address => $host, port => $port, hello => 'dragon-host.net'); +$smtp->on(start => sub { + die "error from start callback\n"; +}); + +$smtp->send( + from => 'abc@mail.ru', + to => 'xyz@mail.ru', + data => 'smth useless', + sub { + my $resp = pop; + + ok($resp->error, "Got error from the `start' callback"); + is($resp->error, "error from start callback\n", "Got right error"); + + $loop->stop; + } +); + +$loop->start; +close $sock; +kill 15, $pid; + +# 8 +($pid, $sock, $host, $port) = Utils::make_smtp_server(); +$smtp = Mojo::SMTP::Client->new(address => $host, port => $port, hello => 'dragon-host.net'); +$smtp->on(response => sub { + my $cmd = $_[1]; + + if ($cmd == Mojo::SMTP::Client::CMD_EHLO) { + die "I don't like you\n"; + } +}); + +$i = 0; + +$smtp->send( + from => 'abc@mail.ru', + to => 'xyz@mail.ru', + data => 'smth useless', + sub { + my $resp = pop; + + ok($resp->error, "Got error from the `response' callback"); + is($resp->error, "I don't like you\n", "Got right error"); + is($i, 2, "connect -> EHLO -> die"); + + $loop->stop; + } +); + +$loop->reactor->io($sock => sub { + my $cmd = <$sock>; + return unless $cmd; # socket closed + syswrite($sock, '220 OK'.CRLF); + $i++; +}); + +$loop->reactor->watch($sock, 1, 0); +$loop->start; +$loop->reactor->remove($sock); +close $sock; +kill 15, $pid; + done_testing; __DATA__