Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

Accessing IMAP-Server via Perl

by PerlingAround (Novice)
on Sep 17, 2019 at 12:12 UTC ( #11106295=perlquestion: print w/replies, xml ) Need Help??

PerlingAround has asked for the wisdom of the Perl Monks concerning the following question:


I'm atm trying to write up a perl script, that I need to monitor my new Office 365 mailbox and I am having some problems. I am currently using the module "Net::IMAP::Simple as I have previously used it to query data from another older IMAP Server. So to test the basics I simply try to connect, login and logout to and from the server.

But it seems like my script simply refuses to properly login to the Server, as anything I try produces the Error-String "Command received in invalid state". Browsing some other sites, I found out, that this Error usually is fixed by using "plain" authentication, an Option I can't seem to find within Net::IMAP::Simple, and all my other searches ended up leading me to modules for use on the IMAP-Server itself.

So what I need help with, is to find out if there is a way to login to the server using the Net::IMAP::Simple Module, or if it is simply not possible that way. If that's the case, I'd be delighted if someone could point me in the direction of a way to actually do it.

Finally, the End-Goal of this Operation is to search for the last unseen mail and read how old it is. Since I can't even login right now, I pushed that issue back a bit, and am focusing on getting the login to work first. If any of you have an idea of how to do this too, that would just be the cherry on top.

Please keep the Solutions "Newb-friendly" though. I am only rarely forced to write Perl-Scripts and usually they are quite short or at the least quite easy to come by, so I am not 100% involved in the whole module-management part.

Thank you for the help in advance

  • Comment on Accessing IMAP-Server via Perl

Replies are listed 'Best First'.
Re: Accessing IMAP-Server via Perl
by NERDVANA (Beadle) on Sep 17, 2019 at 23:16 UTC
    Actually I have some production code that does this, with Office365 even. I've been meaning to clean it up a bit to be less work-specific and publish it on CPAN but never got around to it. But, here's some snippets that might help you:
    my $conn= Net::IMAP::Simple->new( $host, port => $port, ($port == 993? ( use_ssl => 1, ssl_options => [ SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER() ] ) : ()), debug => $log->is_trace, ) or _logcroak("Cannot connect to server $host: $Net::IMAP::Simple +::errstr"); if ($port != 993) { $conn->starttls or _logcroak("Can't start TLS after conencting to $host port +$port: ".$conn->errstr); } $conn->login($user, $self->login_pass) or _logcroak("Can't authenticate as $user to server $host: ".$co +nn->errstr); $log->info("Logged in as ".$user); my $mbox= $url->path; $mbox= 'INBOX' unless defined $mbox and length $mbox and $mbox ne ' +/'; $conn->select($mbox) or _logcroak("Can't select folder $mbox");

    Then, in a loop:

    $conn->select; # call select again to refresh message list
    $msg_ids= [ $conn->search($imap_query) ];
    for my $msgid (@$msglist) { $log->debug("Msg $msgid"); my $header_lines= $conn->top($msgid); my $head= MIME::Head->from_file(\join('', @$header_lines)) or di +e; ... # filtering code goes here, which inspects headers
    # this is the code that pulls in the whole message my $fh= $conn->getfh($msgid) || \ _logcroak("Failed to get message file handle: ".$conn->errstr); my $p= MIME::Parser->new; $p->output_to_core(1); return $p->parse($fh);

    I'll add that Email::MIME has a nicer interface than MIME::Parser but I had some particular edge cases where MIME::Parser worked better for me. I recommend starting with Email::MIME and see if it works for you.

    The part where you want to search only unread messages is done using the IMAP query, and IMAP::Simple describes that well enough. Also I think Office365 doesn't support IMAP unless you specifically enable it somewhere in your account preferences.

Re: Accessing IMAP-Server via Perl
by holli (Abbot) on Sep 17, 2019 at 12:29 UTC
    We can't really help you without seeing the actual code. My best guess without that: Your old script propably did not use encryption, but O365 only works with SSL/TLS encryption. Or maybe the port or the host adress are incorrect. For more information, see the google snippet for "office 365 imap settings".


    You can lead your users to water, but alas, you cannot drown them.
      #!/usr/local/bin/perl -w use Net::IMAP::Simple; use Date::Parse; my $imap_server = ''; printf $imap_server; printf "\n"; if (!($imap_con = new Net::IMAP::Simple($imap_server, find_ssl_default +s=>[]))) { print "The Server is not available. \n"; exit; } my $user = 'USER'; my $password = qq(PW); if (!($imap_con->login($user, $password))) { print "invalid Login: ". $imap_con->errstr ."\n"; exit; } $imap_con->quit(); print "login possible. \n"; exit;

      This is the small "Test"-Script I am using to see if I can login. It's basically c&p from how I invoked the methods in the previous script and "errstr" always returns "Command received in invalid state".

        I highly recommend you look at the module page on CPAN here and follow the example code more closely. You're ignoring the return status of your calls, and that's going to make it virtually impossible to understand what's failing.

        Alex / talexb / Toronto

        Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

        This seems to work, although I'd give the same warning about blindly accepting the SSL certificate as they do on
        #!/usr/local/bin/perl -w use Net::IMAP::Simple; use Date::Parse; my $imap_server = ''; printf $imap_server; printf "\n"; if (!($imap_con = new Net::IMAP::Simple($imap_server, port => 993, use +_ssl => 'true'))) { print "The Server is not available. $Net::IMAP::Simple::errstr +\n"; exit; } my $user = ''; my $password = ''; if (!($imap_con->login($user, $password))) { print "invalid Login: ". $imap_con->errstr ."\n"; exit; } $imap_con->quit(); print "login possible. \n"; exit;
        You might consider using Email::Folder::Exchange
Re: Accessing IMAP-Server via Perl
by Anonymous Monk on Sep 19, 2019 at 02:16 UTC
    It can also be extremely useful to use a tool like WireShark, TCPDump, or what-have-you to see what packets are actually being exchanged between the two parties. Start by eavesdropping on an actual connection to Office ... of course most if not all of it will be encrypted and thus unreadable ... then, watch what happens when your program runs. The root cause of the problem will probably be very quickly apparent once you can see it. Guesses are usually not very useful.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11106295]
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2020-11-29 02:39 GMT
Find Nodes?
    Voting Booth?

    No recent polls found