CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
How to handle failure of sub procedures?

 



frist44
User

Jan 8, 2009, 7:30 AM

Post #1 of 15 (1552 views)
How to handle failure of sub procedures? Can't Post

I have a sub routine that sends an email and relies on a SMTP argument when called. If the SMTP isn't specified the call will obviously fail, however the logging line that occurs after the sub routine call will get skipped.

How do i gracefully handle the sub routine failure and allow the program to move to the next line, or at least test it's success/failure to execute?

Thanks!


FishMonger
Veteran / Moderator

Jan 8, 2009, 7:44 AM

Post #2 of 15 (1551 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post

Since you haven't shown use any of your code, we can't know what modifications it needs.


frist44
User

Jan 8, 2009, 8:51 AM

Post #3 of 15 (1549 views)
Re: [FishMonger] How to handle failure of sub procedures? [In reply to] Can't Post


Code
	if (ping($device_address)){ 
print SFILE "$device_address is alive.\n\n";
} else {
print SFILE "$device_address is DEAD!!! --> ";
sendEmail($email, $email_smtp, $device_address);
print SFILE "Unable to send email.\n\n";
}


The sendEmail function is what will fail without the SMTP and the line "Unable to send email" will be skipped and I'm trying to avoid that.

Thanks!


FishMonger
Veteran / Moderator

Jan 8, 2009, 9:14 AM

Post #4 of 15 (1547 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post

Where are you defining the vars that are passed to sendEmail()?

Exactly what is the sendEmail() function doing?

Does sendEmail() have a return statement?

Are you using one of the standard Perl email modules to send the email? If not, you really should, because they include methods for proper error handling.


KevinR
Veteran


Jan 8, 2009, 9:44 AM

Post #5 of 15 (1545 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post

most functions/subs return a 0 or 1 to indicate failure or success respectively. You can use that to make the function/sub call a condition:


Code
unless(	sendEmail($email, $email_smtp, $device_address)) {  
print SFILE "Unable to send email.\n\n";
}


or in reversed form:


Code
print SFILE "Unable to send email.\n\n" unless	(sendEmail($email, $email_smtp, $device_address));

-------------------------------------------------


FishMonger
Veteran / Moderator

Jan 8, 2009, 10:02 AM

Post #6 of 15 (1543 views)
Re: [KevinR] How to handle failure of sub procedures? [In reply to] Can't Post


In Reply To
most functions/subs return a 0 or 1 to indicate failure or success respectively. You can use that to make the function/sub call a condition:


A caveat, without an explicit return statement, a Perl sub will return the value returned from the last statement it executed, which may not be what you exepect when it's evaluated in boolean context. If the sending of the email failed, but the last statement executed was, for example, a print statement, then the sub will return a true value.


frist44
User

Jan 8, 2009, 11:20 AM

Post #7 of 15 (1539 views)
Re: [FishMonger] How to handle failure of sub procedures? [In reply to] Can't Post

I'm using Net::SMTP to send mail:


Code
# This subroutine sends an email using Net::SMTP 
sub sendEmail
{
# Bring in the passed parameters
my ($s_email, $s_smtp, $s_ip) = @_;

# Create mail object and set headers
my $smtp = Net::SMTP->new($s_smtp, Timeout => 60);
$smtp->mail($s_email);
$smtp->to($s_email);

$smtp->data();

# Set from, to and subject fields
$smtp->datasend("From: $s_email\n");
$smtp->datasend("To: $s_email\n");
$smtp->datasend("Subject: $s_ip is NOT responding!!!");
$smtp->datasend("\n");

# Set email body
$smtp->datasend("Importance: high\n");
$smtp->datasend(ctime());
$smtp->datasend("\n");
$smtp->datasend("\n");
$smtp->datasend("IP Address: $s_ip\n");

$smtp->dataend();
$smtp->quit;
}



frist44
User

Jan 8, 2009, 11:37 AM

Post #8 of 15 (1536 views)
Re: [KevinR] How to handle failure of sub procedures? [In reply to] Can't Post

Ideally, I would like to have it run the sendEmail sub, and if successful, write:

Email sent successfully

If not successful, write:

Unable to send email

Can you point me in the right direction?


KevinR
Veteran


Jan 8, 2009, 1:31 PM

Post #9 of 15 (1535 views)
Re: [FishMonger] How to handle failure of sub procedures? [In reply to] Can't Post


In Reply To

In Reply To
most functions/subs return a 0 or 1 to indicate failure or success respectively. You can use that to make the function/sub call a condition:


A caveat, without an explicit return statement, a Perl sub will return the value returned from the last statement it executed, which may not be what you exepect when it's evaluated in boolean context. If the sending of the email failed, but the last statement executed was, for example, a print statement, then the sub will return a true value.


Blush good catch Fish
-------------------------------------------------


KevinR
Veteran


Jan 8, 2009, 1:37 PM

