MSRetrieve.mesa
Copyright Ó 1988, 1991 by Xerox Corporation. All rights reserved.
Doug Terry, November 29, 1988 8:40:49 pm PST
Wes Irish, December 22, 1988 3:20:06 pm PST
Operations for retrieval of electronic mail messages.
DIRECTORY
IO USING [STREAM],
MSBasics USING [BodyPartInfo, CHName, Envelope],
Rope USING [ROPE];
MSRetrieve: CEDAR DEFINITIONS
~ BEGIN
STREAM: TYPE ~ IO.STREAM;
ROPE: TYPE ~ Rope.ROPE;
Handles
Handle: TYPE = REF;
This interface is intended to be able to be used by multiple clients. They are distinguished by a "handle", created by "Create" and destroyed by the garbage collector. "Close" should be called when you're finished with the handle as a hint to release resources.
ChangeReportProc: TYPE = PROC [state: MboxState, handle: Handle];
Create: PROC [pollingInterval: CARDINAL, reportChanges: ChangeReportProc ¬ NIL] RETURNS [Handle];
Must be called before any other entries in this interface. Can be called many times. "pollingInterval" is the interval in seconds to wait between successive inbox checks and "reportChanges" (if provided) is called whenever the state of the user's authentication or mailboxes changes; "reportChanges" will not be called if the state changes to "unknown" or "userOK".
Close: PROC [handle: Handle];
Releases resources used by this handle. Further use of this handle is illegal.
Authentication and Mailbox Polling
NewUser: PROC [handle: Handle, user: MSBasics.CHName, password: ROPE];
Provides new user name and password, and starts authentication and mailbox checking.
MboxState: TYPE = { unknown, badName, badPwd, cantAuth, userOK, allDown, someEmpty, allEmpty, notEmpty };
Records current state of the user's mailboxes. Initially "unknown". Set to "badName", "badPwd", "cantAuth" or "userOK" after authentication check. Set to "allDown", "someEmpty", "allEmpty", or "notEmpty" after mail polling is complete. "someEmpty" means not all servers replied and none had mail; "allEmpty" means all replied and none had mail; "notEmpty" means at least one has mail; "allDown" means none replied.
MailboxState: PROC [handle: Handle] RETURNS [state: MboxState];
Returns the current mailbox state.
Access to Mailboxes
The user has a number of mailboxes, each of which is on a XNS mail server. To access all of a client's mail, call "NextServer" repeatedly until it returns noMore=TRUE. For each successful call of "NextServer", if the ServerState is "notEmpty" use the mailbox access procedures to read the mail in the mailbox (otherwise there is no point in using the mailbox access procedures, since the mailbox is either empty or inaccessible).
To read the mail in the mailbox, call "NextMessage" until it returns msgExists=FALSE. While accessing a mailbox, "Failed" may be signalled at any time if the communication system fails (because of network or server error).
"NextBodyPart" may be called to access in sequence the body parts which are the contents of the message. Note that the BodyPartInfo contains the body part type and length in bytes. The message body is followed by a body part of type "lastBodyPart". Within a body part, an IO.STREAM may be used to access the data of the body part. EndOf[] will be true at the end of the body part. Calling NextBodyPart closes any IO.STREAM on a current body part (even if the entire body part has not been read yet) and moves on to the next body part.
At any time within a message, you may call "NextMessage" to skip the remainder of this message.
At any time within a mailbox, you may call "Accept". This terminates reading the mailbox and deletes all messages from the mailbox. Calling "accept" will not delete any messages which you haven't been given a chance to read. No other operations on the mailbox are allowed after calling "accept". If you call "NextServer" without having called "accept", the mailbox is closed (if necessary) without deleting the messages (except those which were deleted by calling "deleteMessage").
FailureReason: TYPE = ATOM;
One of:
$RPC -- communication problems
$Authentication -- bad credentials or authentication service unavailable
$Service -- mail service is busy, unavailable, etc.
$Protocol -- protocol used improperly, undoubtedly due to an implemementation bug in MSRetrieveImpl
Failed: ERROR [why: FailureReason, text: ROPE];
May be signalled by any of the procedures that handle messages.
ServerState: TYPE = { unknown, empty, notEmpty };
NextServer: PROC [handle: Handle] RETURNS [noMore: BOOLEAN, state: ServerState];
Returns information about the next server in the mailbox site list of the user, and that server becomes the "current server". If there is no such server, noMore=TRUE, in which case the next call to "NextServer" will start a new sequence of mail retrieval. If the state is "unknown", attempting to access the mailbox is inadvisable, as the server is probably down. If the state is "empty", there may in fact be mail, as the state is only a hint obtained by polling.
ServerName: PROC [handle: Handle] RETURNS [serverName: MSBasics.CHName];
Provides the name of the current server.
NextMessage: PROC [handle: Handle] RETURNS [msgExists, previouslyRead: BOOLEAN];
Returns information about the next message in the mailbox, and that message becomes the "current message". If there is no such message, msgExists=FALSE. If previouslyRead=TRUE then the message is not new, i.e. it has been marked as being read.
GetMessageEnvelope: PROC [handle: Handle] RETURNS [envelope: MSBasics.Envelope];
Retrieves the message's postmark, msgID, sender, etc.
NextBodyPart: PROC [handle: Handle] RETURNS [MSBasics.BodyPartInfo];
Skips the remainder of any previous body part, then delivers information about the next body part.
GetBodyPart: PROC [handle: Handle] RETURNS [STREAM];
Provides an IO stream for reading the current body part.
GetBodyPartAsRope: PROC [handle: Handle] RETURNS [ROPE];
Provides the current bodyPart as a ROPE. This is probably the most convenient and possible even the most efficient way to get the contents of an item for small to moderate sized items. It is perfectly acceptable for clients to get items solely through this call.
GetBodyPartViaCallback: PROC [handle: Handle, proc: GetBodyPartCallback];
Provides the current bodyPart via a callback. This is probably the most efficient for LARGE items and/or items that the client is putting directly to disk, the network, etc.
GetBodyPartCallback: TYPE ~ PROC [s: STREAM, checkAbort: PROC RETURNS [BOOL]] RETURNS [abort: BOOL];
This is the type of PROC that you must provide to GetItemViaCallback.
"s" is the STREAM from which you can read the item.
You can/should occasionally call "checkAbort" to see if the server wants to abort the transfer. "checkAbort" will RETURN TRUE if it would like you to abort the transfer.
You should return abort=TRUE IFF you aborted reading the stream for some reason.
MarkMessage: PROC [handle: Handle];
Marks current message as being read.
DeleteMessage: PROC [handle: Handle];
Deletes current message.
Accept: PROC [handle: Handle];
Flushes the mailbox entirely (and irrecoverably).
END.