Net::Telnet Error Handling - perl

Im trying to print "Error IP USER PASS Failed!", on failure.
When i use my script
use Net::Telnet ();
my $t = new Net::Telnet Timeout => 30,
Prompt => '/[\$#%:><][\s\b]+$/';
$t->open($ARGV[0]);
my $user = $ARGV[1];
my $pass = $ARGV[2];
print "Logging In...\n";
print "Sending Username....\n";
$t->print($user);
$t->waitfor('/[:>%\$#]/');
print "Sending Password....\n";
$t->print($pass);
$t->waitfor('/[:>%\$#]/');
if ($t->errmsg){
print "errmsg: " . $t->errmsg . "\n";
} else {
print"success\n";
}
The issue:
I know the IP and username: admin and admin are working.
root#localhost:~/tel# perl t2.pl *.*.*.* admin admin
Logging In...
Sending Username....
Sending Password....
success
Now using a NON working user and pass i get the same "success"
root#localhost:~/tel# perl t2.pl 36.85.134.191 admin admi1
Logging In...
Sending Username....
Sending Password....
success
What am i doing wrong with the if statement, something is not working correctly.

You should probably enable debugging, but I guess that your expectation for the result of passwort matches not only the prompt (e.g. $ or #) but also the username prompt you get if the password was wrong (:).

Related

Can't call method "verify" on an undefined value

• I am working to migrate a Linux server to a newer one from Ubuntu 10.04 to 12.04
• This server is responsible for executing several a number of Perl modules via crontabs.
• These Perl Modules rely heavily on 30-40 perl extensions.
• I have installed all Perl extensions and the crontabs are able to process successfully except for several Syntax errors caused by the newer versions of these PERL extensions.
• I need some help with modifying the syntax to get the Perl script to process as intended.
This is my error message:
2015/12/28 12:56:48 ./cms.pl 88 FATAL main - Can't call method "verify" on an undefined value at pm/Emails/Core.pm line 438.
Code:
#===================================================================================================
# Send an eamil
# Args: enable_clients?, BCC Arrayref [admin1#a.com, ...], Hashref { email_address, email_subject, email_body }
#===================================================================================================
sub pm::Emails::Core::send_email {
my ($self, $enable_clients, $bcc, $email) = #_;
# die('Invalid BCC array') unless $bcc;
die('Invalid Email hashref') unless ($email && $email->{email_address} && $email->{email_subject} && $email->{email_body});
$email->{email_address} = trim $email->{email_address}; # Trim the email address just to be sure no invalid emails sneak in
my $mime = undef;
my $smtp = undef;
###
# Get a handle to the logger
my $logger = Log::Log4perl->get_logger();
die('Failed to create logger') unless $logger;
###
###
# Send the email using the local SMTP server
# SPAM FILTER NOTES:
# We are sending the email as inlined HTML.
# Sending the email as a multipart with HTML & PlainText is getting flagged as SPAM.
{
my $msg = join(', ',
(
'Time:' . localtime(),
'Sending Email TO: ' . $email->{email_address},
#'BCC: ' . join(',', #$bcc),
'SUBJECT: ' . $email->{email_subject},
'Clients Enabled: ' . ($enable_clients ? 'true' : 'false')
)
);
$logger->warn($msg);
open(FILE, '>>/var/log/mail.log') or die('Failed to open mail log: /var/log/mail.log');
print FILE $msg . "\n";
close FILE;
}
###
if (!defined($self->{_phpversion_})) {
$self->{_phpversion_} = `php -r 'print phpversion();' 2>/dev/null`;
}
###
# Generate the MIME email message
$mime = MIME::Lite->new(
Subject => $email->{email_subject},
To => $email->{email_address},
Type => 'text/html',
Data => $email->{email_body},
'Reply-To' => 'test#test.com',
'Return-Path' => 'test#test.com',
From => 'test#test.com',
Organization => 'Testing',
'X-Mailer' => 'PHP' . $self->{_phpversion_}
);
###
# Check to see if we are sending the email to clients, if not then redirect to another account & update the subject
if ($enable_clients) {
$logger->warn('Sending email to clients is enabled!');
} else {
use Sys::Hostname;
$logger->warn('Sending email to clients is disabled!');
$email->{email_address} = 'test#test.com';
$email->{email_subject} = '<' . hostname . ' - ADMIN ONLY EMAIL> ' . $email->{email_subject};
$mime->replace(Subject => $email->{email_subject});
}
$mime->preamble('');
$mime->top_level(1);
$mime = $mime->as_string();
###
###
# Connect to the SMTP server & send the message
$logger->debug('Connecting to SMPT server');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 0, Hello => 'test.com');
$logger->debug('Connected to SMPT server');
###
###
# Verify we can send the email to the included addresses
foreach my $email_address (($email->{email_address}), #$bcc) {
$logger->debug('Verifying Email address: ' . $email_address);
next if $smtp->verify($email_address);
$logger->warn('Failed to verify email address: ' . $email_address . ', re-connecting to SMPT');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 1, Hello => 'test.com');
die('Failed to reconnect to SMPT server') unless $smtp;
last;
}
###
###
# Send the email message
$smtp->mail('test#test.com');
$smtp->bcc(#$bcc, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->to($email->{email_address}, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->data; # This will start the data connection for the message body
$smtp->datasend( $mime ); # This will send the data for the message body
$smtp->dataend; # This will end the message body and send the message to the user
$smtp->quit;
###
use List::Util qw[min];
sleep(min(1, int(rand(2))));
}
Any help on this is greatly appreciated.
You don't create the $smtp object (using $smtp = Net::SMTP->new(...)) until three lines after you try to call the verify() method on it. So of course it's going to be undefined at that point.
The only way that this could ever work is if the $smtp is also created earlier on in code that you haven't shown us. But assuming that you have shown us all mentions of $smtp, then this code can't possibly have worked on the old server only. This is not a problem that is caused by a newer version of Perl, it's a logic error that would never have worked.
The obvious way to fix this is to re-order the code so that the object is created before you try to use it. But as I can only see a small amount of the code, I have no way of knowing whether this would have knock-on effects elsewhere.
Have you considered paying a Perl programmer to help you carry out these migrations? Expecting free consultancy from StackOverflow isn't really a sustainable business model :-/
Update: Ok, so now you've added more code, we can see that the $smtp is initialised a few lines before the call to verify. So why are you getting the error?
If you read the documentation for Net::SMTP, in the section describing the new() method, it says:
On failure undef will be returned and $# will contain the reason for
the failure.
It looks like this is what is happening. But your code isn't checking the return code from the new() and is assuming that it will always work - which is a pretty strange assumption to make. To fine out what is going wrong, you'll need to add some debugging output to the two lines that create your SMTP object. Where you have:
$smtp = Net::SMTP->new(...);
Change it to:
$smtp = Net::SMTP->new(...)
or die $#;
That way, if you fail to connect to the SMTP server, your program will die with a (hopefully) useful error message which will enable you to investigate further.
Incidentally, I don't know where your code comes from, but no-one really recommends Net::SMTP these days. It's all rather low-level. You would be better off looking at Email::Sender or Email::Stuffer (that's the kind of useful knowledge that a Perl programmer would bring to this project..
Hey Guys just Wanted to follow up on this problem. I tried all of your suggestions and was unable to get a solution.
However more in-depth research of the SMTP/Mail running on this machine revealed that it was running Postfix, it turns out this script was written for SendMail. Simply did the following:
Uninstall Postfix-
sudo apt-get purge postfix
Install Sendmail-
sudo apt-get install sendmail
All was resolved, thank you guys for all your help.

connection to the active server Infoblox

I am a beginner and I have to take a solution using two Infoblox boxes.
Currently, a server is active (master) and the other is passive. if the first fails, the second takes over. I use Perl API, how do I know when I try to connect to a server ,if it is the active server or the passive server?
I would only make the connection to the active server,
I have thought about the method « active_position() » of Infoblox::Grid::Member but I dont know how to use it..
use strict;
use Infoblox;
my $grid_member = Infoblox::Grid::Member->new(gateway=> "xxx.xxx.xxx.xxx",ipv4addr=> "xxx.xxx.xxx.xxx",mask=> "xxx.xxx.xxx.xxx", name=> "ibiza.mydomain.com");
print 'grid : '. $grid_member . "\n";
my $active_server = $grid_member->active_position();
print $active_server . "\n";
exit;
And this returns
grid : Infoblox::Grid::Member=HASH(0xf10ca8)
0
What is this "0" ??
Thank you in advance
If your Grid Master is a HA pair then you don't need to worry about which one to connect to. You just connect to the VIP (virtual IP) of the HA pair which will always be the same address.
Example session test code:
#!/usr/bin/perl
use strict;
use Infoblox;
# Create a session to the Infoblox appliance
my $SESSION = Infoblox::Session->new(
master => "192.168.1.2",
username => "admin",
password => "***"
);
if ($SESSION->status_code()) {
my $result = $SESSION->status_code();
my $response = $SESSION->status_detail();
print "Error: $response ($result)\n";
} else {
print "Connection established\n";
print "Server Version: ".$SESSION->server_version()."\n";
}
Check the API docs on your appliance https://appianceip/api/doc there are lots and lots of examples embedded in the API docs.
Steve

connect to localhost failed (Connection refused) no (more) retries

I want to send an email using perl ,but when i execute the command as follows:
#./sendmail.sh "par1" "par2" "par3"
i got the error msg "connect to localhost failed (Connection refused) no (more) retries"
sendmail.sh:
/usr/bin/perl /code/sendmail.pl "$1" "$2" "$3";
sendmail.pl:
#!/usr/bin/perl -w
use Mail::Sendmail;
my $event1 = shift(#ARGV);
my $event2 = shift(#ARGV);
my $time = shift(#ARGV);
#my $info = shift(#ARGV);
my $datetime = `/bin/date "+20%y-%m-%d %H:%M:%S"`;
chomp $datetime;
$msg = "This is Monitor System speak:\n
The system discovers the events at $datetime.
Something may be abnormal, please check it. The detail is below:\n";
$msg = $msg."$event1 and $event2 at $time\n";
$msg = $msg."\n";
$msg = $msg."Any problem, check it from http://map_test.php\n\n\n";
$mail_subject = "Abnormal";
sendmail(
From => 'localhost',
To => 'test#mail.com',
Subject => $mail_subject,
Message => $msg,
);
Any help appreciated.
smtp stands for simple mail transfer protocol.
When you need to send an email your mail client needs to talk to an smtp server which will accept the message. Normally your internet service provider will provide an smtp host. If you look at your mail client it will need to have an smtp server configured to be able to send mail.
Ok so when you install the Mail::Sendmail module, it doesn't know what your smtp server will be. It is up to you to tell it. It provides a default of localhost which would often be true if your server is running a sendmail daemon.
The configuration of Mail::Sendmail is stored in a variable called
%Mail::Sendmail::mailcfg
You can change the value of the sendmail server using this snippet of code:
unshift #{$Mail::Sendmail::mailcfg{'smtp'}} , 'my.smtp.server';
You need to add this line of code to your script to set the smtp server.
It adds this server to an array which also includes localhost.
So if neither of the hosts work it will still print an error message about localhost which is slightly confusing.
If you use Data::Dumper to print the contents of the mailcfg variable it will look something like this:
#!/usr/bin/perl
use Mail::Sendmail;
use Data::Dumper;
unshift #{$Mail::Sendmail::mailcfg{'smtp'}} , 'my.smtp.server';
print Dumper(\%Mail::Sendmail::mailcfg);
Should return:
$VAR1 = {
'retries' => 1,
'smtp' => [
'my.smtp.server',
'localhost'
],
'delay' => 1,
'port' => 25,
'from' => '',
'debug' => 0,
'tz' => '',
'mime' => 1
};

"Can't call method "auth" on an undefined value at..." after many successful runs

i have a perl app that is supposed to send emails to a massive number of recipients. It seems to work ok, but after about 9K emails it fails with:
Can't call method "auth" on an undefined value at...
In the code I see:
# Open a connection to the SendGrid mail server
my $smtp = Net::SMTP->new('smtp.xyz.net', Port=> 25, Hello=>$DOMAIN);
# Authenticate
my $code = $smtp->auth($USERNAME, $PASSWORD);
The Net::SMTP constructor returns undef if there's a problem (e.g. it's unable to connect to port 25 on smtp.xyz.net). You aren't checking for that, and when you try to call a method on undef, you get the error message you mentioned.
my $smtp = Net::SMTP->new('smtp.xyz.net', Port=> 25, Hello=>$DOMAIN)
or die "Failed to open SMTP connection: $!";
may give you more information. (Although it's not necessarily a socket error, so $! may not contain anything useful.)
The Net::SMTP documentation says that when a method fails it returns undef. So I expect your method call failed.
You might be able to get more information by enabling the Debug => 1 flag in the Net::SMTP constructor.
You will want to detect that your method call failed, and possibly retry it after a short wait.
# Open a connection to the SendGrid mail server
my $smtp = Net::SMTP->new('smtp.xyz.net', Port=> 25, Hello=>$DOMAIN, Debug=>1);
die "Failed to make connection" unless ($smtp);
# Authenticate
my $code = $smtp->auth($USERNAME, $PASSWORD);
You could change it to retry in increasing intervals
something like this:
my $retry = 10; # in seconds;
my $smtp = Net::SMTP->new('smtp.xyz.net', Port=> 25, Hello=>$DOMAIN);
while (not defined $smtp) {
if ($retry > 300) {
die "could not connect to smtp server, giving up";
else {
print "could not connect to smtp, retrying in $retry seconds\n";
}
sleep ($retry);
$smtp = Net::SMTP->new('smtp.xyz.net', Port=> 25, Hello=>$DOMAIN);
$retry *= 2;
}
# Authenticate
my $code = $smtp->auth($USERNAME, $PASSWORD);
This happens mainly if you have the wrong mailbox. Check if smtp.xyz.net is the correct smtp mailbox or it could even be mail.xyz.net. That kind of error occurs if auth is not able to work with the value of 'host' given.

Trouble using Telnet in perl?

I'm having some trouble send commands and receiving text/data from the telnet connection that I set up.
#!perl
#Telnet.pl
use Net::Telnet;
# Create a new instance of Net::Telnet,
my $telnetCon = new Net::Telnet (Timeout => 20,
Dump_Log => "dump.log",
Input_Log => "infile.log",
Output_log => "output.log",
Prompt => '/\$ $/') or die "Could not make connection.";
# Connect to the host of the users choice
$telnetCon->open('');
#get username and password from user
my $CXusername = '';
my $CXpassword = '';
my $task = '50104'; # Get this input from the search
# Recreate the login
# Wait for the login: message and then enter the username
$telnetCon->waitfor(match => '/login:/i');
# this method adds a \n to the end of the username, it mimics hitting the enter key after entering your username
$telnetCon->print($CXusername);
$telnetCon->waitfor(match => '/Password:/i');
# does the same as the previous command but for the password
$telnetCon->print($CXpassword);
#Wait for the login successful message
$telnetCon->waitfor(match => '/$/');
$telnetCon->cmd("viewtask 50104");
$telnetCon->cmd(" ");
$telnetCon->cmd(" ");
#output = $telnetCon->cmd("who");
print #output;
($output) = $telnetCon->waitfor(match => '/$/');
print "Output: ",$output;
if($searched =~ /MODIFIED files in Task $_[1] :(.*?)The/s){
# to Logout of the telnet connection
$telnetCon->print("exit");
#return the modified data
return $1;
}
Tell me if the question doesn't make sense, I'll try and reword it.
So this is the telnet view. I get stuck on the first image when i enter the $telnetCon->cmd("viewtask 50140"). I want to get to the second image and continue entering commands into my telnet session.
The Net::Telnet cmd method writes your command (with a \n appended) and waits for the prompt. this is incompatible with your program's waiting for input to complete output.
I think in your case you would want to use a combination of print and getlines and/or waitfor to get this to work