Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Aug 1995 09:54:43 -0500
From:      Jon Loeliger <jdl@chrome.onramp.net>
To:        Rob Snow <rsnow@txdirect.net>
Cc:        James Ryan <jryan@vt.edu>, freebsd-questions@freefall.FreeBSD.org
Subject:   Re: pop mail 
Message-ID:  <199508251454.JAA19773@chrome.onramp.net>
In-Reply-To: Your message of "Fri, 25 Aug 1995 00:05:27 CDT." <Pine.BSF.3.91.950824234406.27997A-100000@oasis> 

next in thread | previous in thread | raw e-mail | index | archive | help
Apparently, Rob Snow scribbled:
> On Thu, 24 Aug 1995, James Ryan wrote:
> 
> > I know that qpopper is the pop mail server, but is 
> > there a pop mail client that can connect to a 
> > server?
> > 
> > thanks,
> > 	jryan@vt.edu
> 
> get popclient from the /pub/linux/sunsite/system/[mail]? directory on
> ftp.cdrom.com.  It compile out of the box and works great for me.  I've 
> set cron to run it once an hour to retrieve my mail.
> 
> Since this is the 2nd or 3rd time someone has asked this I see that quite 
> a few people, besides myself, have a need for it.  As soon as I finish this 
> message I'll do a port of it.  Hopefully, It'll go better than my first 
> port attempts: tcl-7.4&tk-4.0.
> 
> BTW, here is a small script that I use to get the mail:
> 
> ############ BEGIN INCLUDED SCRIPT ############
> 
> #!/bin/sh
> /sbin/ping -c 2 mailhost
> /usr/local/bin/popclient -3 -u user -p pword -o /var/mail/user mailhost
> 
> ############ END INCLUDED SCRIPT ##############
> 
> user is you, pword is your password, mailhost is where your mail is.
> I use the ping to get iij-ppp out of bed even though I have a static IP.
> If I dont use ping to wake iij-ppp up popclient will often timeout before 
> iij-ppp finishes breakfast and gets to work.  You may also notice that 
> the script appends new mail to your local INBOX in /var/mail instead of 
> using mail to send it to you.  I found that if I didn't do this that all 
> mail ended up being  To: rsnow@txdirect.net  From: rsnow@txdirect.net 
> making it pretty hard to reply to.
> 
> Appending to the file is a BIG kludge since it doesn't do any file 
> locking and simply appends the new mail which causes many mail readers to 
> puke if they happen to be running when the new mail comes in.

Yep, so I hacked a bigger kludge into the script I used for a while.
I've included it here for your potential amusement.  It requires a
~/.pop file that contains on one line:

    <mailhost.my.isp> <mail_port> <user> <passwd>

This one at least locks the mail box in /var/mail/<user>.  It paws around
in the headers to try and determine who the mail might possibly really be
from instead of "popserver".  No, it's not perfect.  It was just enough
of a tolerable improvement that it worked for a while... :-)

jdl

PS -- Jordan, if you ended up using this at all, did it go OK?  Did you
      improve it any?


---------------- ~/bin/pop_client ----------------
#!/usr/bin/perl
# POPMail (RFC1081) Interface for perl
# Copyright (c) 1993 William M. Perry (wmperry@indiana.edu)
#
# Hacked by Bill Reynolds (bill@goshawk.lanl.gov).
# Date strings are done right.
# Mailboxes are now locked during writing.
# Check the permissions on $HOME/.pop, bailing if it's not 600.
#
# Seriously munged by jdl@chromatic.com to better determine real sender.
# Could probably be improved by using RFC822.pl or sendmail.
#

$SIG{'INT'} = 'die_gracefully';
$SIG{'QUIT'} = 'die_gracefully';
$SIG{'TERM'} = 'die_gracefully';
$UID = (getpwuid($<))[2];
$LFILE = "/tmp/popm.$UID";

chop( $ARCH = `uname`);

if ($ARCH = "Linux") { $LINUX = 1; } else { $LINUX = 1; }

# Taken from sigrand by Tom Christiansen (tchrist@convex.com)
# fixed for linux by William Perry (wmperry@indiana.edu)
# (Linux .99pl9 returns 0 on zombie pids)
sub justme {
    if (open LFILE) {
	chop($pid = <LFILE>);
	local($stat) = kill(0,$pid);
	if ($LINUX == 1) {
	    if ($stat == 1) {
		die "$0 already running (pid $pid)\n";
	    }
	}
	else {
	    if ($stat == 0) {
		die "$0 already running (pid $pid)\n";
	    }
	}
	close LFILE;
    }
    open (LFILE, ">$LFILE") || die "can't write $LFILE: $!";
    print LFILE "$$\n";
    close LFILE || die "can't close $LFILE: $!";
} 

sub die_gracefully {
    local($msg) = $_[0];

    print STDERR "An error occurred: $msg\n";
    print STDERR "Resetting.\n";
    unlink "$LFILE";
    print S "rset\n";
    print S "quit\n";
    exit(1);
}

sub quit {
    print S "quit\n";
}

