Subject: Re: Getting Mail headers without mail prog???

From: Out of his mind <[email-masked]>
Date: Wed, 25 Oct 1995 23:09:44 -0400 (EDT)

On Wed, 25 Oct 1995, Automatic digest processor wrote:

> Well, this looks at *all* lines which contain "From".
> It should be "^From: ", though.
> And even this does not skip "included non-quoted mails".
> 
> So - could somebody give a better script?  PERL, anyone?
> I'd promise the best script a postcard from Berlin.
> How about one of the "wrapped Reichstag"?

Which parts of headers do you want? Here is a Perl replacement for 'from'
that I use, and I could certainly customize it for anything you want, or
super-condense it and add support for the Apparently-From: header. Use
'from -h' to get usage; it runs under both Perl 4 and Perl 5. It even
re-canonicalizes addresses to the standard "Name <address>" format, no
matter what format it's currently in.

#!/usr/local/bin/perl -s
# from - Find out who incoming mail is from, with support for mailfiles

sub usage {
  print "'from' displays incoming mail From-addresses, with or without subject,\n";
  print "\toptionally from '~/mbox' or a file.\n";
  print "Usage: from [-s] [-f [mailbox|file]]\n";
  exit;
}
&usage if $h || $help;

sub printhead {
  if ($from) {
    print "From: $from @date\n";
    if ($s) {
      print " Sub: $subject\n" if $subject;
      undef $subject, $subjflag;
    }
    undef $fromflag, $from;
  }
}

if ($f) {
  $file = shift(@ARGV) || "$ENV{'HOME'}/mbox";
  if (! -r $file) {
    print STDERR "Can't open $file\n";
    exit 5;
  }
  open(I,"$file");
} else {
  &usage if $#ARGV >= 0;
  open(I,"$ENV{'MAIL'}");
}
while (<I>) {
  if (/^From /) {
    chop ($i = $_);
    &printhead;
    ($x,$from,@date) = split(/[ \t]+/,$i);
  } elsif (/^From: / && !$fromflag) {
    chop;
    s/^From: //;
    s/ *(.*) +\((.*)\).*/$2 <$1>/;
    s/ *(.*) */<$1>/ unless /.*<.*>.*/;
    s/ *\"(.*)\" *<(.*)> */$1 <$2>/;
    $from = $_;
    $fromflag = 1;
  } elsif ($s && /^Subject: / && !$subjflag) {
    chop;
    s/^Subject: +//;
    $subject = $_;
  }
}
close(I);
&printhead;

=====
== Todd Vierling ([email-masked]): In cyberspace no one can hear you scream. ==
=== Plug: I do freelance C/Perl *IX programming and WWW design. E-mail me ===
=== Vierling's Law: The revolution won't be televised; it will be posted. ===

---

From: [email-masked] (Rick Troxel)
Date: Mon, 30 Oct 1995 21:33:41 GMT

> So - could somebody give a better script?  PERL, anyone?

Since you've asked...  Here's fromf, a script I use that has three
levels of verbosity and some Tenex format support.  (The Pine tech notes
mention two formats; I only used the one I saw my Pine had created.)
You'll want to modify the string identifying the default mailbox by
pathname.

Enjoy,
-- 
Rick Troxel     [email-masked]     [email-masked]     301/496-4824
///////////////////////////////////////////////////////////////////////////
     All effort and exertion put forth by man from the fullness of his
     heart is worship, if it  is prompted  by the  highest motives and
     the will to do service to humanity.                 --Abdu'l-Baha

#!/usr/local/bin/perl
#
# fromf: Like from, but takes a folder name as argument
#	 Has some intelligence in choosing representative sender addresses
#
#	 -v option adds Date: and Subject: headers to report
#	 -V option is same as -v with addition of Message-Id: headers
#	 The string argument gives the name of mailbox file to peruse
#	 -d option provides extra debugging output

# Your choice of default mailbox filename goes here; do not use a tilde '~'
$default = "/home/rick/mail.txt";

