import MessageException; import FolderException; import LoginException; import NetworkConnection; import SimpleOutput; import MessageHeader; import MailMessage; /** * A protocal for Java to interact with an IMAP server * * @author Ben Kaiser * @author Josh Vickery * @version 2.0 of October 1999 * * @modified from version 1.1 to become a class instead of an interface * @modified the interface was renamed MailboxInterface.java * @modified actual implimentation */ public class Mailbox implements MailboxInterface { //+--------+ //| Fields | //+--------+ /** * Since the IMAP server requires a unique number before each command we * must create a variable to keep track of that number and update that * number each time we call a command. */ int count = 0; /** * Create a new Socket object */ java.net.Socket sock; /** * Create a new data input stream to read from the server */ java.io.BufferedReader dis; /** * Create a new stream printer to print to the server */ java.io.PrintWriter ps; /** * an integer to store the number of messages in the current folder */ int numMessages; /** * Prepare for MessageHeader return * Since the MessageHeader class is not implimented use, strngs for now */ String[] headers; /** * Prepare for MessageReturn */ /** * Create the mailbox (initializing all the damn fields), connect to the * default server and port, and read the servers greating * @exception when we cannot establish a succesful connection to the server */ public Mailbox() throws ConnectionException { try { // open the socket sock = new java.net.Socket("pioneerserver.grinnell.edu", 143); } // try catch (Exception e1) { throw new ConnectionException("server unreachable"); } //catch try { // prepare for input dis = new java.io.BufferedReader(new java.io.InputStreamReader(sock.getInputStream())); } //try catch (Exception e2) { throw new ConnectionException("unable to establish connection"); } //catch try { // prepare for output ps = new java.io.PrintWriter(sock.getOutputStream(), true); } //try catch (Exception e3) { throw new ConnectionException("unable to connect"); } //catch try { // read the greating from the IMAP server dis.readLine(); } //try catch (Exception ex) {} } // Mailbox() /** * Attempt to login to the server * This will attempt to create a NetworkConnection using the * NetworkConnection class, with a server name and port deterimined by * the preferances class. If successful it will attemp to login using * the given name and passwd. It will then set the folder to inbox * @exception LoginExcpetion * when it is a bad UserName Password combo */ public void login(String username, String passwd) throws LoginException, Exception { // set the count count = count + 1; SimpleOutput out = new SimpleOutput(); // login with the given username and pass ps.print("a" + count + " LOGIN " + username + " " + passwd); ps.println('\r'); //ps.print('\n'); // check to see if the login worked try { this.clear(); String store; store = dis.readLine(); out.println(store); if (!(store.equals("a" + count + " OK LOGIN completed."))) { throw new LoginException("badlogin"); } // if badlogin } //try catch (Exception e4) {throw new Exception("IOException");} // if login is succesful set the folder to inbox try { this.setFolder("Inbox"); } catch (Exception fe) {/* this will not fail since Inbox must exist */ } } // Login(String, String) /** *closes the imap socket. *Pre: there is an IMAP socket open. */ public void bye() { SimpleOutput out = new SimpleOutput(); // logout ps.print("bye" + " LOGOUT"); ps.println('\r'); //ps.print('\n'); try { out.println(dis.readLine()); out.println(dis.readLine()); } catch(Exception x) {} } //bye() // +=================+ // | Folder Commands | // +=================+ /** list the folders in the account, in the form of an array. * * pre: we are currently logged in to an imap server. * * returns: an array of strings, which are the folder names of the * account currently logged in to teh server. */ public String listFolders() { count = count + 1; SimpleOutput out = new SimpleOutput(); // list the folders ps.print("a" + count + " list \"\" *"); ps.println('\r'); //ps.print('\n'); try { // set the mark at the beggining of the first line dis.mark(10); } // try catch (Exception ex7) {} String list; list = null; boolean test; test = false; try { // while the first character is not "a" (97 ascii code) while (!test) { if (dis.read() == 97) { test = true; } // if else { // reset to the beggining of the line dis.reset(); // add the next line to the list list = list + '\n' + " " + dis.readLine(); try { // set the mark to the beggining of the next line dis.mark(10); } // try catch (Exception ex2) {} } // else } // while } // try catch (Exception ex4) {} try { dis.reset(); } // try catch (Exception ex6) {} try { dis.readLine(); } // try catch (Exception exc1) {} return list; } // listFolders() /** delete a specific folder and its contenets. throws * FolderException if the given folder does not exist. * * pre: we are currently logged in to an imap server. */ public void deleteFolder(String folderName) throws FolderException { count = count + 1; String store; SimpleOutput out = new SimpleOutput(); // delete the folder of folderName ps.print("a" + count + " delete " + folderName); ps.println('\r'); //ps.print('\n'); try { this.clear(); store = dis.readLine(); out.println(store); // check if delete succeeded if (!(store.equals("a" + count + " OK DELETE completed."))) { throw new FolderException("badfolder"); } // if folder does not exist } catch (Exception e6) {throw new FolderException();} } // deleteFolder(String) /** * create an empty folder with the specified name. Throws folderException * if a folder of that name cannot be created. * * pre: we are currently logged in to an imap server. */ public void createFolder(String folderName) throws FolderException { count = count + 1; String store; SimpleOutput out = new SimpleOutput(); // create the folder ps.print("a" + count + " create " + folderName); ps.println('\r'); //ps.print('\n'); try { this.clear(); store = dis.readLine(); out.println(store); // chec to see if it worked if (!(store.equals("a" + count + " OK CREATE completed."))) { throw new FolderException("badfolder"); } // if folder does not exist } // try catch (Exception e7) {throw new FolderException();} } // createFolder(String /** * get the contents of the current folder, returns an array of headers, * pre: we are currently logged into an IMAP server. * returns an array of message headers * * @exception never, this method should not fail */ public String[] getFolderContents() throws Exception { SimpleOutput out = new SimpleOutput(); String[] headers = new String[numMessages + 1]; count = count + 1; // get the message headers ps.print("a" + count + " fetch " + "1:" + numMessages + " body[header]"); ps.println('\r'); //ps.print('\n'); int store; store = 1; // while there are still messages while (store <= numMessages) { this.setHeader(store, headers); store = store + 1; } // while try { this.clear(); dis.readLine(); } // try catch (Exception x5) {} // return the array of message headers return headers; } //getFolderContents(String) /** * renames a folder, throws FolderException when a folder cannot be created * with that name. * * Pre: we are currently logged into an IMAP server. */ public void renameFolder(String folderName, String newFolderName) throws FolderException { SimpleOutput out = new SimpleOutput(); count = count + 1; // rename the folder ps.print("a" + count + " rename " + folderName + " " + newFolderName); ps.println('\r'); //ps.print('\n'); try { this.clear(); String store; store = dis.readLine(); out.println(store); // check to see if it worked if (!(store.equals("a" + count + " OK RENAME completed."))) { throw new FolderException("badfolder"); } // if folder can not be created } // try catch (Exception e9) {throw new FolderException();} } // renameFolder(String, String) /** * Sets the active folder. throws FolderException that folder * doesn't exist, * or is otherwise unavaliable. * * Pre: we are currently logged in to an IMAP server. */ public void setFolder(String folderName) throws FolderException, Exception { count = count + 1; SimpleOutput out = new SimpleOutput(); // set the folder ps.print("a" + count + " select " + folderName); ps.println('\r'); //ps.print('\n'); // set the mark to the beggining of the first line dis.mark(10); // check to see if the value is a * if (dis.read() == 42) { int store; // clear the next character dis.read(); // store the number of messages store = dis.read(); int n; n = dis.read(); // if the next value is a space if (n == 32) { // set the number of messages to the value numMessages = (store - 48); // reset the line to the beggining dis.reset(); } //if else { // whule n is not a space while (n != 32) { // multiple the value by 10 and add the next character store = ((store-48)*10 + (n-48)); // set n to the next value n = dis.read(); } //while numMessages = store; dis.reset(); } //else } // if else { // otherwise, reset the line dis.reset(); // check to see if the command failed this.clear(); String line; line = dis.readLine(); out.println(line); if (!(line.equals("a" + count + " OK [READ-WRITE] SELECT completed."))) { out.println("bad"); throw new FolderException("badfolder"); } // if folder does not exist }// else try { this.clear(); out.println(dis.readLine()); } // try catch (Exception exs) {} count = count + 1; ps.print("a" + count + " expunge"); ps.println('\r'); //ps.print('\n'); try { this.clear(); out.println(dis.readLine()); } // try catch (Exception exs2) {} } // setFolder(String) /** Message Commands */ /** Deletes a message, throws MessageException if the message in question * doesn't exist. * * Pre: we're logged in to an IMAP server, and have a valid folder set as * active. */ public void deleteMessage(int messageID) throws MessageException { SimpleOutput out = new SimpleOutput(); count = count + 1; ps.print("a" + count + " store " + messageID + " +flags (\\Deleted)"); ps.println('\r'); //ps.print('\n'); try { this.clear(); String store; store = dis.readLine(); out.println(store); if (!(store.equals("a" + count + " OK STORE completed."))) { throw new MessageException("badmessage"); } // if invalid message name } // try catch (Exception e11) {throw new MessageException();} count = count + 1; ps.print("a" + count + " expunge"); ps.println('\r'); //ps.print('\n'); try { this.clear(); dis.readLine(); }// try catch (Exception ex) {} } // deleteMessage(String) /** Get the contents of a message, returns a MailMessage, throws * MessageException when teh message in question doesn't exist, or is * otherwise unabaliable. * pre: we are logged in to an IMAP server. */ public String getMessage(int messageID, String[] headers) throws MessageException//, java.io.IOException { SimpleOutput out = new SimpleOutput(); count = count + 1; ps.print("a" + count + " fetch " + messageID + " body[text]"); ps.println('\r'); //ps.print('\n'); try { dis.mark(10); } // try catch (Exception ex3) {} //try { String body; body = null; //body = dis.readLine(); boolean test; test = false; try { while (!test) { if (dis.read() == 97) { int temp; temp = dis.read(); if ((temp >= 49) && (temp <= 57)) { test = true; } // if } // if else { dis.reset(); body = body + '\n' + " " + dis.readLine(); try { dis.mark(10); } // try catch (Exception ex2) {} } // else } // while } // try catch (Exception ex4) {} try { dis.reset(); } // try catch (Exception rf) {} try { dis.readLine(); } //try catch (Exception ex6) {} int eoj = body.indexOf("{"); body = body.substring(eoj); int eol = body.indexOf('\n'); body = body.substring(eol); return body; } // getMessage(int) /** * copy a message to a specified folder * * @exception when an invalid folder or message is given */ public void copyMessage(int messageID, String folder) throws Exception { SimpleOutput out = new SimpleOutput(); count = count + 1; ps.print("a" + count + " copy " + messageID + " " + folder); ps.println('\r'); //ps.print('\n'); try { this.clear(); String store; store = dis.readLine(); out.println(store); if (!(store.equals("OK COPY complete."))) { throw new Exception("badmessage"); } // if invalid message name } // try catch (Exception e11) {throw new Exception();} /*try { this.clear(); }// try catch (Exception ex) {} */ } // deleteMessage(String) /** * ignore all responses that are not responses to the current command * @exception when mark, or readLine fails */ public void clear() throws Exception { SimpleOutput out = new SimpleOutput(); dis.mark(10); int count; count = 0; int n; n = dis.read(); while (n != 97) { dis.reset(); dis.readLine(); dis.mark(10); n = dis.read(); count = count + 1; if (count >= 100) {throw new Exception("bad"); {} } } // while dis.reset(); //out.println(dis.readLine()); } // clear() /** * seach through a header for a specific field, and set that to the * String array */ public void setHeader(int num, String[] headers) throws Exception { SimpleOutput out = new SimpleOutput(); dis.mark(10); int count; count = 0; int n; n = dis.read(); headers[num] = dis.readLine(); //out.println("searching for " + field + " message " + num); while (n != 41) { dis.reset(); headers[num] = headers[num] + '\n' + dis.readLine(); dis.mark(10); n = dis.read(); //count = count + 1; //out.println("count =" + count); if (count >= 100) {throw new Exception("bad"); {} } } // while } // setHeader() /* public MessageHeader parseHeader(String oldHeader) { MessageHeader newHeader = new MessageHeader(); int eol = oldHeader.indexOf('\n'); int leol = oldHeader.lastIndexOf('\n'); String header = oldHeader; int colon; String line; while (eol != leol) { line = header.substring(0,eol); header = header.substring(eol); colon = line.indexOf(":"); newHeader.setField(line.substring(0,colon), line.substring(colon)); } // while line = header.substring(0,leol); colon = line.indexOf(":"); newHeader.setField(line.substring(0,colon), line.substring(colon)); return newHeader; } // parseHeader */ }//Mailbox