/* filename: SendMail.rx                                                    */
/*  version: 1.6     30 Sep 95                                              */
/*  purpose: take input file in Internet RFC822 (e-mail) format and convert */
/*           it into .txt and .wrk files for delivery via an SMTP client    */
/*   syntax: (rx) SendMail <[input file specs]                              */
/*    notes: while this program can be invoked manually, it is intended to  */
/*           be called by AmigaELM as a replacement for other SendMail      */
/*           programs                                                       */
/*   author: Jim Dutton                                                     */
/*           jimd@slip106.termserv.siu.edu                                  */
/*           ca0008@siucvmb.siu.edu                                         */
/* comments: Inspired by Sendmail.rx version 19931205 by Dan Rowan          */
/*                                                                          */
/*           To invoke from AmigaELM, add/modify the "Sendmail"/"Rmail"     */
/*           configuration parameters similar to (using your own directory) */
/*           in the uulib/.elm/elmrc file:                                  */
/*                                                                          */
/*                    SendMail rexxc:rx tcpip:sendmail.rx <$MSG             */
/*                    RMail rexxc:rx tcpip:sendmail.rx <$MSG $TO            */
/*                                                                          */
/*           Some SMTP clients (eg; AmigaNOS) are not able to deal with MX  */
/*           records (or target hosts which do not sport an SMTP server and */
/*           require a seperate mail host to receive mail); an ARexx clip   */
/*           list, needMXlist, is used to find which known hosts use an MX  */
/*           record; another ARexx clip list is used to provide a known mail*/
/*           host which corresponds to the MX record for the original target*/
/*           host, and is called "useMXlist"; both of these lists are built */
/*           and maintained manually by the user via the ARexx RXSET command*/
/*                                                                          */
/*           For example:                                                   */
/*           RXSET needMXlist gwalter.demon.co.uk ppp11.llc.org aston.ac.uk */
/*           RXSET useMXlist post.demon.co.uk biko.llc.org email.aston.ac.uk*/
/*                                                                          */
/*           There is a simple one-to-one correspondance between a known    */
/*           host in the needMXlist and the useMXlist. You will need access */
/*           to something like the NSLOOKUP program to find out the MX      */
/*           record(s) associated with a given host, or you will need to    */
/*           find a Domain Name Server related person who can find out that */
/*           information for you.                                           */
/*                                                                          */
/*           You will need to change the value of the DefaultMailer variable*/
/*           to the host name of a "smart(er)" mail (SMTP) server which can */
/*           resolve host names that your SMTP client cannot; this should be*/
/*           an SMTP server (gateway) within your existing domain/network   */
/*                                                                          */
/*           This SendMail program will process carbon copies and blind     */
/*           carbon copies, but the keywords MUST be spelled correctly (see */
/*           Select clause below), and begin on seperate lines              */
/*                                                                          */
/*           This program also allows MULTIPLE To:, Cc:, or Bcc: targets IF */
/*           each target is immediately followed by a comma (except for the */
/*           LAST target, of course) (eg; <target1>, <target2>)             */
/*                                                                          */
/*           To:, Cc:, and Bcc: target lists may cover more than one line IF*/
/*           each line (but the last one) is terminated with a comma        */
/*                                                                          */
/*           A log file is maintained for every note that is processed. A   */
/*           real sample log entry is:                                      */
/*                                                                          */
/* 22 Nov 1994 19:54:23 To: majordomo@NetBSD.ORG Subject: lists             */
/*                                                                          */
/*           You should modify the path for this log file to conform to your*/
/*           system (set in variable MailLogFile below)                     */
/*                                                                          */
/*           The path for the SMTP client's mail queue on your system should*/
/*           be verified against the MQueue variable below                  */
/*                                                                          */
/*           A working (temporary) copy of the note to be sent is kept on   */
/*           the T: device                                                  */
/*                                                                          */
/*           This SendMail program is by NO means, exhaustive               */
/*                                                                          */
/* V1.5 changes ...                                                         */
/* 1) use ENV:SMTPHOST for default (upstream/"smart") SMTP server/host      */
/* 2) allow for multiple MX lists                                           */
/*                                                                          */
/* V1.6 changes ...                                                         */
/* 1) add support for newsgroup articles (identified by a To: field with a  */
/*    target of <newsgroup name> [ie; no "@" sign]) which inserts NNTP      */
/*    header records and puts the 'note' in the 'news directory',           */
/*    NNTPqueue, which is where AmigaNOS NNTP client looks for news items   */
/*    to post (note: for some unknown reason, AmigaNOS appears to post only */
/*    one note during each NNTP session ???)                                */
/* 2) add generated MSGID to log file entry                                 */
/* 3) added messgage REFID to NNTP articles (notes) log entries such as     */
/*                                                                          */
/* 30 Nov 1995 01:16:47 [30621] To: comp.mail.misc Subject: Re: pop3        */
/*     server for VM/ESA <21b0c6fb.927cc>                                   */

