/* declare our variables... I like the name of the object to be the */
/* same as its type, but differ in case */
Protocol protocol;
Connection connection;
Mailbox mailbox;
/* create a protocol object... this object is the "no protcol" */
/* state when it gets created */
protocol=new Protocol();
/* connect to a server on the same machine ... we are now going */
/* to be in the Non-Authenticated state */
protocol.connection("localhost");
/* login to the server ... we'll reach the authenticated state */
/* this is not my real password, so don't bother! */
protocol.LOGIN("iansmith","secret");
/* we're in the new state, but need the object that represents it */
connection=protocol.getConnection();
/* ok, now try to select the system inbox to get the selected state */
connection.SELECT("inbox");
/* made it to selected state (we hope!) and now get the mailbox */
mailbox=connection.getMailbox();
Note that in the interest of clarity of my example I didn't check for the results of the commands which might have (such as LOGIN & SELECT) nor did catch exceptions which might have resulted from these functions. You certainly should do this. Also, this basic structure of issuing a command, checking to see if succeed or failed, then using a "get" function is present in many places in the toolkit, so get used to it now.
Here's an example piece of code which will retreive the subject line of a message and the text of the same Message, assuming the message has only one part and that part is ascii text. Assume that mailbox is already initialized and is an object of type Mailbox.
Message message;
BodyPart bodypart;
String messageContent;
String subject;
...
/* assume I want message number 25 ... the FETCH() command pulls*/
/* messge into the cache if it is not already there */
mailbox.FETCH(25); /* should check for return code here! */
/* get the message data */
message=mailbox.getMessage(25);
/* lets get the subject line into a string */
subject=message.getSubject();
/* now extract the first (and we assume only) body part from the msg*/
bodypart=message.getBodyPart();
/* the body parts have their own cache, so lets fetch the part */
/* note: if you FETCH() anything already in a cache it has no */
/* effect so don't worry about calling this as much as you want */
bodypart.FETCH();
/* now we know that we have the data, get it is as a string */
messageContent=bodyPart.getData();
Let's continue on with that example a little farther. Suppose you wanted to print on the user's terminal a nicely formatted version of where the mail message came from (the from line). You use the MailAddress object to do this. All of the addressing lines of a mail message (from, to, bcc, cc) are extracted from Message objects as a Vector of MailAddress objects. The common case (although not the only case) is for the from line of a mail message to only have one name on it (messages typically only originate from one person) and in next example, we'll assume that this is the case. Also assume the declarations that we had above are still in force with the same types.
Vector vector;
Again, I should be checking the vectorreturned from getFrom() for
being null and for having more than one element.
MailAddress mailaddress;
...
/* assign the vector of mail addresses */
vector=message.getFrom();
/* rip out the first element of the vector (numbered from 0) */
/* note: you must cast the return value here as vector.elementAt() */
/* is defined to just return Object not some subtype of Object*/
/* which is what we want */
mailaddress=(MailAddress)vector.elementAt(0);
/* if they don't have a personal name, just print the email addr */
if (mailaddress.getPersonalName()==null) {
System.out.println(m.getMailboxName()+"@"+m.getHostname());
} else {
/* they supplied a real name, so we'll just use the default */
/* printer that is supplied with the mailaddress object */
/* it formats like this: Ian Smith <iansmith@cc.gatech.edu> */
System.out.println(mailaddress.toString());
}
If you get MIME multipart mail, the multipart container (say, of MIME type "MULITPART" and subtype "MIXED") will be represented as a BodyPart object, as you would expect. This BodyPart will have a linked list of children whose head is accessible as the value of the getFirstChild(). (Note: If you get a null result from getFirstChild() then the BodyPart does not have any children; this is a very useful test!) Each of the children in the linked list will have their successor available by calling getNextSibling(). Thus you had a Message object which consisted of a multipart message with three parts (a text, an image, and an audio clip) you might want a piece of code like this:
/* assume the the variable message is of type Message */
Also, the MIME type/subtype "MESSAGE/RFC822" is special in NDC. If
such a BodyPart is discovered, you can call
getEmbeddedMessage() to retreive a complete
Message object. Remember, you get a Message from
this call, not a BodyPart. Further, the enclosed Message
itself might be multipart or of type/subtype MESSAGE/RFC822, so this
process could proceed recursively. Be aware that the enclosed message
is really part of the mailbox of its encloser, so that closing the
Mailbox it is contained in effectively removes your ability
to access the enclosed Message. Finally, the enclosed
message doesn't have a set of flags like a normal Message
nor can it have new flags added to it via STORE().
/* and is already initialized to the message of interest */
BodyPart multipart,text,image,audio;
/* get the container */
multipart=message.getBodyPart();
/* traverse into the children */
text=multipart.getFirstChild();
/* successor to text is an image ... */
image=text.getNextSibling();
/* successor to image is an audio */
audio=text.getNextSibling();
/* note, audio.getNextSibling() would give null... */
The MIME object performs functions that are useful in dealing with messages which use the MIME standard. Primarily its function is to decode "base64" encoded email. Base64 is an encoding dictated by the MIME standard for dealing with the problem of sending binary data through email. When base64 is used the binary data is encoded into ascii characters (which won't break the mail systems!) which can then be decoded back into the binary by the receiver. The MIME object includes a base64 decoder. If you use the function decodeBase64() you can just pass it the string you get from doing getData() on a BodyPart (see above) and it will return a String which has the binary data.
Other than base64 encoding, the MIME object can be asked for the filename extension that corresponds to a given MIME type. Generally, this is useful if you are writing MIME data out to disk and want to know what type of file extension to use to indicate the type of the data. Note: If you use this function for writing out MIME data, programs such as Netscape usually will recognize the data in its correct type and launch the correct application to view it.
The other utility type is (obviously) Util. This type has only a few functions that are outside of NDC API developers. (Note: And in future versions the users of the NDC API will not be able to access many of the functions that are now in the Util object which are only of internal use.) The two simplest are the getLine() and makeWidth() functions. The first of these reads a line from the user's terminal and returns it as a String and the second pads or truncates a String to a given width. The other function of interest is the stringInVector() function. This function determines if a given String (second paramter of this function) is a member of Vector of Strings (first parameter of this function). This is most useful in dealing with the flags that are stored on a given message, i.e. testing to see if a message has the "\Seen" or "\Deleted" flag set on it.
Finally, the last utility type is the MailboxName object is used with the LIST command on the Connection object. This object has three "get" functions, getSelectable, getInteresting, and getName. The first two are flags that tell you how a mailbox was marked by the IMAP server in response to a request to list the available mailboxes and third one just gives the mailbox's name. Note: All of these values are more fully explained in RFC 1730. To get a list of mailboxes from the Connection object issue a LIST() command and then use the getMailboxNames() to get a Vector of MailboxName objects.
/**
* This is some comment
* @param int i some stuff
* @exception foobar some more stuff
*/
these are the ones for javadoc which you can read about from the java pages at Sun.
The user of the toolkit may notice that some of the functions in the toolkit are have names that are all capitals. Functions whose names are all capitals correspond very closely to the client commands in the IMAP prtocol, if not exactly. This is a way giving the user of the API some idea of which IMAP protocol commands are being issued in response to which of his actions.
Students take note: You are expected to code to a standard that is at least at good as my code. Thus, you should be using javadoc and its comments on all of your code.