-- File: WalnutRetrieveImpl.mesa -- Contents: Implements mail retrieval for Walnut -- Created by Willie-Sue August 26, 1982 -- Lasted edited by: -- Cattell on XXXX -- Willie-Sue on August 29, 1983 4:42 pm DIRECTORY GVRetrieve USING[Failed, Handle, ServerState, Accept, Close, Create, MailboxState, NewUser, NextMessage, NextServer, ServerName, StartMessage], GVBasics USING[Timestamp, RName], IO, Rope, UserCredentials USING [Get], WalnutLog USING [RName, GVMessageToLog, LogLength], WalnutRetrieve, WalnutWindow USING [Report, ReportRope, WatchMailBox]; WalnutRetrieveImpl: CEDAR PROGRAM IMPORTS GVRetrieve, IO, UserCredentials, WalnutLog, WalnutWindow EXPORTS WalnutRetrieve = BEGIN ROPE: TYPE = Rope.ROPE; -- ************************************************************************ RetrieveGVMessages: PUBLIC PROC RETURNS[numRetrieved: INT, allOK: BOOL] = -- reads any new mail BEGIN startOfNewMessages, currentPos: INT; StashNewMessages: PROC [retrieveOK: BOOL] RETURNS[doRemoteFlush: BOOL] = BEGIN allOK_ allOK AND retrieveOK; currentPos_ WalnutLog.LogLength[doFlush: TRUE]; -- don't do remote flush if ~retrieveOK RETURN[retrieveOK AND flushRemoteMail]; END; allOK_ TRUE; startOfNewMessages_ currentPos_ WalnutLog.LogLength[doFlush: TRUE]; numRetrieved_ AddNewMessages[StashNewMessages]; -- changes currentPos IF currentPos = startOfNewMessages THEN {WalnutWindow.Report["No messages were retrieved"]; RETURN}; IF ~allOK THEN WalnutWindow.Report["Some messages may not have been retrieved"]; END; -- *********************************************************************** msgPollingInterval: INT_ 300; -- Number of seconds between mailbox polling. flushRemoteMail: BOOLEAN_ TRUE; gvRetrieveHandle: GVRetrieve.Handle_ NIL; -- cookie for receiving messages. OpenConnection: PUBLIC PROC[user: WalnutLog.RName] = { -- This establishes a retrieve connection, and sets up a Mail Polling proc CloseConnection[]; NewUser[user] ; }; CloseConnection: PUBLIC PROC[] = { -- This closes the connection, and invalidates the connection handle. IF gvRetrieveHandle # NIL THEN { GVRetrieve.Close[gvRetrieveHandle]; gvRetrieveHandle_ NIL}; }; NewUser: PUBLIC PROC[user: WalnutLog.RName] = { -- Establish a new user on this connection. IF gvRetrieveHandle = NIL THEN gvRetrieveHandle _ GVRetrieve.Create[ msgPollingInterval, WalnutWindow.WatchMailBox ]; GVRetrieve.NewUser[gvRetrieveHandle, user, UserCredentials.Get[].password ] ; } ; -- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * MessageState: TYPE = { noMore, wasArchived, wasDeleted, OK, retrieveFailed } ; AddNewMessages: PUBLIC PROC[FinishedWithServer: PROC[BOOL] RETURNS[BOOL]] RETURNS[numRetrieved: INT] = { ENABLE UNWIND => {IF gvRetrieveHandle # NIL THEN GVRetrieve.Close[gvRetrieveHandle]; gvRetrieveHandle_ NIL; WalnutWindow.Report["New Mail NOT retrieved"]; }; -- This is the routine that actually reads the mail & makes the log entry. -- It calls FinishedWithServer to commit the log before it flushes any particular mail server. serverKnown: BOOLEAN _ FALSE; IF gvRetrieveHandle = NIL THEN { -- Open the connection if it's closed. gvRetrieveHandle _ GVRetrieve.Create[msgPollingInterval, WalnutWindow.WatchMailBox]; GVRetrieve.NewUser[gvRetrieveHandle, UserCredentials.Get[].name, UserCredentials.Get[].password]; } ; SELECT gvRetrieveHandle.MailboxState[] FROM badName, badPwd => GOTO credentialsError; cantAuth => GOTO noServers; ENDCASE; --ok to try numRetrieved_ 0; DO -- Loops over servers. messageState: MessageState; messages: CARDINAL _ 0; -- the number of messages read from server. archivedReported: BOOLEAN _ FALSE; -- seen an archived message? -- Cycle through the servers, until you find one that has mail. -- If it has mail, then go for it. noMore: BOOLEAN; -- TRUE if no more servers. serverState: GVRetrieve.ServerState; -- The state of the server. serverName: ROPE ; -- Step through the servers. [noMore, serverState] _ gvRetrieveHandle.NextServer[]; IF noMore THEN EXIT; -- Last server? Then done. serverKnown _ TRUE; serverName _ gvRetrieveHandle.ServerName[]; WalnutWindow.ReportRope[serverName]; WalnutWindow.ReportRope[": "]; IF serverState # notEmpty THEN { IF serverState = empty THEN WalnutWindow.Report["empty"] ELSE WalnutWindow.Report["didn't respond"] ; LOOP; -- Skip to the next server. }; DO messageState_ ReadMessageRecord[] ; SELECT messageState FROM noMore => EXIT ; wasArchived => IF NOT archivedReported THEN { archivedReported _ TRUE; WalnutWindow.ReportRope["(archived messages exist)"]}; OK => NULL; wasDeleted => NULL; retrieveFailed => EXIT; ENDCASE => ERROR; IF NOT (messageState = wasDeleted) THEN { WalnutWindow.ReportRope["."]; messages _ messages + 1}; ENDLOOP ; -- Finished reading messages from this server. -- Flush the mailbox if desired, we've stashed the messages. IF FinishedWithServer[messageState#retrieveFailed] THEN gvRetrieveHandle.Accept[ ! GVRetrieve.Failed => {WalnutWindow.Report["\nFlush of remote messages failed; you may get these messages again"]; CONTINUE}]; IF messageState#retrieveFailed THEN WalnutWindow.Report[IO.PutFR[": retrieved %g messages.", IO.int[messages] ]]; numRetrieved_ numRetrieved + messages; ENDLOOP ; -- End of servers loop, exit. IF NOT serverKnown THEN GOTO noMailboxes; EXITS -- The error reporter for this routine. noMailboxes => WalnutWindow.Report[" No mail boxes"]; credentialsError => WalnutWindow.Report[" Credentials error"]; noServers => WalnutWindow.Report[" No servers responding"]; }; ReadMessageRecord: PROC RETURNS [messageState: MessageState] = { -- This routine reads the messages on this connection, returning messageState = noMore -- when there anren't any more. ENABLE GVRetrieve.Failed => { WalnutWindow.Report[ SELECT why FROM communicationFailure => "communication failure", noSuchServer => "no such server", connectionRejected => "server busy", badCredentials => "bad credentials", unknownFailure => "unknown Failure", ENDCASE => "unknown Error" ]; GOTO gvFailed; } ; msgExists, archived, deleted, ok: BOOLEAN; timeStamp: GVBasics.Timestamp; gvSender: GVBasics.RName; messageState_ OK; [msgExists, archived, deleted] _ GVRetrieve.NextMessage[ gvRetrieveHandle ]; IF archived THEN messageState _ wasArchived; IF deleted THEN { messageState _ wasDeleted; RETURN}; IF NOT msgExists THEN { messageState _ noMore; RETURN}; -- Now read all the items in the message, terminating on the LastItem, and -- skipping the ones that we're not yet interested in. [timeStamp, gvSender, ] _ GVRetrieve.StartMessage[ gvRetrieveHandle ] ; ok_ WalnutLog.GVMessageToLog[gvRetrieveHandle, timeStamp, gvSender]; IF ~ok THEN messageState_ retrieveFailed; EXITS gvFailed => messageState_ retrieveFailed; } ; END. Ę=˜JšˆĪc!œ[œœœ)œĪk œ žœ˜žœžœžœžœDžœ&Īnœž œžœžœ0žœžœžœžœžœLœŸœžœžœžœžœ žœœžœ$žœŸœžœžœžœžœžœžœ;žœ)œžœ žœžœ žœ@žœ8œžœ!žœ9žœœžœžœFžœLœžœ.œžœžœ'žœ"œŸœžœžœKœ.ŸœžœžœFœžœžœžœ=žœ Ÿœžœžœ-œžœžœžœ´Sœžœ&žœŸœžœžœžœžœžœžœžœžœžœžœžœžœžœ;žœ<Ēœžœžœžœžœžœ'œĶžœ!žœžœ#žœžœ œžœœ.žœ,œžœžœœ @œ$œ žœœ)œžœœ?žœžœžœœžœƒžœžœ žœžœ$žœ0žœœžœ2žœžœžœžœžœžœžœ;žœžœžœžœžœžœžœžœžœAžœ/œ=œžœ1žœŖžœžœžœžœ#žœBžœœžœžœ žœžœžœ(œËŸœžœžœ"wœžœ1žœžœņžœ!žœ=žœOžœUžœ žœžœ žœžœžœžœ žœžœ‚œšžœžœ"žœ5žœ˜ë8—…—ną