Address 'COMMAND'
Call Initialize
Call ProcessInput
Call CreateMqueue
Call CloseUp
Exit


CloseUp:
  duh = open(seqfile,MQueue'/sequence.seq','W')
  duh = writech(seqfile,seq);  duh = close(seqfile)
  duh = close(STDERR); duh = close(maillog)
  'Delete T:tempfile.txt QUIET'
  If ~show("L","rexxsupport.library")  then  duh = addlib("rexxsupport.library",0,-30,0)
  parse value statef("T:SendmailErrors") with . size .
  If size = 0  then  'Delete T:SendmailErrors QUIET'  /* don't waste dir blocks */
Return


Initialize:
  If open(smtphost,"ENV:smtphost","R")  then
     Do; DefaultMailer = strip(readln(smtphost)); duh = close(smtphost); End
  Else
     Do
        duh = open(reminder,"CON:1/1/460/60/SendMail_Error/close")
        duh = writeln(reminder,"*** Required ENV:smtphost not found ***")
        duh = writeln(reminder, " "); duh = writech(reminder,"Press Enter to quit ...")
        duh = readln(reminder);  foo = close(reminder);  Exit 28
     End

  MailLogFile = "TCPIP:Logs/Mail.log";  isNetNews = no
  MQueue = "TCPIP:spool/mqueue";  NNTPqueue = "TCPIP:Spool/News"
  EndOfHeaders = no;  ReturnTrip = no;  TargetNum = 0;  tabchar = '09'x

  If ~open(seqfile,MQueue'/sequence.seq','R') then
    Do; say "***Can't open sequence.seq file, aborting!"; Exit 32; End
  seq = readln(seqfile); duh = close(seqfile)

  numMXlists = getclip("numMXlists")    /* number of MX lists to parse */
  If ~datatype(numMXlists,"WHOLE")  then  numMXlists = 0
  Else
    Do i = 1 to numMXlists
      needMXlist.i = getclip("needMXlist."i);  useMXlist.i = getclip("useMXlist."I)
      upper needMXlist.i useMXlist.i
    End

  If open(timezone,'ENV:TZ','R') then;  Do; tz=left(readln(timezone),3); duh = close(timezone); End
  Else  tz = "GMT"

  If ~open(maillog,MailLogFile,"A")  then  duh = open(maillog,MailLogFile,"W")
  duh = open(STDERR,"T:SendmailErrors","W"); duh = open(tempfile,"T:tempfile.txt","W")
  duh = writeln(tempfile,'Date: '|| left(date('W'),3) ||', '|| date() ||' '|| time()||' '||tz)
Return


ProcessInput:
  Do while EndOfHeaders = no
    inline = strip(readln(STDIN))
    If substr(inline,1,5) ~= "Bcc: "  then   duh = writeln(tempfile,inline)
    Select
        When  substr(inline,1,6) = "From: "     then  Call  ProcessFromLine
        When  substr(inline,1,4) = "To: "       then  Call  ProcessToLines
        When  substr(inline,1,4) = "Cc: "       then  Call  ProcessToLines
        When  substr(inline,1,9) = "Subject: "  then  Call  ProcessSubjectLine
        When  substr(inline,1,5) = "Bcc: "      then  Call  ProcessToLines
        When  ReturnTrip        ~= no           Then  Interpret "Call" ReturnTrip
        Otherwise;              If inline = ""  then  EndOfHeaders = yes
    End
  End

  Do while ~eof(STDIN);  duh = writeln(tempfile,readln(STDIN));  End
	If isNetNews = yes  then duh = writeln(tempfile,".")
  duh = close(STDIN);  duh = close(tempfile)
Return


ProcessFromLine:
  If pos("<",inline) > 0  then   parse var inline "<"sendinguser">"
  Else parse var inline . sendinguser .
Return


ProcessSubjectLine:
	subjline = inline
	If isNetNews = yes  then  Call  Rewrite_TempFile
Return


