Skip to content

Instantly share code, notes, and snippets.

@DamianZaremba
Created July 18, 2011 23:25
Show Gist options
  • Save DamianZaremba/1090943 to your computer and use it in GitHub Desktop.
Save DamianZaremba/1090943 to your computer and use it in GitHub Desktop.
Perl script for grabbing emails from an IMAP folder
#!/usr/bin/perl
use strict;
use Mail::IMAPClient;
use IO::Socket;
use IO::Socket::SSL;
use Time::ParseDate;
use Data::Dumper;
# Config stuff
my $mail_hostname = '';
my $mail_username = '';
my $mail_password = '';
my $mail_ssl = 1;
# Make sure this is accessable for this namespace
my $socket = undef;
if( $mail_ssl ) {
# Open up a SSL socket to use with IMAPClient later
$socket = IO::Socket::SSL->new(
PeerAddr => $mail_hostname,
PeerPort => 993,
Timeout => 5,
);
} else {
# Open up a none SSL socket to use with IMAPClient later
$socket = IO::Socket::INET->new(
PeerAddr => $mail_hostname,
PeerPort => 143,
Timeout => 5,
);
}
# Check we connected
if( ! defined( $socket ) ) {
print STDERR "Could not open socket to mailserver: $@\n";
exit 1;
}
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $mail_username,
Password => $mail_password,
Timeout => 5,
);
# Check we have an imap client
if( ! defined( $client ) ) {
print STDERR "Could not initialize the imap client: $@\n";
exit 1;
}
# Check we are authenticated
if( $client->IsAuthenticated() ) {
# Select the INBOX folder
if( ! $client->select("INBOX") ) {
print STDERR "Could not select the INBOX: $@\n";
} else {
if( $client->message_count("INBOX") > 0) {
print "Processing " . $client->message_count("INBOX") . " messages....\n";
# We delete messages after processing so get all in the inbox
for( $client->search('ALL') ) {
print " ..." . $_ . "\n";
# Pull the RFC822 date out the message
my $date = $client->date( $_ );
# Pull the subject out the message
my $subject = $client->subject( $_ );
# Pull the body out the message
my $body = $client->body_string( $_ );
# Try and get the unix time of the message being sent
my $unix_date = undef;
if( $date ) {
$unix_date = parsedate( $date );
}
# Log the recieved time
my $recv_unix = time;
# Check we have valid stuff
if( ! $unix_date || ! $subject || ! $body ) {
print "Missing header stuff....\n";
} else {
print Dumper( $unix_date );
print Dumper( $subject );
print Dumper( $body );
}
# Remove the message
$client->delete_message($_);
}
# Delete the messages we have deleted
# Yes, you read that right, IMAP is strangly awesome
$client->expunge("INBOX");
} else {
# No messages
print "No messages to process\n";
}
# Close the inbox
$client->close("INBOX");
}
} else {
print STDERR "Could not authenticate against IMAP: $@\n";
exit 1;
}
# Tidy up after we are done
$client->done();
exit 0;
@hongz1
Copy link

hongz1 commented Aug 15, 2018

wondering why you use done method... Does logout method should be used instead of done?

The done method tells the IMAP server that the connection is finished idling. See idle for more information. It accepts one argument, which is the transaction number you received from the previous call to idle.
If you pass the wrong transaction number to done then your perl program will probably hang. If you don't pass any transaction number to done then it will try to guess, and if it guesses wrong it will hang.
If you call done without previously having called idle then your server will mysteriously respond with * BAD Invalid tag.
If you try to run any other mailbox method after calling idle but before calling done, then that method will not only fail but also take you out of the IDLE state. This means that when you eventually remember to call done you will just get that * BAD Invalid tag thing again.

The logout method issues the LOGOUT IMAP client commmand. Since the LOGOUT IMAP client command causes the server to end the connection, this also results in the IMAPClient client entering the Unconnected state. This method does not, however, destroy the IMAPClient object, so a program can re-invoke the connect and login methods if it wishes to reestablish a session later in the program.
According to the standard, a well-behaved client should log out before closing the socket connection. Therefore, Mail::IMAPClient will attempt to log out of the server during DESTROY processing if the object being destroyed is in the Connected state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment