#!/usr/bin/perl -w use strict; use Mail::IMAPClient; use Data::Dumper; use IO::File; use AppConfig qw/:argcount/; my $config = AppConfig->new(); $config->define( 'EXPUNGE' => { ARGCOUNT => ARGCOUNT_NONE,DEFAULT => 1 }, 'SAVEDIR' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "/home/tzz/imap" }, 'VERBOSE' => { ARGCOUNT => ARGCOUNT_NONE,DEFAULT => 0 }, 'BACKUP' => { ARGCOUNT => ARGCOUNT_NONE,DEFAULT => 0 }, 'HOST' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "imap.yourserver.here" }, 'AUTHINFO' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "~/.authinfo" }, 'PORT' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => 143 }, 'USER' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "Ahab" }, 'PASSWORD' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "MobyDick" }, 'MAILBOX' => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => "INBOX" }, 'TO' => { ARGCOUNT => ARGCOUNT_ONE }, 'N' => { ARGCOUNT => ARGCOUNT_ONE }, 'DUMP' => { ARGCOUNT => ARGCOUNT_NONE }, 'CRAMMD5' => { ARGCOUNT => ARGCOUNT_NONE }, # Dangerous!!! 'DELETE_MAILBOX_REALLY' => { ARGCOUNT => ARGCOUNT_NONE, DEFAULT => 0 }, 'EXPUNGE_OFTEN' => { ARGCOUNT => ARGCOUNT_NONE, DEFAULT => 0 }, ); $config->args(); my $filename = $config->AUTHINFO; my $afh = new IO::File(glob($filename)); if ($afh) { while (my $auth = <$afh>) { my %values; foreach my $keyword (qw/machine login password port/) { if ($auth =~ m/$keyword\s+(\S+)/) { $values{$keyword} = $1; } } $values{machine} = "" unless defined $values{machine}; # avoid the undef comparison next unless $config->HOST() eq $values{machine}; $config->USER($values{login}) if exists $values{login}; $config->PASSWORD($values{password}) if exists $values{password}; $config->PORT($values{port}) if exists $values{port}; } } my $imap = Mail::IMAPClient->new( # returns a new, authenticated Mail::IMAPClient object Server => $config->HOST(), User => $config->USER(), Port => $config->PORT(), Password => $config->PASSWORD(), Peek => 1, ) or die "Cannot connect: $@"; if ($config->CRAMMD5()) { my $authmech = "CRAM-MD5"; if ($imap->has_capability($authmech)) { print "Switching to $authmech authentication\n"; $imap->Authmechanism($authmech); } } my $count = 0; if ($config->DELETE_MAILBOX_REALLY) { $imap->delete($config->MAILBOX) or warn "Could not delete mailbox " . $config->MAILBOX . "\n"; } elsif ($config->BACKUP) { my $dir = $config->SAVEDIR; die "Can't access directory $dir for writing" unless -d $dir && -w $dir; my @folders = $imap->folders; foreach my $f (@folders) { next if $f =~ /^\./; $imap->select($f); unless (-d "$dir/$f") { mkdir "$dir/$f" or die "Couldn't create folder $dir/$f"; } my @msg_list = $imap->search('UNDELETED'); print "Saw message list [@msg_list]\n" if $config->VERBOSE; foreach my $message (@msg_list) { my $filename = "$dir/$f/$message"; next if -e $filename; print "saving message $f/$message to $filename\n" if $config->VERBOSE; my $data_fh = new IO::File $filename, "w"; my $data = $imap->message_string($message); warn "Empty message data for $f/$message" unless defined $data && length $data; $data_fh->print($data); } } } else { $imap->select($config->MAILBOX); my @msg_list = $imap->search('UNDELETED'); print "Saw message list [@msg_list]\n" if $config->VERBOSE; foreach my $message (@msg_list) { $count++; my $data = $imap->parse_headers($message,"Subject","From"); my $address = $data->{From}->[0]; $address = $1 if ($address =~ m/[<"]?([^\s@]+@[^\s@>"]+)"?>?/); printf "%5d %-35.35s %s\n", $count, $address, ((defined $data->{Subject}->[0]) ? $data->{Subject}->[0] : ''); if ($config->DUMP) { my $string = $imap->body_string($message) or die "Could not body_string($message): $@\n"; print "\n===\n\n$string\n===\n\n"; } if ($config->TO) { die "Could not move message $message: $!" unless $imap->move($config->TO, $message); print "Moved message $message to " . $config->TO, "\n"; $imap->expunge() if $config->EXPUNGE_OFTEN; last if $count >= $config->N; } } if ($config->TO) { $imap->expunge(); } }