#!/usr/bin/perl -w
#
# poppy - POP3/IMAP/SMTP Mail Interface (RFC1939/RFC1730/RFC821) for perl
#
# Poppy allows you to read mail headers from a POP3 or IMAP server and then
# selectively view, save, delete, or reply to messages off of the server.
#
# Check out http://www.cnpbagwell.com/projects.html for the
# latest version.
#
# This program is Copyright 1997,2002 by Chris Bagwell <chris@cnpbagwell.com>.
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# If you do not have a copy of the GNU General Public License write to
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
# MA 02139, USA.
#
# System Dependent Variables. Please double check their values!
#
# Those using a windows port of perl my like to change the path to the
# config file to be in the directory you store poppy.
$cfgfilename = $ENV{"HOME"} . "/.poppyrc"; # Unix style
#$cfgfilename = "C:\\perl\\bin\\poppyrc"; # Windows style
# Default values for these features. Should only be modified by config file.
$headers = 0; # Set to 1 to display full mail headers
$cl_headers = ""; # Used to override config file version
$verbose = 0; # Set to 1 to see full debugging info
$quiet = 0; # Set to 1 to be extra quiet.
$gonew = 0; # Set to 1 to auto skip over last read messages
$cl_gonew = ""; # Used to override config file version.
# Default value for features that are only command line oriented.
$frommode = 0;
# Misc. Global Variables. No need to initialize to anything really.
$server_search = "";
$user_search = "";
$ma_mailhost = "";
$ma_mailport = "";
$ma_user = "";
$ma_passwd = "";
$ma_proto = "";
$smtp_mailhost = "";
$smtp_mailport = "";
$sender_address = "";
$poppy_version = "4.01";
use Poppy;
use Getopt::Std;
sub printhelp {
print<<EOF;
commandline: poppy [-c name][-afghlsv] [server_name|user_name\@server_name]\n
a - Work with all messages. Reverse of the -g option.
c - Use new configuration file instead of default
f - Enter \"From\" mode. Display all messages From and Subject fields
g - Goto new message at startup
h - Print Help
l - Display Long Mail Headers
s - Display Short Mail Headers. Reverse of the -l option.
v - Verbose Mode
q - Quiet Mode\n
[user_name\@server_name] specifies an account on a mail server to use.
[server_name] may be a substring of the full name to search for.
EOF
die "\nThanks for using poppy!\n";
}
sub parseopt {
my %opts;
my $opt_errs = getopts("c:afghlsvq", \%opts);
if ($opts{"h"} || !$opt_errs)
{
printhelp();
}
if ($opts{a})
{
$cl_gonew = 0;
}
if ($opts{c})
{
if (-f $opts{c})
{
$cfgfilename = $opts{"c"};
}
}
if ($opts{"g"})
{
$cl_gonew = 1;
}
if ($opts{"f"})
{
$frommode = 1;
}
if ($opts{"l"})
{
$cl_headers = 1;
}
if ($opts{"s"})
{
$cl_headers = 0;
}
if ($opts{"v"})
{
$verbose = 1;
}
if ($opts{"q"})
{
$quiet = 1;
}
}
sub command_help {
print "\npoppy $poppy_version - written by Chris Bagwell <chris\@cnpbagwell.com> (c) 1997-2002\n\n";
print<<EOF;
[V]iew message - Display the current message, using \$PAGER
if defined in your enviornment.
[D]elete message - Delete the current message from server. Optionally a
- range of messages can be given (i.e. D 1-5)
[S]ave message - Save/Append current message to a specified
file in unix mailbox format. If filename is not
specified with the command it will be prompted for.
[N]ext message - Skip to the next message on the server.
[P]rev message - Goto the previous message on the server.
[G]o to message - Go to a specific message # on server. If no message
number given, it is prompted for.
[R]eply - Send a reply back to the author of the current message.
[A]bort - Quit and do not delete any previous messages
from the mail server.
[Q]uit - Quit program and possibly delete all specified
messages from mail server.
[Enter] - Goto next message on server.
[-] - Goto previous message on server.
[value] - Entering a message number as a command will jump to
that message.
[|] params - Pipe a message to an external program
[!] params - Escape to the shell of your choice or just run a command
EOF
}
# Do anything required to prevent modifications from occuring.
sub abort {
# No need to abort if no object has been defined yet
return if (!defined($poppy));
print "\nAborting modifications...";
if ($poppy->abort()) {
print "OK\n";
}
else {
print "FAILED\n";
}
}
# Disconnect from server. This will also cause any deletions to become
# permenent.
sub disconnect {
# No need to disconnect if no object has been defined yet
return if (!defined($poppy));
print "\nDisconnecting...";
if ($poppy->disconnect()) {
print "OK\n";
}
else {
print "FAILED\n";
}
}
# Version of die() that also cleans up server connections. Attempts
# to prevent modifications from occuring if possible.
sub die_gracefully {
local($msg) = @_;
$msg =~ s/\r*\n*//g;
print STDOUT "An error occurred: '$msg' -- Resetting.\n";
abort();
disconnect();
exit(1);
}
# Signal callback called when a pipe is closed early (usually by ctrl-c).
# This informs the Poppy library so that it stops feading data to the
# output FH. This allows aborts to happen much faster an prevents the
# internal perl I/O routines from getting really confused.
sub close_pipe {
$poppy->abort_read(1);
}
# Returns a list of all mail accounts in form of user@server. Not
# used by poppy but useful example in case someone wants to loop
# over a config file and connect to servers.
sub get_all_mailboxes {
local($tmp, $host, $user, @mailboxes);
@mailboxes = ();
if (! open(POPPYFILE, $cfgfilename)) {
return @mailboxes;
}
while (<POPPYFILE>)
{
chop;
if (/^imap\w*/) # imap server options start with imap
{
($tmp, $host, $tmp, $user, $tmp) = split(' ', $_, 5);
@mailboxes = (@mailboxes, "$user\@$host");
}
if (/^pop\w*/) # pop4 server options start with pop
{
($tmp, $host, $tmp, $user, $tmp) = split(' ', $_, 5);
@mailboxes = (@mailboxes, "$user\@$host");
}
}
return @mailboxes;
}
# Reads in a configuration file and finds the first POP3/IMAP server to
# connect to. If $server_search or $user_search is defined then it will
# look for the first to match those parameters. Also, finds an SMTP
# entry to use for this connection.
sub get_user_info {
my ($tmp, $mailhost, $mailport, $user, $passwd);
my ($match_mailhost, $match_user);
my ($found_server, $found_smtp);
if (-f $cfgfilename) {
open(POPPYFILE,$cfgfilename) || die_gracefully("Can't Open $cfgfilename file! $!");
if ("$^O" eq "MSWin32")
{
my $tmp;
my $mod;
# Skip mod check for Win32 port. Will not work
($tmp,$tmp,$mod,$tmp,$tmp,$tmp,$tmp,$tmp,
$tmp,$tmp,$tmp,$tmp,$tmp) = stat POPPYFILE;
if($mod != 0100600) {
die_gracefully("$cfgfilename needs permissions rw-------");
}
}
$found_server = "";
$found_smtp = 0;
while (<POPPYFILE>)
{
chop;
# imap server options start with imap
if (!$found_server && /^imap\s*/)
{
if ($server_search eq "" || /$server_search*/)
{
if ($user_search eq "" || /$user_search*/)
{
($tmp, $mailhost, $mailport, $user, $passwd) = split(' ', $_, 5);
$ma_proto = "imap";
# Stop looking any more by causing all future lookups to fail.
$found_server = 1;
}
}
}
# pop3 server options start with pop
if (!$found_server && /^pop\s*/)
{
if ($server_search eq "" || /$server_search*/)
{
if ($user_search eq "" || /$user_search*/)
{
$ma_proto = "pop3";
($tmp, $mailhost, $mailport, $user, $passwd) = split(' ', $_, 5);
# Stop looking any more by causing all future lookups to fail.
$found_server = 1;
}
}
}
# smtp server options start with smtp
if (!$found_smtp && /^smtp\s*/)
{
($tmp, $smtp_mailhost, $smtp_mailport, $sender_address, $match_mailhost, $match_user) = split(' ', $_, 6);
# Search for matching SMTP server. If user ever specifies
# a default SMTP server then that will always be used.
if (!$match_mailhost ||
($match_mailhost eq $mailhost && $match_user eq $user))
{
$found_smtp = 1;
}
else
{
$smtp_mailhost = "";
}
}
if (/^editor\s*/)
{
($tmp, $EDITOR) = split(' ', $_, 2);
}
if (/^shell\s*/)
{
($tmp, $SHELL) = split(' ', $_, 2);
}
if (/^pager\s*/)
{
($tmp, $PAGER) = split(' ', $_, 2);
}
if (/^mbox\s*/)
{
($tmp, $MBOX) = split(' ', $_, 2);
}
if (/^headers\s*/)
{
if (/long/) {
$headers = 1;
} else {
$headers = 0;
}
}
if (/^gonew*/)
{
$gonew = 1;
}
}
close(POPPYFILE);
if ($mailhost eq "")
{
die("Could not find a mail server host\n");
}
if ($passwd eq "")
{
print "Mail password for ${user}\@${mailhost}:";
system("stty -echo");
chop($passwd = <STDIN>);
system("stty echo");
print "\n";
}
}
else {
print "No configuration file found. Poppy will attempt to create one.\n\n";
print "Would you like to exit poppy (y/N)?";
chop($answer = <STDIN>);
if ($answer eq "y" || $answer eq "Y")
{
die "Exiting poppy.\n";
}
print "\nPlease provide the following information about your mail server.\n";
print "You may press enter to accept any defaults listed in brackets ([]).\n\n";
print "To change the values in the future, you can modify the file\n";
print "$cfgfilename\n";
print "or you can delete it and rerun poppy to creat it.\n\n";
print "Mail Server Username: ";
chop ($user = <STDIN>);
print "\nYou may enter the password for your account or leave it blank. If left blank\n";
print "then poppy will prompt you to enter it each time it is ran.\n\n";
print "Password: ";
system('stty -echo');
chop ($passwd = <STDIN>);
system('stty echo');
print "\n";
print "\nIs mail server an \"IMAP\" or a \"POP3\" server [POP3]? ";
chop ($tmp = <STDIN>);
if ($tmp eq "imap" || $tmp eq "IMAP")
{
$ma_proto = "imap";
}
if ($ma_proto eq "imap")
{
print "IMAP Host Name: ";
chop ($mailhost = <STDIN>);
print "IMAP Port [143]: ";
chop ($mailport = <STDIN>);
$mailport = 143 if ($mailport eq "");
}
else
{
print "POP3 Host Name: ";
chop ($mailhost = <STDIN>);
print "POP3 Port [110]: ";
chop ($mailport = <STDIN>);
$mailport = 110 if ($mailport eq "");
}
print "Is there an SMTP mail server associated with above host (y/N)? ";
chop ($tmp = <STDIN>);
if ($tmp eq "y" || $tmp eq "Y")
{
print "SMTP Host Name: ";
chop ($smtp_mailhost = <STDIN>);
print "SMTP Port [25]: ";
chop ($smtp_mailport = <STDIN>);
print "From Email Address: ";
chop ($sender_address = <STDIN>);
}
open(POPPYFILE,">$cfgfilename") || die_gracefully("Can't Open $cfgfilename file! $!");
if ($ma_proto eq "imap")
{
printf POPPYFILE "imap ";
}
else
{
printf POPPYFILE "pop3 ";
}
printf POPPYFILE "$mailhost $mailport $user $passwd\n";
if ($smtp_mailhost ne "")
{
printf POPPYFILE "smtp $smtp_mailhost $smtp_mailport $sender_address $mailhost $user\n";
}
close (POPPYFILE);
if ("$^O" eq "MSWin32")
{
chmod(0600,$cfgfilename);
}
if ($passwd eq "")
{
print("Please enter password so that poppy may now login:");
system("stty -echo");
chop($passwd = <STDIN>);
system("stty echo");
print("\n");
}
print("\n");
}
$ma_mailhost = $mailhost;
$ma_mailport = $mailport;
$ma_user = $user;
$ma_passwd = $passwd;
}
# Retreives the header of message # passed in. Displays it in a
# compressed format for better display.
sub retrieve_header {
my $msg_num = shift;
my ($from, $to, $cc, $subject, $date, $reply_to);
my ($apparently_from, $apparently_to);
die_gracefully("Unable to read message header") if (!$poppy->header($msg_num));
$msg_size = int((($poppy->msg_size($msg_num)-1)+1024)/1024);
($from) = $poppy->from();
($apparently_from) = $poppy->apparently_from();
($to) = $poppy->to();
($apparently_to) = $poppy->apparently_to();
($cc) = $poppy->cc();
($subject) = $poppy->subject();
($date) = $poppy->date();
($reply_to) = $poppy->reply_to();
$from = $apparently_from if (!$from);
$to = $apparently_to if (!$to);
$subject = "(No Subject)" if (!$subject);
print "\n";
print(" From: $from\n") if ($from);
print(" To: $to\n") if ($to);
print(" Cc: $cc\n") if ($cc);
print(" Subject: $subject\n") if ($subject);
print(" Date: $date\n") if ($date);
print("Reply-To: $reply_to\n") if ($reply_to);
print " Size: ${msg_size}K bytes\n";
}
# View specified message using $PAGER. Supports viewing with long or
# short headers. WARNING: Only works for viewing a message that just
# had its header retrieved.
sub view_msg {
my $msg_num = shift;
my ($from, $to, $cc, $subject, $date, $reply_to);
my ($apparently_from, $apparently_to);
if (open(MSGFH, "|$PAGER")) {
if ($headers) {
$poppy->message($msg_num, *MSGFH);
}
else {
# Do a dummy read of this message header if its not the
# last one we read.
$poppy->header($msg_num) if ($msg_num != $poppy->last_header_num());
($from) = $poppy->from();
($apparently_from) = $poppy->apparently_from();
($to) = $poppy->to();
($apparently_to) = $poppy->apparently_to();
($cc) = $poppy->cc();
($subject) = $poppy->subject();
($date) = $poppy->date();
($reply_to) = $poppy->reply_to();
$from = $apparently_from if (!$from);
$to = $apparently_to if (!$to);
$subject = "(No Subject)" if (!$subject);
print MSGFH "From: $from\n" if ($from);
print MSGFH "To: $to\n" if ($to);
print MSGFH "Cc: $cc\n" if ($cc);
print MSGFH "Subject: $subject\n" if ($subject);
print MSGFH "Date: $date\n" if ($date);
print MSGFH "Reply-To: $reply_to\n" if ($reply_to);
print MSGFH "\n";
$poppy->body($msg_num, *MSGFH);
}
close(MSGFH);
}
else {
print "Unable to invoke $PAGER to view message.\n";
}
}
# Similar to view_msg(), but sends unaltered to an external program
sub pipe_msg {
my $msg_num = shift;
my $program = shift;
if (open(MSGFH, "|$program")) {
$poppy->message($msg_num, *MSGFH);
close(MSGFH);
}
else {
print "Unable to invoke $program to view message.\n";
}
}
# Saves message in mbox format
sub save_msg {
my ($msg_num, $filename) = @_;
if (! $filename) {
print "\nEnter filename";
if ($MBOX) {
print "[!=$MBOX]";
}
print ":";
chop($filename = <STDIN>);
}
if ($filename eq "\!") {
$filename = $MBOX;
}
if ($filename ne "")
{
if ($filename eq "stdout" && !open(MSGFH, ">&STDOUT")) {
print "Error opening stdout\n";
return;
}
elsif ($filename eq "stderr" && !open(MSGFH, ">&STDERR")) {
print "Error opening stderr\n";
return;
}
elsif (!open(MSGFH,">>$filename"))
{
print "Error opening $filename\n";
return;
}
print "\nSaving message to $filename...";
$poppy->message_mbox($msg_num, *MSGFH);
close(MSGFH);
print "done.\n";
}
}
# Deletes message or range of messages
sub delete_msgs {
my $msg_num = shift;
my $range = shift;
my ($first_msg, $last_msg);
if (!$range) {
$poppy->delete($msg_num);
return($msg_num);
}
# Cosmetic newline
print "\n";
if ($range =~ /(\d+)\s*-+\s*(\d+)/) {
$first_msg = $1;
$last_msg = $2;
}
else {
print "Bad range format. Use \"D firstmsg-lastmsg\"\n";
return(0);
}
if ($first_msg < 1) {
print "Message $first_msg out of range.\n";
return(0);
}
if ($last_msg > $totalmsgs || $last_msg < $first_msg) {
print "Message $last_msg out of range.\n";
return(0);
}
print "Delete messages $first_msg to $last_msg [y/N]? ";
chop (my $answer = <STDIN>);
if ($answer eq "y" || $answer eq "Y")
{
foreach my $msg_to_delete ($first_msg..$last_msg) {
$poppy->delete($msg_to_delete);
}
if ($msg_num >= $first_msg && $msg_num <= $last_msg)
{
# We were viewing a message that got deleted. Return last
# message in range so that main for() loop will increment
# and end up right past $last_msg.
return($last_msg);
}
else
{
# Subtract 1 so that when the main for() loop is executed
# we will end up at the same message we were at.
return($msg-1);
}
}
else
{
return 0;
}
}
# Verifies that message # is valid to goto
sub retrieve_go {
(my $old_msg_num, my $new_msg_num) = @_;
if (!$new_msg_num) {
printf "\nGo to which message? ";
chop ($new_msg_num = <STDIN>);
}
if ($new_msg_num >= 1 && $new_msg_num <= $totalmsgs)
{
return($new_msg_num);
}
else
{
print "\nInvalid message number.\n";
return($old_msg_num);
}
}
# Send a reply email to the message specified on the server.
sub smtp_reply {
my $msg_num = shift;
my @msg_header;
my ($temp_dir, $mail_name);
if ($smtp_mailhost eq "")
{
printf("SMTP host not defined. Can not send replies.\n");
return;
}
# Do a dummy read of this message header if its not the last one we read
$poppy->header($msg_num) if ($msg_num != $poppy->last_header_num());
my ($from) = $poppy->to();
my ($to) = $poppy->from();
my ($reply_to) = $poppy->reply_to();
my ($subject) = $poppy->subject();
my ($msg_id) = $poppy->message_id(@msg_header);
my ($ref) = $poppy->reference(@msg_header);
my ($inreply_to) = $poppy->in_reply_to(@msg_header);
# Remove extra Re: to prevent making string needlessly longer.
$subject =~ s/^[Rr][Ee]: //;
$subject = "Re: " . $subject;
$to = $reply_to if ($reply_to);
$act = " ";
print "\nPlease verify header information:\n";
while ($act ne "C")
{
print "\nFrom: $from\n";
print "To: $to\n";
print "Subject: $subject\n";
printf("\n[F]rom, [T]o, [S]ubject, [A]bort, [C]ontinue:");
chop ($act = <STDIN>);
$param = $act;
# Convert into uppercase
$act =~ tr/a-z/A-Z/;
if ($act eq "F") {
print "From: ";
chop($from = <STDIN>);
}
if ($act eq "T") {
print "To: ";
chop($to = <STDIN>);
}
if ($act eq "S") {
print "Subject: ";
chop($subject = <STDIN>);
}
if ($act eq "A") {
return;
}
}
push(@msg_header, "From: $from");
push(@msg_header, "To: $to");
push(@msg_header, "Subject: $subject");
push(@msg_header, "In-Reply-To: $msg_id") if ($msg_id);
# Add Reference using previous Reference or In-Reply-To field,
# with Reference taking priority. Always add Message-ID if exists.
if ($ref || $msg_id || $inreply_to) {
$ref = $inreply_to unless ($ref);
if ($msg_id) {
if ($ref) {
$ref .= " ";
} else {
$ref = "";
}
$ref .= $msg_id;
}
push(@msg_header, "Reference: $ref");
}
push(@msg_header, "X-Mailer: poppy $Poppy::VERSION");
$temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP};
$mail_name = sprintf("%s/poppy-%d", $temp_dir, time());
# Create an empty file so that we can control the permissions.
unless (open(MAILFILE,">$mail_name")) {
print "Unable to open temporary $mail_name\n";
return;
}
if ("$^O" eq "MSWin32")
{
chmod(0600, $mail_name);
}
close(MAILFILE);
system("$EDITOR $mail_name");
$act = " ";
while ($act ne "S" && $act ne "A")
{
printf("\n[S]end, [A]bort, or [E]dit message:");
chop ($act = <STDIN>);
$param = $act;
# Convert into uppercase
$act =~ tr/a-z/A-Z/;
if ($act eq "E") {
system("$EDITOR $mail_name");
}
}
if ($act eq "A") {
unlink($mail_name);
}
if ($act eq "S") {
unless (open(MAILFILE,"$mail_name")) {
print "Unable to open temporary $mail_name\n";
return;
}
unless ($poppy->connect_smtp(smtp_name =>$smtp_mailhost,
smtp_port =>$smtp_mailport)) {
print "Unable to connect to SMTP server\n";
return;
}
unless ($poppy->send_header(@msg_header) &&
$poppy->send_file(\*MAILFILE)) {
print "Unable to send message\n";
return;
}
$poppy->disconnect_smtp();
close(MAILFILE);
unlink($mail_name);
}
}
sub shell {
local($param) = @_;
print "\nShelling to external program.\n";
if ($param)
{
system($param);
}
else
{
print "Type \"exit\" to return to poppy.\n\n";
system($SHELL);
}
}
sub interactive_mail {
$modifications = 0;
my $act = " ";
my $msg_num;
my $msg_header;
for ($msg_num = $startmsg; $msg_num <= $totalmsgs; $msg_num++) {
retrieve_header($msg_num);
$act = " ";
while ($act ne "D" && $act ne "A" && $act ne "N" && $act ne "Q")
{
printf("\n[Msg $msg_num of $totalmsgs] |=pipe !=shell [R]eply, [N]ext, [P]revious\n[V]iew, [D]elete, [S]ave, [G]o, [A]bort, [Q]uit, or [H]elp:");
chop ($act = <STDIN>);
# The following take user short cuts and map them to suitable
# commands that they map to.
# Hitting return goes to next message
$act = "N" if ($act eq "");
# Typing only a number will go to that message.
$act = "G $act" if ($act =~ /^\d+$/);
# - or [pP] will go to previous message
if ($act eq "-" || $act eq "p" || $act eq "P") {
$act = sprintf("G %d", $msg_num - 1);
}
# Split the action requested into the Action and any Parameters
if ($act =~ /^([A-Za-z\|\!]+)\s*(\S*)/) {
$act = $1;
$param = $2;
}
# Convert action into uppercase
$act =~ tr/a-z/A-Z/;
if ($act eq "V") {
view_msg($msg_num);
}
if ($act eq "T") {
}
if ($act eq "|") {
pipe_msg($msg_num, $param);
}
if ($act eq "S") {
save_msg($msg_num, $param);
}
if ($act eq "D") {
$new_msg = delete_msgs($msg_num, $param);
if ($new_msg) {
$msg_num = $new_msg;
$modifications = 1;
}
else {
# Invalid parameters so set action to NULL to prevent
# advancing to next messages.
$act = "";
}
}
if ($act eq "G") {
$msg_num = retrieve_go($msg_num, $param);
retrieve_header($msg_num);
}
if ($act eq "X") {
if ($verbose == 0) {
print "Verbose (-v) mode on.\n";
$verbose = 1;
}
else {
print "Verbose (-v) mode off.\n";
$verbose = 0;
}
$poppy->debug($verbose);
}
#if ($act eq "T" || $act eq "T ") {
# retrieve_top_msg($msg_num, $param);
#}
if ($act eq "R") {
smtp_reply($msg_num);
}
if ($act eq "H" || $act eq "?") {
command_help();
}
if ($act eq "!") {
shell($param);
}
}
if ($act eq "N" && $msg_num == $totalmsgs) {
print("\nCan not go past last message. Enter \"Q\" to quit.\n");
$msg_num -= 1;
}
if ($act eq "Q" || $act eq "A") {
# Set this so that it will think we are done processing msgs
$msg_num = $totalmsgs + 1;
}
}
if ($act eq "A") {
abort();
}
else {
if ($modifications) {
printf("\nDo you really want to delete the messages [y/N]? ");
chop ($act = <STDIN>);
# Convert into uppercase
$act =~ tr/a-z/A-Z/;
if ($act ne "Y") {
abort();
}
}
}
disconnect();
}
sub from_mail {
my $msg_size;
my ($from, $subject);
my ($apparently_from, $apparently_to);
# Cosmetic newline
print "\n";
for (my $msg_num = $startmsg; $msg_num <= $totalmsgs ; $msg_num++)
{
# When only interested in new messages, do not display last email
# if not new.
if ($gonew && $msg_num<=$lastmsg) {
next;
}
die_graceflly("Unable to read message header") if (!$poppy->header($msg_num));
$msg_size = int((($poppy->msg_size($msg_num)-1)+1024)/1024);
($from) = $poppy->from();
($apparently_from) = $poppy->apparently_from();
($subject) = $poppy->subject();
$from = $apparently_from if (!$from);
$subject = "(No Subject)" if (!$subject);
printf "#%-4d From: %s (%sK bytes)\n Subject: %s\n", $msg_num, $from, $msg_size, $subject;
}
$poppy->disconnect();
}
##############################################################################
# Main
##############################################################################
$PAGER = $ENV{'PAGER'} || "more";
$EDITOR = $ENV{'EDITOR'} || "vi";
$SHELL = $ENV{'SHELL'} || "/bin/sh"; # $SHELL="COMMAND.COM"
$MBOX = $ENV{'POPPY_MBOX'} || "";
# Parse options up front to get -q flag
parseopt();
if (!$quiet) {
printf "\npoppy $poppy_version - by Chris Bagwell <chris\@cnpbagwell.com>\n\n";
}
# Take command line argument... Split name@host or host@name into hostname
# and username to be search in configuration file.
$user_search = $ARGV[0];
if ($ARGV[0]) {
if ($ARGV[0] =~ /(.+)!(.+)/)
{
$server_search = $1;
$user_search = $2;
}
elsif ($ARGV[0] =~ /(.+)\@(.+)/)
{
$user_search = $1;
$server_search = $2;
}
}
else
{
$server_search = "";
$user_search = "";
}
# Get rid of argument since its been processed to match how
# getopt works.
shift(@ARGV);
get_user_info();
$gonew = $cl_gonew if ($cl_gonew ne "");
$headers = $cl_headers if ($cl_headers ne "");
$SIG{"INT"} = 'die_gracefully';
$SIG{"TERM"} = 'die_gracefully';
$SIG{"PIPE"} = 'close_pipe';
printf ("Connecting to $ma_proto account at %s@%s...", $ma_user, $ma_mailhost);
$poppy = Poppy->connect(user_name => $ma_user,
user_pass => $ma_passwd,
server_name => $ma_mailhost,
server_port => $ma_mailport,
server_proto => $ma_proto,
debug => $verbose);
if (!defined($poppy)) {
print "FAILED\n";
exit 1;
}
print "OK\n";
($totalmsgs, $lastmsg, $totalbytes) = $poppy->stats();
# Must properly set the value of $startmsg and it must always equal at
# least 1 for the program to properly work. This will be the point
# for which messages will be read.
if ($gonew)
{
$startmsg = $lastmsg + 1;
# This test makes sure that $startmsg equals at least 1 and
# that it wasn't incremented past $totalmsgs.
if ($totalmsgs != 0 && $startmsg > $totalmsgs) {
$startmsg = $totalmsgs;
}
}
else
{
$startmsg = 1;
}
printf "\n$totalmsgs total messages" if (!$quiet);
if (!$quiet && $totalbytes)
{
my $totalkbytes = int($totalbytes / 1024);
printf " containing ${totalkbytes}K bytes";
}
printf ".\n" if (!$quiet);
if (!$quiet)
{
printf "Last message read is $lastmsg.\n";
}
if (!$frommode) {
interactive_mail();
}
else {
from_mail();
}
syntax highlighted by Code2HTML, v. 0.9.1