Post #10 of 15 (1534 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post


In Reply To
Ideally, I would like to have it run the sendEmail sub, and if successful, write:

Email sent successfully

If not successful, write:

Unable to send email

Can you point me in the right direction?


Something like this looks like it should work. Test it out.


Code
if (ping($device_address)){  
print SFILE "$device_address is alive.\n\n";
}
else {
print SFILE "$device_address is DEAD!!! --> ";
if (sendEmail($email, $email_smtp, $device_address) {
print SFILE "Email sent successfully\n\n";
}
else {
print SFILE "Unable to send email.\n\n";
}
}

-------------------------------------------------


(This post was edited by KevinR on Jan 8, 2009, 1:38 PM)


frist44
User

Jan 8, 2009, 3:08 PM

Post #11 of 15 (1530 views)
Re: [KevinR] How to handle failure of sub procedures? [In reply to] Can't Post

I tried this, but no luck. It seems the sendemail sub isn't outputting anything that's true or false so it just stops


Code
	if (ping($device_address)){ 
print SFILE "$device_address is alive.\n\n";
} else {
print SFILE "$device_address is DEAD!!! --> ";
if (sendEmail($email, $email_smtp, $device_address)){
print "Email notification sent to $email via $email_smtp\n\n";
} else {
print SFILE "Unable to send email notification";
}
}


This is the output file:
# Created Thu Jan 8 18:06:43 2009
google.com is DEAD!!! -->


FishMonger
Veteran / Moderator

Jan 8, 2009, 3:59 PM

Post #12 of 15 (1526 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post

The main advantage of using Net::SMTP is that it's a core module. However, IMO its syntax is a little "noisy". I prefer to use MIME::Lite.
http://search.cpan.org/~rjbs/MIME-Lite-3.023/lib/MIME/Lite.pm

Try this version, which assumes that you've already verified that the passed in vars are properly defined.

Code
sub sendEmail  
{
# Bring in the passed parameters
my ($s_email, $s_smtp, $s_ip) = @_;

# Create mail object and set headers
my $smtp = Net::SMTP->new($s_smtp, Timeout => 60);
if (! $smtp) {
warn "Failed to connect to $s_smtp smtp server\n";
return undef;
}

$smtp->mail($s_email);
$smtp->to($s_email);

$smtp->data();

# Set from, to and subject fields
$smtp->datasend("From: $s_email\n");
$smtp->datasend("To: $s_email\n");
$smtp->datasend("Subject: $s_ip is NOT responding!!!");
$smtp->datasend("\n");

# Set email body
$smtp->datasend("Importance: high\n");
$smtp->datasend(ctime());
$smtp->datasend("\n");
$smtp->datasend("\n");
$smtp->datasend("IP Address: $s_ip\n");

my $status = $smtp->dataend();

$smtp->quit;

return $status;
}


Or my preference, which uses MIME::Lite

Code
sub sendEmail 
{
my ($s_email, $s_smtp, $s_ip) = @_;

my $message = "Importance: high\n"
. ctime()
. "\n\n"
. "IP Address: $s_ip\n";

MIME::Lite->send('smtp', $s_smtp, Timeout=>60);

my $msg = MIME::Lite->new(
From => $s_email,
To => $s_email,
Subject => "$s_ip is NOT responding!!!",
Data => $message

);
$msg->send;
}



(This post was edited by FishMonger on Jan 8, 2009, 4:00 PM)


frist44
User

Jan 9, 2009, 5:58 AM

Post #13 of 15 (1518 views)
Re: [FishMonger] How to handle failure of sub procedures? [In reply to] Can't Post

The first piece worked perfect and passed everything through. That was my mistake, I should've realized just attached a variable to the $smtp->dataend(); would give it a true/false kind of thing.

The second piece is indeed much simpler, but it doesn't seem to work in windows with the default installation of the ActivePerl, which is where this will run.

Let me know if I'm not doing something right.

Thanks again!


FishMonger
Veteran / Moderator

Jan 9, 2009, 6:16 AM

Post #14 of 15 (1517 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post

MIME::Lite is not a core module, so you'll need to install it via the ppm utility.


KevinR
Veteran


Jan 9, 2009, 9:39 AM

Post #15 of 15 (1513 views)
Re: [frist44] How to handle failure of sub procedures? [In reply to] Can't Post


In Reply To
The first piece worked perfect and passed everything through. That was my mistake, I should've realized just attached a variable to the $smtp->dataend(); would give it a true/false kind of thing.

The second piece is indeed much simpler, but it doesn't seem to work in windows with the default installation of the ActivePerl, which is where this will run.

Let me know if I'm not doing something right.

Thanks again!


While I agree with Fish about MIME::Lite, using Net::SMTP is OK. If your code is now working (thanks for the assist Fish) then you can leave it as is unless you really want to try MIME::Lite.
-------------------------------------------------

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives