• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4087
  • Last Modified:

Net::SMTP Unexpected EOF error

I've searched the net, and couldn't find anything about a problem I'm having with Net::SMTP.
Could you suggest something or direct me somewhere about this problem ?  Ultimately I'm looking to get it resolved.
 
I get the error at various parts of the SMTP conversation, either after $smtp->to or $stmp->dataend(), etc.
The logs are like this:
Net::SMTP=GLOB(0x80664e4)>>> .
Net::SMTP: Unexpected EOF on command channel at smtp.pl line 163
 
From what it looks like, remote server drops the connection unexpectedly, yet I may be wrong.  I want to be able to know when this happens, so I can deal with it in my script.

I tried if (undef($stmp)) die "EOF error again";
However, this doesn't do it.  Even though $smtp should NOT be defined anymore, it seems to still 'be there", and program skips right past it.  Hence the script continues on (much faster though, since it doesn't really send anymore), and tells me that ALL emails were sent, when in fact the script stopped sending emails after the EOF error.  The only way to find out where it really stopped sending is to go to the log, where I found that EOF error.  What I want to do is to automatically stop any and all processing when that error happens.  In other words, do something like throw () catch () exception handling and deal with it from there.  Or anything else that will do the job.

Is there a way to do that ?  

thanks,
Dennis
0
dennismv
Asked:
dennismv
  • 5
  • 3
  • 3
  • +1
1 Solution
 
kanduraCommented:
I thnk you may be able to test for it by looking at the return value from each call. They should return false or undef if they fail.
To put it in a try-catch style, wrap it in an eval and call each method as
$smtp->method() or die "Something descriptive";

Part of the descriptive message might be the returned status message: $smtp->code() or $smtp->message(). See the Net::Cmd doc for more details.

The eval will also take care of the instances where your $smtp object is undefined.
0
 
ahoffmannCommented:
could you please post relevant parts of your code (including the use and new statements)
0
 
dennismvAuthor Commented:
thanks. .  I'm still testing it

code so far..
use Net::SMTP;  
use strict;

$smtp=Net::SMTP->new($server, Timeout => 15, Debug => 1);
########################################      
$smtp->mail($mailfrom);        

$smtp->to( $mailto );
$smtp->data();       # Start the mail  

# headers  
$smtp->datasend("From:  $mailfrom\n");  
$smtp->datasend("To:  $mailto\n");
$smtp->datasend("Subject: $subject\n");  
$smtp->datasend("\n");

# body.  
$smtp->datasend("$message\n\n");
$smtp->dataend(); # Send the termination string  
########################################      

What I did, I put "or last;" at the end of each $smtp command instead of "or die 'desc.message';", because I have the above in a while loop
I don't know if it works yet, haven't had any errors.  I'll test it some more to make sure it does work.

Dennis
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
amandeepCommented:
dennismv,

I would advise you to use "\r\n" instead of "\n" in $smtp->datasend() method.
Let me know if this solves your problem.

Also are you trying to send some attachments?
Let me know.

Aman
:-)


0
 
dennismvAuthor Commented:
no, no attachments, thanks for \r\n, I'll put it in.
but why ?  I thought \r\n is for more Windows, while \n is for unix encoding.  what's the difference ?

Dennis

0
 
ahoffmannCommented:
what is $server set too?
and you're missing a final
$smtp->quit();
0
 
kanduraCommented:
don't worry about the newline differences. Officially the SMTP protocol (and many other protocols) specify \r\n as newline character, but Net::SMTP takes care of that for you. See the documentation of Net::Cmd:
"datasend ( DATA )
    Send data to the remote server, converting LF to CRLF."

What I tried to explain with wrapping the smtp conversation in an eval block is the following:

eval {
  $smtp->mail($from) or
    die "Error sending to $from: " . $smtp->code() . ' '. $smtp->message();

  $smtp->to($to) or
    die "Error sending to $to: " . $smtp->code() . ' '. $smtp->message();

  $smtp->data($data) or
    die "Error sending data $data: " . $smtp->code() . ' '. $smtp->message();
};

