<> <> DIRECTORY DefaultRemoteNames USING [Get], GVBasics USING [RName], GVSend USING [Abort, AddRecipient, AddToItem, CheckValidity, Create, Handle, Send, SendFailed, StartItem, StartSend], IO USING [PutFR, time, rope], Rope USING [Cat, Concat, Find, Flatten, IsEmpty, ROPE], SimpleMailer USING [SendMessageInfo], UserCredentials USING [Get]; SimpleMailerImpl: CEDAR PROGRAM IMPORTS DefaultRemoteNames, GVSend, IO, Rope, UserCredentials EXPORTS SimpleMailer ~ BEGIN ROPE: TYPE = Rope.ROPE; RName: TYPE = GVBasics.RName; SendMessageInfo: TYPE = SimpleMailer.SendMessageInfo; defaultRegistry: ROPE _ DefaultRemoteNames.Get[].registry; SendMessage: PUBLIC PROC [from: ROPE _ NIL, returnTo: RName _ NIL, to, cc: LIST OF RName _ NIL, subject: ROPE _ NIL, otherHeader: ROPE _ NIL, body: ROPE _ NIL, validate: BOOL _ TRUE, sendIfValidateFails: BOOL _ FALSE] RETURNS [sent: BOOL, info: SendMessageInfo] ~ { NoticeInvalidRecipient: PROC [rNumber: INT, rName: RName] = { state _ $invalidRecipient; }; h: GVSend.Handle = GVSend.Create[]; state: SendMessageInfo; aborted: BOOL _ FALSE; sender, senderPwd: ROPE; [sender, senderPwd] _ UserCredentials.Get[]; IF from = NIL THEN from _ sender; DO ENABLE GVSend.SendFailed => IF notDelivered THEN LOOP ELSE EXIT; SELECT h.StartSend[senderPwd, sender, returnTo, validate] FROM ok => state _ $ok; badPwd => { state _ $badPwd; EXIT }; badSender => { state _ $badSender; EXIT }; badReturnTo => { state _ $badReturnTo; EXIT }; allDown => { state _ $allDown; EXIT }; ENDCASE => ERROR; AddRecipients[h, to]; AddRecipients[h, cc]; IF validate THEN { IF h.CheckValidity[NoticeInvalidRecipient] = 0 THEN state _ $noValidRecipients; IF NOT sendIfValidateFails AND state # $ok THEN { h.Abort[]; aborted _ TRUE; EXIT; }; }; h.StartItem[Text]; h.AddToItem[ConsMessage[sender, subject, from, to, cc, otherHeader, body]]; h.Send[]; EXIT; ENDLOOP; RETURN [state IN [$ok .. $noValidRecipients] AND NOT aborted, state] }; AddRecipients: PROC [h: GVSend.Handle, recipients: LIST OF RName] = { FOR r: LIST OF RName _ recipients, r.rest UNTIL r = NIL DO recip: ROPE _ r.first; IF Rope.Find[s1: recip, s2: "."] = -1 THEN recip _ Rope.Cat[recip, ".", defaultRegistry]; h.AddRecipient[recipient: recip]; ENDLOOP; }; ConsMessage: PROC [ sender: RName, subject, from: ROPE, to, cc: LIST OF RName, otherHeader, body: ROPE] RETURNS [ROPE] = { dateRope: ROPE = ConsField["Date", IO.PutFR["%g", IO.time[]]]; senderRope: ROPE = IF from # sender THEN ConsField["Sender", sender] ELSE NIL; subjectRope: ROPE = ConsField["Subject", subject]; fromRope: ROPE = ConsField["From", from]; toRope: ROPE = ConsListField["To", to]; ccRope: ROPE = IF cc # NIL THEN ConsListField["cc", cc] ELSE NIL; header: ROPE = Rope.Cat[dateRope, senderRope, subjectRope, Rope.Cat[fromRope, toRope, ccRope]]; RETURN[Rope.Cat[header, otherHeader, "\n", body]]; }; ConsField: PROC [fieldName, fieldContents: ROPE] RETURNS [ROPE] = { RETURN [IF fieldContents.IsEmpty[] THEN NIL ELSE IO.PutFR["%g: %g\n", IO.rope[fieldName], IO.rope[fieldContents]]]; }; ConsListField: PROC [fieldName: ROPE, fieldContents: LIST OF ROPE] RETURNS [ROPE]= { result: ROPE _ NIL; IF fieldContents # NIL THEN { result _ fieldName.Concat[": "]; DO result _ result.Concat[fieldContents.first]; fieldContents _ fieldContents.rest; IF fieldContents = NIL THEN EXIT; result _ result.Concat[", "]; ENDLOOP; result _ result.Concat["\n"]; }; RETURN [result.Flatten[]]; }; END.