sub openserver {
    local($them, $port) = @_;
    
    $AF_INET = 2;
    $SOCK_STREAM = 1;
    
    $sockaddr = 'S n a4 x8';
    $hostname = "localhost";

    ($name, $aliases, $proto) = getprotobyname('tcp');
    ($name, $aliases, $port) = getservbyname($port,'tcp')
	unless $port =~ /^\d+$/;;

    ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
    ($name, $aliases, $type, $len, $thataddr) = gethostbyname($them);

    # The following line replaced by Will Scales / On-Ramp
    #$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
    $this = pack($sockaddr, $AF_INET, 0, "\0\0\0\0");
    $that = pack($sockaddr, $AF_INET, $port, $thataddr);

    if (socket(S,$AF_INET, $SOCK_STREAM, $proto)) { }
    else { &die_gracefully("Can't open socket: $!"); }

    if (bind(S,$this)) {}
    else { &die_gracefully("Can't bind socket: $!"); }
    
    if (connect(S,$that)) {}
    else { &die_gracefully("Can't connect to socket: $!"); }

    select(S); $| = 1; select(stdout);

    print S "user $user\n";
    ($status, $smsg) = &waitfor("^.\(OK\|ERR\)\(.*\)");
    if ($status ne "OK") {
	&die_gracefully($smsg);
    }
    print S "pass $passwd\n";
    ($status, $smsg) = &waitfor("^.\(OK\|ERR\)\(.*\)");
    if ($status ne "OK") {
	&die_gracefully($smsg);
    }
    &waitfor("^.\(OK\|ERR\)\(.*\)");
}

sub nummsgs {
    print S "stat\n";
    local($status, $messages) = &waitfor("^.\(OK\|ERR\)\(.*\)");
    ($msgs,$octets) = split(' ',$messages);
}

sub waitfor {
    local($signal) = $_[0];
    $_ = <S>;
    while (!/$signal/) {
	$_ = <S>;
    }
    ($1,$2);
}

sub retrieve {
    local($msgnum) = @_;
    local($themsg) = "";
    local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);

    @day = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri','Sat', 'Sun');

    @month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'Jul',
	      'Aug', 'Sep', 'Oct', 'Nov', 'Dec');

    open(SPOOLOUT,"+>/tmp/poptmp.$$");
    
    
    print S "retr $msgnum\n";
    local($status,$smsg) = &waitfor("^.\(OK\|ERR\)\(.*\)");
    if ($status ne "OK") {
	&die_gracefully($smsg);
    }
    else {
	#
	# Try and determine the real sender by finding "From:" header.
	# jdl@chromatic.com
	#
	$nHeaders = 0;
	@headers = ();
	$whom = "popserver";

	$_ = <S>;
	while (!/^\.\r*$/ && !/^$/) {
	    s/\r//g;
	    $headers[$nHeaders++] = $_;
	    if (/^From:/) {
		$1 = "";
		if (/<(.*)@.*>/) {
		} elsif (/[^\s]*\s(.*)@.*/) {
		}
		$whom = $1 if ($1);
		break;
	    }
	    $_ = <S>;
	}

	# 
	# Some mailers are very persnickity about the time string, 
	# hence the goop. BR Wed Sep  8 14:52:34 MDT 1993
	# 

	printf(SPOOLOUT "From %s %s %s %2d %02d:%02d:%02d GMT 19%02d\n",
	       $whom,$day[$wday],$month[$mon],$mday,$hour,$min,$sec,$year);

	for ($i = 0; $i < $nHeaders; $i++) {
	    print SPOOLOUT $headers[$i];
	}

	while (!/^\.\r*$/) {
	    s/\r//g;
	    print SPOOLOUT $_;
	    $_ = <S>;
	}

	print S "dele $msgnum\n";
	($status, $smsg) = &waitfor("^.\(OK\|ERR\)\(.*\)");
	if ($status ne "OK") {
	    &die_gracefully($smsg);
	}
    }

#    FreeBSD mailbox hack.  jdl@chromatic.com
#    open(MBOX, ">>/usr/spool/mail/$user")
    open(MBOX, ">>/var/mail/$user")
	||   &die_gracefully("Can't open mailbox"); 
    
    $LOCK_SH = 1;
    $LOCK_EX = 2;
    $LOCK_NB = 4;
    $LOCK_UN = 8;

    flock(MBOX,$LOCK_EX);
    # and, in case someone appended
    # while we were waiting...
    seek(MBOX, 0, 2);

    seek(SPOOLOUT,0,0);
    while(<SPOOLOUT>){
	print MBOX $_;
    } 
    close SPOOLOUT;
    unlink "/tmp/poptmp.$$";
    flock(MBOX,$LOCK_UN);
    close MBOX;
}

sub get_user_info {
    local($filename) = $ENV{"HOME"} . '/.pop';
    if (-f $filename) {
	open(POPFILE,$filename) || &die_gracefully("Can't Open .pop file! $!");

	($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
	 $atime,$mtime,$ctime,$blksize,$blocks) = stat POPFILE;

	if($mode != 0100600){
	    &die_gracefully("$HOME/.pop needs permissions rw-------");
	    }

	$_ = <POPFILE>;
	chop;
	($pophost, $popport, $user, $passwd) = split(' ',$_);
	close(POPFILE);
    }
    else {
	print "Username: ";
	$_ = <STDIN>;
	chop;
	$user = $_;
	print "Password: ";
	system('stty -echo');
	$_ = <STDIN>;
	chop;
	$passwd = $_;
	system('stty echo');
	print "\n";
	print "Pop Host: ";
	$_ = <STDIN>;
	chop;
	$pophost = $_;
	print "Pop Port: ";
	$_ = <STDIN>;
	chop;
	$popport = $_;
    }
}

&get_user_info;
$pid = fork();

if ($pid != 0) {
    print "Starting popmail daemon for $user\n";
    exit;
}
else {
    &justme;

    while (1) {
	&openserver($pophost,$popport) && &nummsgs;
	for ($msg = 1; $msg <= $msgs; $msg++) {
	    &retrieve($msg);
	}
	&quit;
#	sleep(500);
	sleep(300);
    }
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508251454.JAA19773>