Rewrite_TempFile:
	duh = close(tempfile)
	'Rename from T:TempFile.Txt to T:TempFile.Hdrs QUIET'
	duh = open(hdrsfile,"T:TempFile.Hdrs","R")
	duh = open(tempfile,"T:TempFile.Txt","W")
	dateline = strip(readln(hdrsfile)); fromline = strip(readln(hdrsfile))
	parse value readln(hdrsfile) with "<"msgid"-" .
	parse value readln(hdrsfile) with .  newsgroup .
	subjectline = strip(readln(hdrsfile)); duh = close(hdrsfile)

	duh = writeln(tempfile,"Path: slip106.termserv.siu.edu")
	duh = writeln(tempfile,fromline); duh = writeln(tempfile,"Newsgroups:" newsgroup)
	duh = writeln(tempfile,subjectline)
	duh = writeln(tempfile,"Message-Id: <"msgid"@slip106.termserv.siu.edu>") 
	duh = writeln(tempfile,dateline)
	duh = writeln(tempfile,"Sender: NNTP@slip106.termserv.siu.edu")
	duh = writeln(tempfile,"Reply-To: jimd@slip106.termserv.siu.edu")
	duh = writeln(tempfile,"Organization: Southern Illinois University")
	duh = writeln(tempfile,"Comment: AmigaNOS v2.9p")
	'Delete T:TempFile.Hdrs Quiet'
Return


ProcessToLines:
  If pos(',',inline) > 0  then  /* split off multiple address fields */
    Do
	ReturnTrip = "ProcessToLines"; parse var inline inline","
    End
  Else  ReturnTrip = no

  TargetNum = TargetNum + 1;  ToLine.TargetNum = inline
  Select
    When pos("<",inline) > 0  then   parse var inline "<"targetuser">"
    When pos("(",inline) > 0  then
            Do
              parse var inline before"(".")"after;  before = strip(before)
              If before ~= ""  then  targetuser = before
              Else targetuser = after

              If pos(":",targetuser) > 0  then  targetuser = subword(targetuser,2)
              Else
              If substr(targetuser,1,1) = tabchar  then  parse var targetuser +1 targetuser
            End
    When substr(inline,1,1) = tabchar  then   parse var inline +1 targetuser
    Otherwise;    targetuser = subword(inline,2)
  End

	/* determine if targethost is a newsgroup */
	If (pos("@",targetuser) = 0) & (pos(".",targetuser) > 0)  then
		Do; isNetNews = yes; routinghost = ""; Return;  End

  /* determine initial host to route mail to */
  If pos("%",targetuser) > 0  then
    Do
      parse var targetuser userid"%"userhost"@"routinghost .
      targetuser = userid"@"userhost
    End
  Else  parse var targetuser"@"routinghost .

  /* check for known hosts who require an (alternative) MX host */
  If numMXlists > 0  then
    Do
       uppered_routinghost = routinghost;  upper uppered_routinghost
       Do i = 1 to numMXlists
         loc = find(needMXlist.i,uppered_routinghost)
         If loc > 0  then  routinghost = word(useMXlist.i,loc)
       End
    End

  /* check for nasty UUCP addresses and convert */
  upper inline
  If pos("UUCP",inline) > 0  then
    Do
       routinghost = DefaultMailer; parse var targethost lhs"@"rhs".uucp" .
       targetuser = lhs"%"rhs"@uunet.uu.net"
    End

  TargetUser.TargetNum = targetuser;  RoutingHost.TargetNum = routinghost
Return


CreateMqueue:
  Do i = 1 to TargetNum
    seq = seq + 1

		If isNetNews = no  then
			Do
		    duh = writeln(maillog,date() time() "["seq"]" ToLine.i subjline)
		    duh = open(mailwrk,MQueue'/'seq'.wrk','W')
		    duh = writeln(mailwrk,RoutingHost.i); duh = writeln(mailwrk,sendinguser)
		    duh = writeln(mailwrk,TargetUser.i);  duh = close(mailwrk)
		    'COPY T:tempfile.txt TO' MQueue'/'seq'.txt'
			End
		Else
			Do
		    duh = writeln(maillog,date() time() "["seq"]" ToLine.i subjline" <"msgid">")
		    duh = open(mailwrk,NNTPqueue'/'seq'.wrk','W')
				duh = writeln(mailwrk,newsgroup)
				duh = writeln(mailwrk,"<"seq"@slip106.termserv.siu.edu>")
				duh = close(mailwrk)
		    'COPY T:tempfile.txt TO' NNTPqueue'/'seq'.txt'
			End
  End
Return
