-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. -- MailerGV.mesa, HGM, 15-Dec-83 18:24:00 DIRECTORY Ascii USING [CR, SP, TAB], Heap USING [Create, Delete], String USING [AppendString, AppendChar, Equivalent, AppendNumber], Time USING [Append, Unpack, Unpacked], Mailer USING [Level], PupDefs USING [AppendMyName], SendDefs USING [ AddRecipient, AddToItem, CheckValidity, Create, Destroy, Handle, Send, SendFailed, StartSend, StartText]; MailerGV: PROGRAM IMPORTS Heap, String, Time, PupDefs, SendDefs EXPORTS Mailer = BEGIN SendGVMail: PUBLIC PROCEDURE [ subject, to, cc, body, troubles: LONG STRING, info: PROCEDURE [s: LONG STRING, level: Mailer.Level]] RETURNS [worked: BOOLEAN] = BEGIN handle: SendDefs.Handle; recipients, rejections: CARDINAL ← 0; nameList, nameListTail: NameHandle ← NIL; z: UNCOUNTED ZONE = Heap.Create[4]; SendHeaderLine: PROCEDURE [field, contents: LONG STRING] = BEGIN IF contents = NIL OR contents.length = 0 THEN RETURN; SendDefs.AddToItem[ handle, [LOOPHOLE[@field.text, LONG POINTER], 0, field.length]]; SendDefs.AddToItem[ handle, [LOOPHOLE[@contents.text, LONG POINTER], 0, contents.length]]; SendCR[]; END; SendDateLine: PROCEDURE = BEGIN days: ARRAY [0..7) OF STRING = [ "Monday"L, "Tuesday"L, "Wednesday"L, "Thursday"L, "Friday"L, "Saturday"L, "Sunday"L]; date: STRING = [40]; now: Time.Unpacked = Time.Unpack[]; Time.Append[date, now, TRUE]; String.AppendString[date, " ("L]; String.AppendString[date, days[now.weekday]]; String.AppendChar[date, ')]; SendHeaderLine["Date: "L, date]; END; SendFromLine: PROCEDURE = BEGIN temp: STRING = [200]; PupDefs.AppendMyName[temp]; String.AppendString[temp, ".internet"L]; SendHeaderLine["From: "L, temp]; END; SendCR: PROCEDURE = BEGIN endOfLine: STRING ← [1]; endOfLine.length ← 1; endOfLine[0] ← Ascii.CR; SendDefs.AddToItem[ handle, [LOOPHOLE[@endOfLine.text, POINTER], 0, endOfLine.length]]; END; NameHandle: TYPE = LONG POINTER TO Name; Name: TYPE = RECORD [next: NameHandle, name: LONG STRING]; AddName: PROCEDURE [name: LONG STRING] = BEGIN p: NameHandle; FOR p ← nameList, p.next UNTIL p = NIL DO IF String.Equivalent[p.name, name] THEN RETURN; ENDLOOP; FOR i: CARDINAL IN [0..name.length) DO IF name[i] = '. THEN EXIT; REPEAT FINISHED => BEGIN OPEN String; s: STRING ← [200]; AppendString[s, "MailerGV: Registry missing: "L]; AppendString[s, name]; info[s, rejection]; RETURN; END; ENDLOOP; recipients ← recipients + 1; p ← z.NEW[Name]; p↑ ← [NIL, z.NEW[StringBody[name.length]] ]; String.AppendString[p.name, name]; IF nameList = NIL THEN nameList ← p ELSE nameListTail.next ← p; nameListTail ← p; END; SendRecipientList: PROCEDURE = BEGIN FOR recipient: NameHandle ← nameList, recipient.next UNTIL recipient = NIL DO SendDefs.AddRecipient[handle, recipient.name]; ENDLOOP; END; CheckForRejections: PROCEDURE = BEGIN Complain: PROCEDURE [n: CARDINAL, who: LONG STRING] = BEGIN s: STRING = [100]; String.AppendString[s, "MailerGV: Invalid recipient: "L]; String.AppendString[s, who]; info[s, rejection]; rejections ← rejections + 1; END; recipients ← SendDefs.CheckValidity[handle, Complain]; END; FindUsers: PROCEDURE [names: LONG STRING] = BEGIN name: STRING = [100]; NextName: PROCEDURE = BEGIN WHILE name.length > 0 AND name[name.length - 1] = Ascii.SP DO name.length ← name.length - 1; ENDLOOP; IF name.length > 0 THEN AddName[name]; name.length ← 0; END; FOR i: CARDINAL IN [0..names.length) DO c: CHARACTER ← names[i]; SELECT c FROM ', => NextName[]; ENDCASE => IF c # Ascii.SP AND c # Ascii.TAB AND c # Ascii.CR THEN String.AppendChar[name, c]; ENDLOOP; NextName[]; END; FreeNames: PROCEDURE = BEGIN next: NameHandle; UNTIL nameList = NIL DO next ← nameList.next; z.FREE[@nameList.name]; z.FREE[@nameList]; nameList ← next; ENDLOOP; END; TellHimItWorked: PROCEDURE = BEGIN temp: STRING = [100]; String.AppendString[temp, "MailerGV: Sent it"L]; String.AppendString[temp, " to "L]; String.AppendNumber[temp, recipients, 10]; String.AppendString[temp, " reciepient"L]; IF recipients # 1 THEN String.AppendString[temp, "s"L]; IF rejections # 0 THEN BEGIN String.AppendString[temp, ", but there were "L]; String.AppendNumber[temp, rejections, 10]; String.AppendString[temp, " rejections"L]; END; info[temp, ok]; END; -- Here begins the real thing worked ← FALSE; FindUsers[to]; IF cc # NIL THEN FindUsers[cc]; IF nameList = NIL THEN BEGIN info["MailerGV: No recipients in to or cc list"L, trouble]; RETURN; END; handle ← SendDefs.Create[]; FOR tries: CARDINAL IN [0..4) DO ENABLE SendDefs.SendFailed => BEGIN info["MailerGV: Send Failed"L, trouble]; CONTINUE; END; SELECT SendDefs.StartSend[handle, "Portola"L, "PupGateway.auto"L, troubles, TRUE] FROM ok => NULL; badPwd => GOTO BadPassword; badSender => GOTO BadSender; badReturnTo => GOTO BadTroubles; allDown => GOTO AllDown; ENDCASE => GOTO Mixup; SendRecipientList[]; CheckForRejections[]; IF recipients = 0 THEN GOTO NoValidRecipients; SendDefs.StartText[handle]; SendDateLine[]; SendFromLine[]; SendHeaderLine["Subject: "L, subject]; SendHeaderLine["To: "L, to]; SendHeaderLine["cc: "L, cc]; SendHeaderLine["Reply-To: "L, troubles]; -- A blank line separates header from body SendCR[]; SendDefs.AddToItem[ handle, [LOOPHOLE[@body.text, LONG POINTER], 0, body.length]]; SendCR[]; SendDefs.Send[handle]; TellHimItWorked[]; worked ← TRUE; EXIT; REPEAT Mixup => info["MailerGV: Mixup someplace"L, trouble]; BadPassword => info["MailerGV: Invalid Sender password; Call GrapevineWizard"L, trouble]; BadSender => info["MailerGV: Sender rejected; Call GrapevineWizard"L, trouble]; BadTroubles => info["MailerGV: ReturnTo rejected"L, trouble]; AllDown => info["MailerGV: All Servers appear to be down"L, trouble]; NoValidRecipients => info["MailerGV: No valid recipients"L, trouble]; FINISHED => info["MailerGV: Too many retries"L, trouble]; ENDLOOP; SendDefs.Destroy[handle]; FreeNames[]; Heap.Delete[z]; END; END.