#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Net::POP3; use Pod::Usage; use Term::ReadLine; use Term::ANSIColor qw(:constants); $Term::ANSIColor::AUTORESET = 1; use Carp; use vars qw( $VERSION $opt_verbose $opt_host $opt_username $opt_password $opt_port $opt_noprompt $opt_separator $opt_output $opt_stdin $opt_lines $opt_timeout $opt_help $opt_version $processed_count $pop3 ); $VERSION = sprintf '%d.%02d', q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/; $opt_port = 110; $opt_timeout = 120; $opt_separator = "none"; GetOptions( 'v|verbose' => \$opt_verbose, 'h|host=s' => \$opt_host, 'u|username=s' => \$opt_username, 'p|password=s' => \$opt_password, 'noprompt' => \$opt_noprompt, 'timeout=i' => \$opt_timeout, 'port=s' => \$opt_port, 's|separator=s' => \$opt_separator, 'l|lines=i' => \$opt_lines, 'o|output=s' => \$opt_output, 'stdin' => \$opt_stdin, 'help' => \$opt_help, 'version' => \$opt_version, ) or pod2usage(2); pod2usage(1) if $opt_help; if ($opt_version) { print <. Copyright (c) 2002-2003 Michael A Nachbaur. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. VERSION exit(0); } unless ($opt_noprompt) { my $term = new Term::ReadLine::Gnu 'pop3list'; my $attribs = $term->Attribs; $term->ReadHistory; Term::ReadLine::Gnu->Features->{ornaments} = 0; Term::ReadLine::Gnu->Features->{autohistory} = 0; my $OUT = $term->OUT || *STDOUT; unless ($opt_host) { $opt_host = $term->readline("Hostname: "); } unless ($opt_username) { $opt_username = $term->readline("Username: "); } unless ($opt_password) { $attribs->{redisplay_function} = $attribs->{shadow_redisplay}; $opt_password = $term->readline("Password: "); $term->remove_history($term->where_history); } $term->WriteHistory; } if ($opt_separator !~ /(none|short|long|fancy|null)/) { die "You specified an invalid separator: \"$opt_separator\".\n"; } if ($opt_output and !-w $opt_output) { die "The output location \"$opt_output\" does not exist or is not writable.\n"; } $opt_lines = undef if (defined($opt_lines) and $opt_lines < 1); $processed_count = 0; my $message_count = undef; ($pop3, $message_count) = pop_connect( username => $opt_username, password => $opt_password, host => $opt_host, port => $opt_port, timeout => $opt_timeout, ) or carp "Could not get connect to the mail server.\n"; if ($#ARGV < 0 or $opt_stdin) { if (test_interactive()) { print STDERR "Enter the message IDs you want to retrieve, followed by \na carriage return. Press CTRL-D to finish.\n"; print STDERR "$message_count messages in this mailbox.\n"; } while (my $line = ) { chomp $line; if (test_interactive() and $line =~ /\s*all\s*/i) { print STDERR "The \"all\" keyword is not available in STDIN mode.\n"; next; } processMessages($line); } } else { if ($#ARGV == 0 and lc($ARGV[0]) eq 'all') { my $list = $pop3->list; foreach my $id (keys %{$list}) { retrieveMessage($id); } } else { foreach my $id (@ARGV) { processMessages($id); } } } print STDERR GREEN "Disconnecting from POP3 server.\n" if ($opt_verbose); $pop3->quit(); sub processMessages { my ($id) = @_; if ($id =~ /^\s*(\d+)\s*$/) { my $message = $1; retrieveMessage($message); } elsif ($id =~ /^\s*(\d+)-(\d+)\s*$/ and $1 < $2) { foreach my $message ($1 .. $2) { retrieveMessage($message); } } } sub retrieveMessage { my ($id) = @_; $processed_count++; print STDERR RED "Processed $processed_count messages.\n" if $opt_verbose; printSeparator($id); if ($opt_output and -d $opt_output) { open OUTFILE, ">$opt_output/$id"; } elsif ($opt_output and -f $opt_output or -c $opt_output) { open OUTFILE, ">>$opt_output"; } else { open OUTFILE, ">&STDOUT"; } if ($opt_lines) { print STDERR YELLOW "Retrieving $opt_lines lines from #$id\n" if $opt_verbose; print OUTFILE join("", @{$pop3->top($id, $opt_lines)}) or print STDERR RED "Cannot retrieve message #$id\n"; } else { print STDERR YELLOW "Retrieving #$id\n" if $opt_verbose; print OUTFILE join("", @{$pop3->get($id)}); } close OUTFILE; } sub printSeparator { my ($id) = shift @_; return if ($opt_separator eq "none"); print STDERR YELLOW "Printing separator\n" if $opt_verbose; if ($opt_separator eq "short") { print STDOUT "$id\n"; } elsif ($opt_separator eq "long") { print STDOUT "-" x 4 . "[ " . $id . " ]" . "-" x (67 - length($id)) . "\n"; } elsif ($opt_separator eq "fancy") { my $top_line = "+" . "-" x 73 . "+" . "\n"; print STDOUT $top_line; my @messages = ("$processed_count", "Message $id"); foreach (@messages) { print STDOUT "| " . $_ . " " x (71 - length($_)) . " |\n"; } print STDOUT $top_line; } elsif ($opt_separator eq "null") { print STDOUT "\0"; } } sub pop_connect { my (%params) = @_; my $res = undef; my $num_messages = undef; print STDERR GREEN "Opening POP3 connectionn to $params{host}.\n" if ($opt_verbose); my $pop = Net::POP3->new($params{host}, Timeout => $params{timeout}); print STDERR GREEN "Sending USER command.\n" if ($opt_verbose); $res = $pop->user( $params{username} ); unless ($res) { print STDERR RED "Username rejected\n"; return 0; } print STDERR GREEN "Sending PASS command.\n" if ($opt_verbose); $res = $pop->pass( $params{password} ); unless ($res) { print STDERR RED "Password rejected\n"; return 0; } else { ($num_messages) = $res =~ /^(\d+)/; } print STDERR CYAN "This mailbox contains $num_messages messages.\n" if ($opt_verbose); return ($pop, $num_messages); } sub test_interactive { return -t STDIN && -t STDOUT; } 1; __END__ # Below is stub documentation for your module. You better edit it! =head1 NAME pop3retr - Retrieves the specified messages from a POP3 account =head1 OSNAMES Any Unix-like only =head1 SCRIPT CATEGORIES UNIX/System_administration Mail =head1 PREREQUISITES This script requires the C, C and C packages, which should be on your system anyway. Additionally, C and C are used to print pretty verbose messages, so you can differentiate between local message and server-side mail. Finally, the magic behind this package is thanks to C, which is required. =head1 SYNOPSIS pop3retr [OPTIONS] Options: -v, --verbose be verbose about what's happening -h, --host hostname of POP server -u, --username pop3 username -p, --password password -s, --separator message separator: none|short|long|fancy|null (default: none) -l, --lines optional number of lines to retrieve --noprompt do not prompt for information --stdin force the use of STDIN only --port override the TCP port (default: 110) --timeout response timeout in secs (default: 120) --help this help screen --version version information =head1 DESCRIPTION pop3retr is a simple script that connects to a POP3 server and retrieves the indicated messages, by message number. It accepts message numbers on the command line, or through STDIN. This functions very simillarly to L, so refer to that manpage for more details. =head1 README pop3retr is a simple script that connects to a POP3 server and retrieves the indicated messages, by message number. It accepts message numbers on the command line, or through STDIN. This functions very simillarly to L, so refer to that manpage for more details. =head1 SEPARATORS There are four types of separator possible. In the event that multiple messages are returned, this separator will be used. =over 4 =item none (default) all the messages will be run together with no separation (essentially an exact copy of the mail file on the mail server). =item short this outputs just the message number. =item long this outputs a short separator, consisting of 75 dashes and the message number. =item fancy this returns a fancy separator, a block of ascii-art, also indicating the message number. =item null this will return a null byte (\0), for use in processing by another script. =back =head1 AUTHOR Michael A Nachbaur, Emike@nachbaur.comE =head1 COPYRIGHT Copyright (c) 2002-2003 Michael A Nachbaur. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L. =head1 REVISION $Id: pop3retr,v 1.2 2003/09/10 17:44:54 nachbaur Exp $ =cut