#!/usr/bin/perl -w
# Cotains HARD CODE LOGIC TAILORED TO THE SPECIAL PHRASES!!!!
# Usage: AAAS21Jan07.pl <txtmsg> <email-addresses> <attempts-list> <delay #> <msgslimit>
#        and it expects a file called smtppwd.txt in a location specified
#        below. The <delay> between msgs is in seconds, and the delay used is
#        100-200% of that delay, averaging 150% of the seconds value.
#        The <msgslimit> is the number of messages to send before stopping.
# Example:  sendit06.pl sendit06.17Nov05.textmsg sendit06.17Nov05.do  sendit06.17Nov05.done 40 1000
#
# David Harris, Version of 11 Dec 2006 pm 05:50
# [Autoflushes ATTEMPTS buffer, so one can see what the last email
#  was, after some kinds of crash]

#  [Delays 2 seconds before AUTH authentication is 
#  sent, in hope of giving possibly ansynchronous processes enough
#  time to complete before the authentication process begins.]

# ------------------------------------------------

use Net::SMTP;
use Authen::SASL qw(Perl);


# Read SMTP servername|account|passwd|delay|debugFlag from an outside file that
# can be changed to use different outgoing SMTP systems, perhaps on different
# friends' machines.  The file name and location can be customized here:
open(SMTPPWD, 'C:/htdocs/smtppwd.txt') or die "Couldn't open smtppwd.txt";
chomp($lineread = <SMTPPWD>);     # Reads just first line.
close(SMTPPWD);
# Breaks into 5 substrings at |'s:
($servername, $smtpusername, $passwd, $debugFlag)
        = split /\|/, $lineread, 4;
# 0 for $debugFlag sets NO debugging.

# Check the number of arguments on the command line:
if ($#ARGV+1 != 5) {
  die "sendit06.pl needs txtmsg file, emails file, successes file,
  delayseconds, and msgslimit, as arguments";
  };
  
# Check existence of the textfile and email listing file:
(open TXTMSG, "<$ARGV[0]") or die "sendit06.pl txtmsg file ($ARGV[0]) not found.\n";
(open EMAILS, "<$ARGV[1]") or die "sendit06.pl email targetss file not found.\n";
# And file to report successful sendings:
(open ATTEMPTS, ">$ARGV[2]") or die "sendit06.pl: successes/done file not opened.\n";
# And delay-time base number (up to 100% of it will be randomly added to it):
# Thus a value of 48 sec. will average 50 msg/hour, 8 => 8 to 16 sec, averaging
#  12 sec, etc.  Changes to use of the delay and the random aspect
#   are "hard coded" in this program.
$delayseconds = "$ARGV[3]";
$msgslimit = "$ARGV[4]";

#Read the internal documentation from the TXTMSG template file, and throw
# the internal documentation away:
THRUDOCS: while ($lineread = <TXTMSG>) {
  last THRUDOCS if ($lineread =~ /^----------------------+$/);
}

# Read in the lines that give the substitution target fields,
# like TTTTT=1 and FFFFF=2 etc. (which tell which strings are targets to
# be substituted in the text message farther down in the TXTMSG file)
# followed by an '=' sign and the number of the field (column) to
# substitute from each line of the EMAILS file.

# IF there isn't at least one line of such substitutions, then there will
# not be any variation in the emails sent to, so don't use this program but
# just send an ordinary email to a single (set of) persons.

$linenum = 0;
while ($lineread = <TXTMSG>) {
  chomp $lineread;
  if ($lineread =~ /\w+=\d+/) {
     ($substit[$linenum], $subsfield[$linenum]) = split /=/, $lineread, 2;
     $linenum++;
  } elsif ($lineread =~ /^M+$/) {
     last;
  }
    else { die "MMMMMM...MMMMM line not found.\n";}
}

$msglines = 0;
# Read in the substitutable lines from the textfile opened above:
while ($lineread = <TXTMSG>) {
# The mail stuff wraps the lines if needed.
$messagearray[$msglines] = $lineread;
$msglines++;    # The array grows and this index is used below.
};
close(TXTMSG);

$emailnumber = 1;  # Counter of emails sent, for output near end.
 
