#!/usr/bin/perl

# Script to generate a return read receipt similar to the one sent
# from Pegasus mail.  The script also keeps up with "Message-Id:"
# headers so that read receipts will only be sent for the first
# read and not for subsequent reads.
#
# Pegasus mail inserts a header into the mail message called
# "X-Confirm-Reading-To:".  If Pegasus sees this same header on
# an incoming mail message then it will respond by sending a
# read confirmation message as soon as the message is opened.
# There is no standard for this type of receipt.  One advantage
# of this script is that it can be easily tailored to look for
# a similar header from other email tools.
#
# Requests for read receipts should be ignored if the message being
# scanned is from the current user.  For instance, a mailbox that
# contains copies of outgoing messages will likely have
# X-Confirm-Reading-To headers.  These should be ignored because they
# were actually addressed remote users.
#
# The script is to be called from a macro inside mutt that looks like:
#
# macro index <return> '|cat > /tmp/mutt.out^M!/home/gentlec/local/bin/muttrcpt.pl^M '
#
# This macro first cats the message into /tmp/mutt.out and then
# fires off this script to process the contents of /tmp/mutt.out.
# The space at the end of the macro tells mutt to go ahead and
# display the contents of the message after the script exits.
#
# Notes:
# I originally tried having mutt to pipe it's message directly across
# this script.  This approach did not work.  I was unable to read a
# Yes/No response from the user when asked if a receipt should be sent.
# It appeared that after reading the file from <STDIN> there was still
# something in the buffer.  The script would just fall through the prompt
# and no value would be assigned.  I haven't figured out how to get
# around this problem yet.
# 
# Chris Gentle
# Tue Mar  9 10:57:58 CST 1999
#
# Chris Gentle
# Mon Apr 16 13:32:11 CDT 2001
# Modified to include a "neVer" option.  Sometimes you never want to send
# a reply and mutt needs to stop asking when you re-read these messages.
# Just store the message_id and forget it.
#
# Chris Gentle
# Wed Jul 18 09:01:21 CDT 2001
# Modified to (1) parse gcos field of password file to determine
# first.last format used by Exchange server email addresses, and (2)
# perform case insensitive searching for receipt headers.  Pegasus
# apparently changed the case of the X-Confirm-Reading-To header and
# it was not being seen by this script.
#
# Chris Gentle Tue Aug 21 14:04:50 CDT 2001 Fixed a couple of bugs
# with the Message-ID header.  First, I learned there is no standard
# case for this header.  I needed a case insensitive search to
# ensure that the message ID was actually located.  I changed the
# regexes to ignore case.  Also, I received a message that had such
# a long message-id that the string was actually found on the line
# following the "Message-ID:" header.  This means that message-id's
# can conceivably span more than one line.  The program now strips
# off the "Message-ID: " text and if the result is blank it will
# retrieve the next line of input to get the message id text.


###########################################################################
#
# Configuration Variables
#
###########################################################################

$home = $ENV{"HOME"};

# File to store unique message id's from headers that have already
# had a receipt sent.
$idfile = "$home/.messageid";

# Temp file that currently holds the email message that was output
# from mutt.
$tempfile = "/tmp/mutt.out";

# Draft file used to construct the headers and body for the receipt.
$draftfile =  "/tmp/mutt.draftfile";

# Current user.
$user = $ENV{"USER"};

# If this script is going to be used by more than one person, we need to
# get the user's name in first.last format so that later in the script we can
# determine if the message is question is from the user.  It turns out that
# the information in the gcos field of the passwd file is exactly what we
# need.

($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwnam($user);
$gcos =~ s/ /\./g;

# Open the tempfile and read the headers, storing information from
# specific headers into variables.

open (FILE, "$tempfile") || die "Can't open $tempfile for reading.";
while (<FILE>) {
  chop();

  # Only read the header.  Bail out when a blank line is found.
  if ( $_ eq "" ) {
    last;
  }

  if ( /^X-Confirm-Reading-To:/i ) {  # Pegasus read receipt requested
    s/^X-Confirm-Reading-To: //g;
    $recipient = $_;
  }
  elsif ( /^Disposition-notification-to:/i ) { # Netscape receipt requested
    s/^Disposition-notification-to: //g;
    $recipient = $_;
  }
  elsif ( /^Return-Receipt-To:/i ) { # Netscape receipt requested
    s/^Return-Receipt-To: //g;
    $recipient = $_;
  }
  elsif ( /^Subject:/ ) {
    s/^Subject: //g;
    $subject = $_;
  }
  elsif ( /^Date:/ ) {
    s/^Date: //g;
    $date = $_;
  }
  elsif ( /^Message-ID:/i ) {
    s/^Message-ID: //ig;

    # If a very long message-id exists, it could actually show up on the
    # NEXT line rather than the line with the header tag.
    if (/^$/) {  
      $_ = <FILE>;
      chop();
      s/ //g;
    }

    $messageid = $_;
  }
  elsif ( /^From:/ ) {
    s/^From: //g;
    $from = $_;
  }
}
close(FILE);
unlink("$tempfile");


# Bail out if no return receipt requested or if current message is
# from current user.
if ( $recipient eq "" || $from =~ /$user/ || $from =~ /$gcos/i ) {
  exit;
}

# Check the $idfile to be sure a read receipt has not been sent for
# this message yet.  We only want a receipt sent the first time the
# message is read.

open(FILE, "$idfile");
while (<FILE>) {
  chop;
  if ( $_ eq $messageid ) { # if current $messageid is found
    exit;
  }
  push(@ids, $_);
}
close(FILE);


system("clear");
print "\n\n$recipient has requested a read receipt\n";
print "for this message.  Do you wish to send this receipt now?  [Yes/No/neVer] ";
$answer = <STDIN>;

chop;

if ($answer eq "" || $answer =~ /[Yy]/ ) {

  # Construct the mutt draftfile.
  open (FILE, ">$draftfile") || die "Can't open $draftfile\n";
  print FILE "Subject: RCPT: $subject\n";
  print FILE "To: $recipient\n";
  print FILE "\n\n";
  print FILE "Confirmation of reading:  your message -\n\n";
  print FILE "    Date:    $date\n";
  print FILE "    To:      $recipient\n";
  print FILE "    Subject: $subject\n\n";
  print FILE "Was read at " . `date` . "\n";
  close(FILE);

  # Command line used to fire off the mail message
  $cmd = "mutt ";  # Location of mutt
  $cmd = $cmd . "-H $draftfile < /dev/null";   # draftfile to use
  system($cmd);
  print "Mail sent.\n";

  # Clean up temp files
  unlink("$draftfile");

  # Store the message id into the id file.
  push(@ids, $messageid);
  open(FILE, ">$idfile") || die "Can't open $idfile for writing.\n";
  foreach $id (sort(@ids)) {
    print FILE "$id\n"; 
  }
  close(FILE);
}
elsif ($answer =~ /[Vv]/ ) {
  # Store the message id into the id file.
  push(@ids, $messageid);
  open(FILE, ">$idfile") || die "Can't open $idfile for writing.\n";
  foreach $id (sort(@ids)) {
    print FILE "$id\n"; 
  }
  close(FILE);
}