if($@) {
  print STDERR "Error sending mail: $@";
}

The eval{} is like a try{} block in Java. The 'die' statements correspond to throw. If a die gets triggered, it takes you out of the eval{} block, setting $@ to contain the message. So the if($@) is like the catch part.
This way you can continue your code and know when and why it failed.

HTH,
Kandura
0
 
dennismvAuthor Commented:
this is just an update.  eval helped to kinda track down some problem areas, but I still get the error.  However, I am not yet stuck, as I still have things to try before I 'give up'.

Just so you know how it's going:
the log usually goes like this:
Net::SMTP=GLOB(0x82616e0)>>> MAIL FROM:<me@domain.com>
Net::SMTP=GLOB(0x82616e0)<<< 250 sender <me@domain.com> ok
Net::SMTP=GLOB(0x82616e0)>>> RCPT TO:<userto@domain.com>
Net::SMTP: Unexpected EOF on command channel at smtp.pl line 211
Sending test message to --> test@domain.com
Exiting eval via next at smtp.pl line 254, <DATA> line 11.
Sending test message to --> test@domain.com
Exiting eval via next at smtp.pl line 254, <DATA> line 12.
etc.

NOTE:  after the EOF error server stops replying completely.  That's what I called "the script going awry" -- I can't regain the control of it.
I test the connection every email by this line:
if (undef($smtp)) die "smtp undef";  
but the server keeps going, without giving any response, so
apparently $smtp is still defined, yet it's practically dead..

Unexpected EOF happens on any of the lines where I have
$smtp->command();  #where "command" may be any of the to,from,datasend,etc.

And what's interesting is, i.e. in this case I have the command from line 254 as from the error above:
if ($smtp->to($to)==0) {print "bad recipient or unexpected EOF";};

self explanatory, but I'll reiterate:
$smtp->to() gives 0 if it's bad rcpt, or the EOF error.
it still gives 0 when the server doesn't reply anymore.
So I can't differentiate the two.  And depending on which one it is, I want different processing.  

So the (new) definition of the problem is .. how do I know when server stops replying.

I tried $smtp->response(), but it always times out, no matter what.
So, I am still trying things .. like maybe I'll try $smtp->code (); and see what it does.  It may differentiate between bad rcpt and EOF.  Then, if I know it's EOF I can halt the script without it going awry, and that's what I've been looking for.

Dennis

0
 
ahoffmannCommented:
again:
  $smtp->quit();
might be a reason for EOF, depending on the server ...
0
 
dennismvAuthor Commented:
I have $smtp-quit(); at the end :)  I forgot to mention it last time.
However, the error happens in the loop, before $smtp->quit();

Dennis

0
 
kanduraCommented:
If I understand the documentation for Net::Cmd correctly, $smtp->response() is a method for obtaining a response from the server. You should not call this yourself, Net::SMTP uses this internally. To be specific, it is being called after every $cmd->command() call (which sends a command to the server).

Please test the return values of $smtp->ok() or $smtp->code() and $smtp->message(), because they should contain the last response from the server.

If I'm reading Net::Cmd correctly, it will set code to 599 and message to 'Connection closed'.

BTW, I found your error message in Net::Cmd's getline() routine (on line 273), and it closes the connection right after it reports that. So you will know the connection is closed in this instance.

So, check $smtp->code(). If it equals 599, you know the connection has been closed, and you should reconnect (by setting $smtp = new Net::SMTP($server).

Hope this clarifies stuff a bit.

Kandura
0
 
dennismvAuthor Commented:
Thanks, Kandura !

eval and $smtp->code() helped.  $smtp->message() may also help if I'll need it later on.
I've regained control of the script ! :)

and thanks to everybody for hints and suggestions,
Dennis
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 5
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now