$usage = "Usage:\tfromf [-dVv] <file>\n\tTerminating";
require 'getopts.pl';		# from the Perl library [/usr/local/lib/perl]
&Getopts(':dVv');
if ( ($#ARGV == -1) && (-r $default) ) {
    @ARGV = ($default);
}
die $usage if $#ARGV != 0;
exit(1) unless -e $ARGV[0];	# "die" silently for unfound file

$opt_v = 1 if $opt_d;		# debugging mode implies verbose
$opt_v = 1 if $opt_V;		# extra-verbose mode implies verbose

$ll = `ls -l $ARGV[0]`;
print "   $ll";

# Determine whether filename is consistent with Tenex format (cf. pine.faq)
@components = split(/\//, $ARGV[0]);
$basename = pop(@components);
if ($basename eq "mail.txt" || $basename eq "mail.TxT") {
    $tenex_name = 1;
    $tenex_delimiter = '^[ 123]\d-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-[12]\d{3} [012]\d:[0-5]\d:[0-5]\d -\d\d00,\d+;\d{12}$';
}

while (<>) {
    # Determine whether first line is in Tenex format
    if ( ($. == 1) && ($tenex_name) ) {
	$tenex_format = /$tenex_delimiter/ ? 1 : 0;

	$blankline = 0;
	print "* LINE ONE blankline == 0\n" if $opt_d;
	$forwarded = 0;
	print "* LINE ONE forwarded == 0\n" if $opt_d;
	$news = 0;
	print "* LINE ONE news == 0\n" if $opt_d;
	$in_headers = 1;
	print "* LINE ONE in_headers == 1\n" if $opt_d;
	$fromline = "";		# lower priority sender address
	print "* LINE ONE no fromline\n" if $opt_d;
	$dateline = "";		# lower priority date
	print "* LINE ONE no dateline\n" if $opt_d;
    }
    if (/^$/) {
	if ($in_headers) {
	    do {
		print $fromline;
		if ($opt_v) {
		    print "\t$dateline" unless $dateline eq '';
		    print "\t$subjline" unless $subjline eq '';
		    if ($opt_V) {
			print "\t$id" unless $id eq '';
		    }
		}
		$in_headers = 0;
		print "* BLANK  in_headers == 0\n" if $opt_d;
		$fromline = '';	# best return addr known in current msg
		print "* BLANK  fromline == null\n" if $opt_d;
		$dateline = ''; # best known date
		print "* BLANK  dateline == null\n" if $opt_d;
		$subjline = '';	# best known subject header
		print "* BLANK  subjline == null\n" if $opt_d;
		$id = '';	# Message-Id
		print "* BLANK  id == null\n" if $opt_d;
		$blankline = 1;	# have encountered a blank line at hdr end
		print "* BLANK  blankline == 1\n" if $opt_d;
	    } unless $forwarded || $news; # we expect more headers
	}
    }
    if (/^Subject: /) {
        # Look for cues that forwarded headers will follow
        if ( (/^Subject: \[/) || (/^Subject: .*(fwd)/) ) {
	    $forwarded = 1;
	    print "* SUBJ FORW forwarded == 1\n" if $opt_d;
	    $subjline = $_;	# in case forwarder deleted the original hdrs
	    print "* SUBJ FORW $subjline" if $opt_d;
	} else {
	    $forwarded = 0;
	    print "* SUBJ forwarded == 0\n" if $opt_d;
	    $subjline = $_ if $in_headers || $forwarded || $news;
	    print "**SUBJ $subjline" if $opt_d;
	}
    }
#   if (/^Date:/ && ($in_headers || $forwarded || $news)) {
    if (/^Date:/ && $in_headers && ! $realdate) {
	$dateline = $_;		# preferred date header
	print "* DATE $dateline" if $opt_d;
	$realdate = 1;
	print "* DATE realdate == 1\n" if $opt_d;
    }
    if (/^Message-Id:/ && ($in_headers) && ($id eq '')) {
	$id = $_;
	print "* ID $id" if $opt_d;
    }
    if ( ! $tenex_format && (/^From / && ($blankline || ($. = 1))) ) {
	if ($in_headers) {	# i.e. previous message body is empty
				# hence msg has not yet been reported
	    print $fromline;
	    if ($opt_v) {
		print "\t$dateline" unless $dateline eq '';
		print "\t$subjline" unless $subjline eq '';
	    }
	}
	$blankline = 0;
	print "* UNIX FROM blankline == 0\n" if $opt_d;
	$forwarded = 0;
	print "* UNIX FROM forwarded == 0\n" if $opt_d;
	$news = 0;
	print "* UNIX FROM news == 0\n" if $opt_d;
	$in_headers = 1;
	print "* UNIX FROM in_headers == 1\n" if $opt_d;
	$fromline = $_;		# lower priority sender address
	print "* UNIX FROM $fromline" if $opt_d;
	$dateline = $_;		# lower priority date
	print "**UNIX FROM $dateline" if $opt_d;
	$realdate = 0;
	print "* UNIX FROM realdate == 0\n" if $opt_d;
    }
    if ( $tenex_format && /$tenex_delimiter/ ) {
	if ($in_headers) {	# i.e. previous message body is empty
				# hence msg has not yet been reported
	    print $fromline;
	    if ($opt_v) {
		print "\t$dateline" unless $dateline eq '';
		print "\t$subjline" unless $subjline eq '';
	    }
	}
	$blankline = 0;
	print "* TENEX blankline == 0\n" if $opt_d;
	$forwarded = 0;
	print "* TENEX forwarded == 0\n" if $opt_d;
	$news = 0;
	print "* TENEX news == 0\n" if $opt_d;
	$in_headers = 1;
	print "* TENEX in_headers == 1\n" if $opt_d;
	$fromline = "";		# lower priority sender address
	print "* TENEX no fromline\n" if $opt_d;
	$dateline = "";		# lower priority date
	print "* TENEX no dateline\n" if $opt_d;
	$realdate = 0;
	print "* TENEX realdate == 0\n" if $opt_d;
    }
    if (/^From: /) {
	if ($in_headers) {
	    $fromline = $_;	# preferred sender address
	    print "**FROM $fromline" if $opt_d;
	    if (/USENET|news/) {
		$news = 1;	# expect more headers subsequently
		print "* FROM news == 1\n" if $opt_d;
	    } else {
		$news = 0;
		print "* FROM news == 0\n" if $opt_d;
	    }
	}
    }
}

# Input loop has ended; i.e. mailbox has been read in full
# Only needed for Tenex format, as standard mbox format ends with a blank line
if ($in_headers) {		# i.e. final message body is empty
				# hence msg has not yet been reported
    print $fromline;
    if ($opt_v) {
	print "\t$dateline" unless $dateline eq '';
	print "\t$subjline" unless $subjline eq '';
    }
}

# Local variables:
# mode:Perl
# End:
--
Rick Troxel     [email-masked]     [email-masked]     301/496-4823
///////////////////////////////////////////////////////////////////////////
     All effort and exertion put forth by man from the fullness of his
     heart is worship, if it  is prompted  by the  highest motives and
     the will to do service to humanity.                 --Abdu'l-Baha