-- File: MailerGV.mesa, Last Edit: HGM March 24, 1981 1:04 PM DIRECTORY Ascii USING [CR, SP, TAB], Storage USING [Node, String, Free, FreeString, CopyString], String USING [AppendString, AppendChar, EquivalentString, AppendNumber], Time USING [AppendCurrent], Mailer USING [Level, SendMailViaMTP], PupDefs USING [AppendMyName], SendDefs USING [ AddRecipient, AddToItem, CheckValidity, Create, Destroy, Handle, Send, SendFailed, StartSend, StartText]; MailerGV: PROGRAM IMPORTS Storage, String, Time, Mailer, PupDefs, SendDefs EXPORTS Mailer = BEGIN SendMail: PUBLIC PROCEDURE [ from, subject, to, cc: STRING, body: LONG STRING, sender, password: STRING, info: PROCEDURE [s: STRING, level: Mailer.Level]] RETURNS [worked: BOOLEAN] = BEGIN worked ← SendMailViaGV[from, subject, to, cc, body, sender, password, info] OR Mailer.SendMailViaMTP[from, subject, to, cc, body, sender, password, info]; END; SendMailViaGV: PUBLIC PROCEDURE [ from, subject, to, cc: STRING, body: LONG STRING, sender, password: STRING, info: PROCEDURE [s: STRING, level: Mailer.Level]] RETURNS [worked: BOOLEAN] = BEGIN handle: SendDefs.Handle; recipients, rejections: CARDINAL ← 0; nameList, nameListTail: NameHandle ← NIL; SendHeaderLine: PROCEDURE [field, contents: STRING] = BEGIN IF contents = NIL OR contents.length = 0 THEN RETURN; SendDefs.AddToItem[handle, DESCRIPTOR[@field.text, field.length]]; SendDefs.AddToItem[handle, DESCRIPTOR[@contents.text, contents.length]]; SendCR[]; END; SendDateLine: PROCEDURE = BEGIN date: STRING = [30]; Time.AppendCurrent[date, TRUE]; SendHeaderLine["Date: "L, date]; END; SendFromLine: PROCEDURE = BEGIN temp: STRING = [200]; String.AppendString[temp, from]; String.AppendString[temp, " on "L]; PupDefs.AppendMyName[temp]; SendHeaderLine["From: "L, temp]; END; SendCR: PROCEDURE = BEGIN endOfLine: STRING ← [1]; endOfLine.length ← 1; endOfLine[0] ← Ascii.CR; SendDefs.AddToItem[handle, DESCRIPTOR[@endOfLine.text, endOfLine.length]]; END; SendLongString: PROCEDURE [s: LONG STRING] = BEGIN max: CARDINAL = 200; temp: PACKED ARRAY [0..max) OF CHARACTER; k: CARDINAL ← 0; FOR i: CARDINAL IN [0..s.length) DO temp[k] ← s[i]; k ← k + 1; IF k = max THEN BEGIN SendDefs.AddToItem[handle, DESCRIPTOR[@temp, k]]; k ← 0; END; ENDLOOP; IF k # 0 THEN SendDefs.AddToItem[handle, DESCRIPTOR[@temp, k]]; END; NameHandle: TYPE = POINTER TO Name; Name: TYPE = RECORD [next: NameHandle, name: STRING]; AddName: PROCEDURE [name: STRING] = BEGIN p: NameHandle; FOR p ← nameList, p.next UNTIL p = NIL DO IF String.EquivalentString[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]; IF info # NIL THEN info[s, rejection]; RETURN; END; ENDLOOP; recipients ← recipients + 1; p ← Storage.Node[SIZE[Name]]; p↑ ← [NIL, Storage.CopyString[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: STRING] = BEGIN s: STRING = [100]; String.AppendString[s, "MailerGV: Invalid recipient: "L]; String.AppendString[s, who]; IF info # NIL THEN info[s, rejection]; rejections ← rejections + 1; END; recipients ← SendDefs.CheckValidity[handle, Complain]; END; FindUsers: PROCEDURE [names: STRING] = BEGIN name: STRING ← Storage.String[30]; pos: CARDINAL ← 0; c: CHARACTER; 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; WHILE pos < names.length DO c ← names[pos]; pos ← pos + 1; SELECT c FROM ', => NextName[]; ENDCASE => IF c # Ascii.SP AND c # Ascii.TAB AND c # Ascii.CR THEN String.AppendChar[name, c]; ENDLOOP; NextName[]; Storage.FreeString[name]; END; FreeNames: PROCEDURE = BEGIN next: NameHandle; UNTIL nameList = NIL DO next ← nameList.next; Storage.FreeString[nameList.name]; Storage.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; String.AppendString[temp, "."L]; info[temp, ok]; END; IF password = NIL THEN password ← ""L; -- MakeKey gets an AddressFault ******** -- 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, password, sender, NIL, TRUE] FROM ok => NULL; badPwd => GOTO BadPassword; badSender, badReturnTo => GOTO BadSender; 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]; -- A blank line separates header from body SendCR[]; SendLongString[body]; SendCR[]; SendDefs.Send[handle]; TellHimItWorked[]; worked ← TRUE; EXIT; REPEAT Mixup => info["MailerGV: Mixup someplace."L, trouble]; BadPassword => info["MailerGV: Invalid Sender password."L, trouble]; BadSender => info["MailerGV: Sender 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[]; END; END.