# Do the rest of this program once for each non-empty line in EMAILS file,
#  until the count limit is reached:
while ((chomp($email = <EMAILS>)) && (length($email) > 2)
       && ($emailnumber <= $msgslimit)) {
  # Put fields into array.
  @fields = split /\|/, $email;

  # Now @messagearray has the text with the targets embedded,
  #     @substit has the images of the targets,
  #     @subsfield has the numbers of the fields that are  used, and
  #     @fields has the fields OF THIS PARTICULAR EMAIL FILE LINE
  #        to put in place of the targets.

  # Activate the SMTP link: [IMPLEMENTING A RETRY ABILITY]
  $numretries = 0;
  RETRY: for ($retries = $numretries; $retries >= 0; $retries--) {
  # Make the 'Date:' string for this particular email
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
                  localtime(time-(0*3600)-3);  # Future time zone correction?
  $weekday = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday];
  $monthname = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon];
  $yr2000 = $year+1900;
  if (length($mday) == 1) {
    $mday = '0'.$mday;
  }
  if (length($hour) == 1) {
    $hour = '0'.$hour;
  }
  if (length($min) == 1) {
    $min = '0'.$min;
  }
  if (length($sec) == 1) {
    $sec = '0'.$sec;
  }
  $datestr = "$weekday, $mday $monthname $yr2000 $hour\:$min\:$sec +0000\n";
  $hadwarning = 0;  # Set problem flag to "No problemo" before trying to send.
  # $servername comes from smtppwd.txt file here.:
  if ($debugFlag eq '0') {
    $smtp = Net::SMTP->new( Host => $servername,
                            Hello => 'darwinday.sbcglobal.net',
                            Timeout => 120 );
  } else {
    $smtp = Net::SMTP->new( Host => $servername,
                            Hello => 'darwinday.sbcglobal.net',
                            Timeout => 120,
                            Debug => 1 );     # Non-zero says DO debugging.
  }
  sleep 2;  # Does this give enough time to avoid the "auth error"
            #   problems?
  $smtp->auth($smtpusername,$passwd);  # Authentication!
  #Start of substitutable message, as stored in array by code above.
  MSGLINE:
  for ($j = 0; $j < $msglines; $j++) {  # Step thru array of stored lines
    $linetosend = $messagearray[$j];
      ## HARD CODE LOGIC TAILORED TO THE SPECIAL PHRASES:
      ## Conditional insertion of the special PR thank you phrase:
      ## First for the plain text version and then for the HTML text version:
      #if ($linetosend =~ m/^We are particularly grateful for the SSSSS/) {
      #  if ($fields[4] eq 'orig') {
      #    $j = $j + 1;  #Skip 'orig' lines from emiting the 2 line grateful phrase.
      #    next MSGLINE;
      #  };
      #};
      #if ($linetosend =~ m/0.510in/) {  # Special unique but harmless modification is the flag.
      #  if ($fields[4] eq 'orig') {
      #    $j = $j + 3;  #Skip 'orig' lines from emiting the 4 line grateful phrase in HTML.
      #    next MSGLINE;
      #  };
      #};  # END OF HARD CODED LOGIC
    for ($i = 0; $i < $linenum; $i++) {  #For this line, make substitutions
                  # from the i-inexed array of subtitutions.          
      # Make a substitution as often as needed in 1 line:
    ($linetosend = $linetosend) =~ s/$substit[$i]/$fields[$subsfield[$i]-1]/g;
    };
    # Special calls for the first 3 lines:
    SWITCH: {
      if ($j == 0) { eval'$smtp->mail($linetosend)';
                    if ($@) {warn("WARNING: $@\n"); $hadwarning = 1 };
          last SWITCH;
      }
      if ($j == 1) { eval'$smtp->recipient($linetosend)';
                    if ($@) {warn("WARNING: $@\n"); $hadwarning = 1 };
          last SWITCH;
      }
      # Blank line then the computed date:
      if ($j == 2) { eval'$smtp->data()';
                    if ($@) {warn("WARNING: $@\n"); $hadwarning = 1 };
          last SWITCH;
      }
      # All further lines:
      if ($linetosend =~ m/^From: /) {
        $smtp->datasend("Date: $datestr");  # Emit computed date
      }
      chomp($linetosend);  # Lines must end with CR/LF!
      eval '$smtp->datasend($linetosend."\r\n")';
            if ($@) {warn("WARNING: $@\n"); $hadwarning = 1 };
      #print STDERR "DOLLAR-AT VALUE IS $@\n"; 
    } # End of SWITCH.
  }
  $smtp->dataend();
  $smtp->quit;
  # Write the emails.txt line that was attempted to be sent, and its number:
  chomp($dateinsert = $datestr);
  # Cause ATTEMPTSs log to flush after every char write
  #                (from p.781 of Programming Perl, v.3):
  my $oldfilehandle = select ATTEMPTS; $| = 1 ; select $oldfilehandle;
  if ($hadwarning == 1) {
    print ATTEMPTS  "$dateinsert HADWARNING |$emailnumber|$email\n" ;
    print STDERR "At $dateinsert HADWARNING #$emailnumber: $email\n" ;        
  } else {
    print ATTEMPTS  "$dateinsert processed|$emailnumber|$email\n" ;
    print STDERR "At $dateinsert processed #$emailnumber: $email\n" ;
    $emailnumber++ ;  # Only increment on successes
  }
  # Let some seconds elapse: the specified time plus randomly to 100% more:
  sleep $delayseconds + int(rand ($delayseconds * 100/100)) ;
    }
  }  # End of processing one line of email addresses (one person).
print STDERR "ATTEMPTS file closed and about to exit now.\n" ;
exit;