Connection error using Net::IMAPClient in Perl - perl

I am trying to connect to an Outlook email server via IMAP and the error I am getting is curious. Here is a sample of my code:
use Mail::IMAPClient;
my $imap = Mail::IMAPClient->new;
$host='outlook.office365.com';
$username='.....';
$password='.....';
$folder='INBOX';
$imap=Mail::IMAPClient->new(
Server => $host,
User => $username,
Password => $password,
Port => 993,
Ssl => 1,
Clear=> 5,
Folder => $folder,
Uid => 0,
) or die "Cannot connect to $host as $username: $#";
When I run this, the output line looks like this:
Cannot connect to outlook.office365.com as [...]: Socket closed while reading data from server.
More specifically, Socket closed while reading data from server is what is confusing me.
I specify port 993, so is the only remaining possible issue that there's a firewall in place that is preventing this? I have emailed my school's (this is a school email account) tech department (quite some time ago) and they have yet to get back, but hopefully I will hear from them soon.
I get an even stranger error when I remove the line specifying the port, I am including it only in the hopes it is somehow relevant or helpful:
Cannot connect to outlook.office365.com as [...]: Error sending '1 Login "baldassaren#wit.edu" {15}
[password is shown here, along with a newline character I can't seem to force here]
' to IMAP: Bad file descriptor at ./test.pl line 10.

Please check directly with openssl:
openssl s_client -connect outlook.office365.com:993
This should give you a connection and at the end the welcome message from the IMAP server:
* OK The Microsoft Exchange IMAP4 service is ready. ....
If this does not work the connection is blocked by firewall or so. If this works try connecting with IO::Socket::SSL, which is the module Mail::IMAPClient uses for SSL connections:
perl -MIO::Socket::SSL -e 'print IO::Socket::SSL->new(q[outlook.office365.com:993])->getline.""'
This should also give you the welcome message. If it does not there might be problems with certificate checking or so. In this case please post the versions of modules you use and the OS, e.g.
perl -e 'print "version=$^V, os=$^O\n"'
perl -MIO::Socket::SSL -e 'print IO::Socket::SSL->VERSION,"\n"'
perl -MMail::IMAPCient -e 'print Mail::IMAPClient->VERSION,"\n"'
But, if IO::Socket::SSL gets a successful connection please add the Debug => 1 option to Mail::IMAPClient->new and add the output to your question.

Related

Cpan, address already in use error when installing IO::Socket::Timeout

I am trying to install IO::Socket::Timeout (as part of a requirement for Redis, on 5.14, on Linux as root).
I have tried in both CPAN and CPANM, when I enter the command
cpan IO::Socket::Timeout
It comes up with the error
t/timeout.t ............... ops Address already in use at /root/.cpan/build/IO-Socket-Timeout-0.32-ZVMh0b/t/tlib/TestTimeout.pm line 31.
cannot open port: 50420 at /opt/perl/lib/site_perl/5.14.2/Test/TCP.pm line 51.
# Child (test with no delays and no timeouts) exited without calling finalize()
t/timeout.t ............... 1/?
# Failed test 'test with no delays and no timeouts'
If I do
netstat -lntu | grep 50420
netstat -ntp | grep 50420
It doesn't show any port in use.
If I look at the timeout.t test that seems to be calling, it's
my $socket = IO::Socket::INET->new(
Listen => 5,
Reuse => 1,
Blocking => 1,
LocalPort => $port
) or die "ops $!";
If I download the gzip from cpan and try to install with
Perl Makefile.PL && make && make test
and I add some debug to display which port its trying, it tries different ports, eg
50341 or 50809 etc which aren't in use either
Any ideas what the problem may be, or how I can isolate ?
For whatever reason, it simply worked this morning. I can only think there was something else going on affecting a ports ability to be in use, but I'm not sure why this would be. The server was quite busy which could be related.
If anyone has any ideas on how to confirm why a port may come up as in use or unavailable (is there a timeout/sleep time for ports?), even though it doesn't appear in a netstat dump, I will gladly accept their answer.

Perl - Best way to establish an SFTP connection on windows

I need to put files in a remote directory using SFTP on a Windows machine. I've tried Net::SFTP::Foreign though I can't use it because it needs IO::Pty which is not available on Windows machine. What's the best/simplest way to do this?
Update With Requested Info:
Here are the versions I'm using:
Net::SFTP::Foreign : v 1.89
Net::SSH2 : v 0.69
Net::SFTP::Foreign::Backend::Net_SSH2 : v 0.09
and here is the gist of my code:
$ssh2 = Net::SSH2->new();
$ssh2->connect($host) || die "connect failed";
$ssh2->auth_password($user, $pass) || die "password auth failed";
$sftp = Net::SFTP::Foreign->new(ssh2 => $ssh2,
backend => 'Net_SSH2');
$sftp->error and
die "Unable to stablish SFTP connection: ". $sftp->error;
Right now I'm just trying to establish a connection. I will need to put files on the server. The erro I'm receiving is as follows:
Net::SSH2::timeout(ss, timeout) at C:/Strawberry/perl/site/lib/Net/SSH2.pm line 111, <STDIN> line 1.
The preferred way to use Net::SFTP::Foreign in Windows is probably to use the Net::SFTP::Foreign::Backend::Net_SSH2 backend (update: a Perl module available from CPAN) which uses Net::SSH2 under the hood (which is already included with Strawberry Perl, update: otherwise, you will need to build and install libssh2 yourself which sometimes is not as easy as it should be).
Another option is to tell Net::SFTP::Foreign to use the plink command to run the SSH connection (search for plink on the module docs). Update:plink is part of the PuTTY application distribution, a very popular SSH client that may be already installed in that machine.
Finally you can also try using Net::SSH::Any which provides its own backend for Net::SFTP::Foreign and can run on top of several SSH clients and modules... but it is still in beta!
I have several cross-platform scripts that are using Net::SFTP::Foreign using plink on windows and openssh on linux and it works great. Windows is using the latest strawberry perl release.
my $sftp = Net::SFTP::Foreign->new(
host=> $server,
ssh_cmd => $plink, #Contains full path to plink or path to ssh
user=> $user,
more => ['-i', $keyfile],
stderr_discard => 1,
);
The only thing about using the plink backend is that you have to first manually establish a connection using psftp or Putty gui so it stores the trust confirmation in the registry. After that it is good to go from the script.
The nice thing is you can just have the actual path to ssh or to plink defined in a system level config file and the script just reads what is needed on that particular platform. ie (...\bin\Putty\plink.exe or /usr/bin/ssh )
Not a pure Perl solution, but has been very robust. I don't see IO::Pty on any of my windows boxes so no dependency there for plink.
SFTP is actually SSH with a wrapper to simulate the FTP like commands, so a mdir is actually a ssh 'ls /path/to/dir'.
While there might be a Perl SFTP package that avoids IO::Pty, you might get to your solution much faster by just translating the "FTP" commands into their ssh / scp equivalents and looking at Net::SSH
--- Adding an Example as requested ---
#!/bin/env perl
use Net::OpenSSH ();
my $connection = Net::OpenSSH->new('somehost.com', user => 'myuser', password => 'mypassword' );
my #ls = $connection->capture("ls");
printf "remote listing is %s\n", join(', ', #ls);
This should list the files to your console.
You mentioned not having IO::Pty because it is not available for a windows machine. Perhaps you should be attempting to install IO::Pty::Easy. Note that Net::OpenSSH uses IO::Pty too, but that should be possible to do on windows, provided you also install Glib as indicated in this post http://www.perlmonks.org/bare/?node_id=856863
Good luck!

Connection Refused While connecting Host Through Net::FTP in perl

When I run below code through perl script at that time I always get error like connection refused so please any body can suggest to solve this issue.
ftp_check.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;
my $host = '111.118.248.24';
#-- connect to ftp server
my $ftp = Net::FTP->new($host, Debug => 1) or die "Error connecting to $host: $!";
Message getting like "Error connecting to 111.118.248.24: Connection refused at ftp_check.pl line 10."
i supposed you server works properly, just for the case you can make some pings on it. Anyway, do you have a possibility to run in a terminal ( with ssh or some client like putty if you are a windows user ) following commands:
netstat -tulpena | grep -i LIST <<ENTER>>
Now you can see is there a FTP-Server which is running in a listener mode.
The second step would be to to use some ftp-client to check, that you can connect with your FTP-Server properly, just to see is there a firewall-rule in between, actually you could run "iptables -L" on a server to, but it will be easier just to use some ftp-client to make a verification of your ftp-server.
An other suggestion would be to use something more secure
and not the net::ftp-module. Perl has nice CPAN-Modules for SFTP (Net::FTP).
Cheers.

How to access file on a remote server and get the file data as return value in perl?

I want to write a perl script which will read a file on a remote server, alter some parameters inside the file and get whole file data or specific data as a return value.
Actually what I was thinking is to use cpan openssh utility to create a ssh connection, then call the script on the server side, which does all the reading and changing the parameters value. But the problem in this approach is that I will get only success or failure as a return value - not the file data.
Can anyone please tell me how I will achieve this functionality?
Thanks in advance....
Here is one way to do what you are asking with Net::SSH::Expect
use Net::SSH::Expect;
my $ssh = Net::SSH::Expect->new (
host => "some.example.net",
password=> 'your-password',
user => 'you',
raw_pty => 1
);
my $login_output = $ssh->login();
if ($login_output !~ /Welcome/) {
die "Login has failed. Login output was $login_output";
}
$ssh->exec("perl -i -pe 'tr/9/a/;' temp.txt");
my $cat=$ssh->exec("cat temp.txt");
print($cat);
The file on the remote server (temp.txt) contains just one line 0123456789
and running the script has this output
$ perl /tmp/a.pl
012345678a
The main point here is that with this module I can log in to a remote machine and execute commands as I would with any other ssh session.

Is it possible to create a read/write FileHandle for a system() call?

I have a POP3 login test script which uses IO::Socket::INET to read and write to the opened socket on TCP:110. This is what I'm used to: -
my $sock = IO::Socket::INET->new(
PeerAddr => "$h:$port",
Proto => "tcp",
) or die "$!\n";
However, I also need to test the same POP3 conversation through SSL-secured POP3S (TCP:995).
I've found that I can use the following on the command-line, which gets me a similar state as "telnet hostname 110", but encrypted: -
openssl s_client -crlf -connect hostname:995
I am hoping to find a way that I can set up some sort of read/write FileHandle or socket on the openssl command, which I can read til it's empty, then write in the required POP3 commands into, then read the responses, and so on...
I feel like because I can see it on screen, it's close enough to grab, but I don't quite know my way around perl well enough, to "get it" and move on!
Unfortunately, the server this script will be run on, is not able to have more perl modules installed, which might have been an obvious solution.
UPDATE
Thanks to #ventatsu for the inspiration, I am now using IPC::Open2 like this: -
my ($sslread,$sslwrite);
my $ssl_fh = open2(
$sslread,
$sslwrite,
"openssl s_client -crlf -connect mail.example.com:995"
) or die "$!\n";
while (<$sslread>) {
print;
if (/^\+OK.*$/) {
## Try to log in
print $sslwrite "USER $u\r\n";
print "USER $u\n";
while (<$sslread>) {
print;
if (/^\+OK.*$/) {
## Keep going
print $sslwrite "PASS $p\r\n";
print "PASS $p\n";
while (<$sslread>) {
print;
}
}
}
print $sslwrite "QUIT";
print "QUIT\n";
}
}
waitpid( $ssl_fh, 0 );
my $child_exit_status = $? >> 8;
My non-SSL test scrip works thusly: -
Testing pop3 on mail.example.com:110
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest#example.com
+OK
PASS Abcd3fGh
+OK User successfully logged on.
The credentials work OK when I run the POP3 commands in an interactive SSL session on the CLI like this: -
openssl s_client -crlf -connect mail.example.com:995
<snip out the SSL bumph />
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest#example.com
+OK
PASS Abcd3fGh
+OK User successfully logged on.
But my SSL test script only almost works thusly: -
Testing pop3s on mail.example.com:995
<snip out the SSL bumph />
+OK The Microsoft Exchange POP3 service is ready.
USER mailtest#example.com
+OK
PASS Abcd3fGh
-ERR Logon failure: unknown user name or bad password.
What am I doing wrong?
You can use IPC::Open2 to attache two file handles, one to the input and one to the output of a program. It may be closer to what you really want to use IO::Socket::SSL, which functions like IO::Socket::INET but encrypted.
Update:
My best guess is that your doubling up \r characters. According to the man page for s_client -crlf converts line feeds into carriage return + line feed. An when you print to the $sslwrite handle you are sending "\r\n". I think the result would be that the server would receive "\r\r\n" at the end of each command. You probably want to drop the -crlf from the openssl command in your program.