Project 5 — You've Got Mail: The Real Thing
|
![]() |
Objectives
- To gain experience extending and refining class hierarchies
- To gain further experience handling exceptions
- To gain experience updating a design to meet changing requirements
- To build a working, real-world application
Project Overview
In this final phase of the evolving mail program, you will be expanding and adapting the class hierarchy from Project 4. We are providing a set of libraries that will give you the necessary infrastructure support to access actual mail servers over the internet. These libraries have their own models of how a class hierarchy should look for mail access. Your job is to interface your existing system to this model. This will likely require you to modify your own class hierarchy to fit gracefully with the libraries we provide. The better you planned ahead when you were designing the MailRepository class hierarchy, the easier and more logical the update wil be.
This project requires an about-face from the way Projects 2, 3, and 4 were evolving: for that set, we were having you gradually implement your own layers of a multi-layer model, replacing out parts that we provided for you with ones you designed and implemented yourself. However, in the real world, you rarely develop monolithic programs in isolation. Instead, you work in teams, or work on extensions to legacy projects. That involves being able to adapt to other people's packages, classes, and interfaces. That's an important skill to develop.
At the end of this project, you will have a working Java application that you can use to access pretty much any network-based mailbox out there. You should be able to access UMBC mail, Gmail, etc. That's pretty cool.
Project Requirements and Specification
This project mainly involves expanding the stub classes you started designing in Project 4 to anticipate network-based mail stores. We are providing a set of libraries that manages the more technical parts of interacting with an actual Internet mail server machine: the network connection setup and management, the handshaking protocols, resource management, etc. On top of existing Java libraries, we have layered our own interface that goes part-way towards matching the model we have been working from in our class projects. However, this is just a foundation that you need to build further on top of.
At the end of Project 4, you had a working program, comprising the EmailClient class, plus the MailRepository class hierarchy. As part of that, you had to program up a concrete implementation of the file-based extension of the MailRepository class. You also had to have skeletal versions of a NetworkMailRepository. You will now be building that out. The goal is to be to do all the things with NetworkMailRepository that you were able to do with FileMailRepository.
Part 1: Adapting the EmailClient
class
You should not need to do much with the EmailClient class. You
will need to add a new constructor that takes several more arguments,
to set up a connection to a network-based mail server. The new
constructor signature should be:
public EmailClient(String host, String type, int port, String mailbox)This should be in addition to your existing constructor for setting up a file-based mailbox: do not delete that other constructor!
EmailClient should be extended to have logic for alternatively constructing a new FileMailRepository or a NetworkMailRepository or some subclass of that. However, as before, you should then assign the instance to a reference variable declared to be just MailRepository, and the rest should be transparent. Not much else will change.
Part 2: Building out the Network-based MailRepository
subclasses
Specifically, you will then build out your NetworkMailRepository class(es) (or
whatever you called it). Remember: it must implement or override
all the proper methods of MailRepository. I would highly recommend
that you create distinct subclasses for IMAP and POP3 mail repositories,
as they have quite different behaviors. Your job is to design your
subclasses such that EmailClient will not have to know about those
distinctions.
Part 3: Refactoring Your Existing Design
As far as functionality goes, you should not need to do anything with yourFileMailRepository
class; it should work exactly as
it is (assuming it currently works! :-) ) However, you might find that
there are some parts of FileMailRepository, especially the parsing
functionality, that might be very useful for handling POP3 mail
servers, because our libraries are (purposefully) deficient in that
area. So, you might want to abstract out some of the methods, make
them static
, and place them in a utility class like
MailRepositoryUtil, so that the code can be shared by methods in
the FileRepository class and the Pop3MailRepository class.
That's it for Project 5. Good luck!
Provided Classes and Sample Files
We are providing a pair of .jar files. Look back at the instructions
for previous projects to see how to incorporate them into your build
path for Eclipse, or how to unpack them into your working directory for
compiling manually. The archive
proj5Lib.jar contains the classes
NetworkMailbox
and MailMessage
; you will also
need the archive mail.jar which contains
the Java mail library that proj5Lib is built upon.
Here are the declarations for the classes and methods we are providing for Project 5. A couple of important points:
-
All of the directly-provided classes are in package
proj5Lib
-- this is a compact package, so it is safe to just "import proj5Lib.*
". -
Many of the methods in the
NetworkMailbox
andMailMessage
classes potentially throw one of four exception types:UnsupportedOperationException
MailboxException
, with subclasses:MailboxOpenException
MailboxContentException
Here are the summaries of the two main classes you will be using. You will not be calling any constructors of either:
The
This is an abstract class. You will be using the static factory methodNetworkMailbox
class:NetworkMailbox.openNetworkMailbox
which will return an instance of some subclass ofNetworkMailbox
(but you will just declare all of your reference variables to be of typeNetworkMailbox
)package proj5Lib; public abstract class NetworkMailbox { public static String IMAP = "imap"; public static String POP3 = "pop3"; // A factory method for creating an appropriately-subclassed // NetworkMailbox based on the various mailbox parameters. // @param host: the server name (e.g.: "imap.umbc.edu" // @param type: either NetworkMailbox.IMAP, or NetworkMailbox.POP3 // // The rest of the parameters have good defaults, so you can // just plug in 0 or null as appropriate: // @param port: if "0", will guess best port# based on protocol // @param mailbox: the mailbox name to open; if null, will use "INBOX" // @param username: if null, will prompt user at runtime // @param password: if null, will prompt user at runtime // // (There is another version of this that gives finer control // over SSL treatment--ask me if you are having problems with // this with your test mail server.) public static NetworkMailbox openNetworkMailbox(String host, String type, int port, String mailbox, String username, String password) throws MailboxOpenException; // Some simple accessors public String getHostname(); public String getUsername(); // Returns the number of messages in the mailbox; in the case // of IMAP servers, this includes any items that are marked for // eventual deletion. public int getNumMessages() throws MailboxException; // Fetches the n-th mail item from the mailbox. Note that // the index starts from 0, while your interface should present // the user with numbering starting from 1. public MailMessage getMessage(int index) throws MailboxException; // "Deletes" the nth mail item. In the case of POP3 mailboxes, // this deletes immediately (and the later items are thus renumbered), // while for IMAP mailboxes, this just changes the status to "D" // for "Deleted", with these items actually expunged when // commitChanges() is invoked. // Returns the message's previous "isDeleted" status. public boolean deleteMessage(int index) throws MailboxException; // For IMAP mailboxes, actually expunges items marked for deletion. // Does nothing on POP3 mailboxes. // Returns "true" if everything went okay. public boolean commitChanges() throws MailboxException; }
The
Again, this is an abstract class, and you will not be constructing any instances of this class or any subclass. Various method calls to the NetworkMailbox reference above will return objects of typeMailMessage
class:MailMessage
.NB: many of the methods in this class, in addition to the specific exceptions they are explicitly declared to
throw
, also potentially throwUnsupportedOperationException
. This is not a checked exception, so, the compiler will not enforce the "catch-or-declare" rule on this one. However, it is still important that you explicitly deal with it in your code.Another note: The more sharp-eyed among you will probably also notice that
getFromAddr()
from previous projects is now getFromAddrs(); this is because real mail systems allow messages to be broadcast to multiple recipients.package proj5Lib; public abstract class MailMessage { /** * Name: getFromAddr * PreCondition: None. * PostCondition: None. * @return the "From:" header field for the mail item * @throws MailboxException either when the operation is unsupported * by the protocol (e.g., POP3), or there is an internal or server * error. * (Also throws UnsupportedOperationException for POP3 servers.) */ public String getFromAddr() throws MailboxException; /** * Name: getToAddrs * PreCondition: None. * PostCondition: None. * @return the values in the "To: " header field for the mail item; * note that there may be multiple addresses, separated by ',' * @throws MailboxException either when the operation is unsupported * by the protocol (e.g., POP3), or there is an internal or server * error. * (Also throws UnsupportedOperationException for POP3 servers.) */ public String getToAddrs() throws MailboxException; /** * Name: getSentDate * PreCondition: None. * PostCondition: None. * @return the "Date:" header field for the mail item * @throws MailboxException either when the operation is unsupported * by the protocol (e.g., POP3), or there is an internal or server * error. * (Also throws UnsupportedOperationException for POP3 servers.) */ public String getSentDate() throws MailboxException; /** * Name: getSubject * PreCondition: None. * PostCondition: None. * @return the "Subject:" header field for the mail item * @throws MailboxException either when the operation is unsupported * by the protocol (e.g., POP3), or there is an internal or server * error. * (Also throws UnsupportedOperationException for POP3 servers.) */ public String getSubject() throws MailboxException; /** * Name: getStatus * PreCondition: None. * PostCondition: None. * @return the status flags for the mail item * @throws MailboxException when there is an internal or server * error. */ public abstract String getStatus() throws MailboxException; /** * Name: getHeaderText * This method returns the full set of header fields, in "FIELD: value\n" * format. You should be able to apply a general header parser to the * returned value. Some of the header fields will be continued * across multiple lines, just as with your file-based header. * PreCondition: * PostCondition: * @return The full block of header fields, in "FIELD: value\n" format. * @throws MailboxException when there is an internal or server * error. */ public String getHeaderText() throws MailboxException; /** * Name: getBodyText * PreCondition: * PostCondition: * @return The full text of the body of the mail item. Note that * since your programs for Project 5 cannot handle non-text or * multi-part mail messages, this method throws an exception in * those cases, which you should handle appropriately. * @throws MailboxContentException when the body is not simple text * @throws MailboxException when there is an internal or server * error. */ public String getBodyText() throws MailboxException, MailboxContentException; }
You are not to use any classes other than those in the standard Java libraries, and those specifically provided by me, without first checking with me.
Project Hints and Notes
- A sample test application
testClient.java is available here.
You can look at it to see how to use the methods in the provided classes.
- To test your program, first mail yourself some
simple plain-text emails; send it from a variety of different accounts
to make the "From:" field more interesting. MAKE SURE YOU SEND PLAIN
TEXT FILES--do not use HTML-formatted mail, nor send yourself anything
with attachments. (Be careful about signatures, too.)
Then, use your favorite mail client program (e.g.: Thunderbird, or the my.umbc.edu web interface) to go into your UMBC account, create a separate folder ON THE UMBC SERVER (i.e., not local to your own personal computer), and copy these email messages to that folder.
Lastly, copy the invocation of
NetworkMailbox.openNetworkMailbox()
from testClient.java as a template, replacing the string "PROJ5-TEST" with the name of your own folder. That should do it! - As the university changes over to Gmail, some people have reported in the past that they had trouble reliably accessing their mailbox. I will be setting up my own mail server on a spare host I have at home to give you guys a testbed in case your own mail account is one of the finicky ones. Let me know if you are having issues. I have an unusually high-bandwidth connection to my house, so it should not be a problem hosting many of you for testing your programs. (But don't send any mail there that you would want to keep (or keep private :-) ).
Provided Files
Here is a repeat of the downloadable resources refered and linked to in various places above:
-
proj5Lib.jar: contains the classes
NetworkMailbox
andMailMessage
- mail.jar: javax library needed by above
- testClient.java: a sample program that uses proj5Lib.jar
Sample Output
Since yourEmailClient
class will not have changed much,
the output should be much as it was in Project 3.
Extra Credit Option
There are no extra credit options for this project.
Grading
The standard grading rules will apply to this project.
Project Submission
Before submitting your project, be sure to compile and test your code on the GL system. See the Project Compiling section of the course projects page for details on how to run and execute your project on GL.
Important Note:
When I provide any .jar files for the project, unless you
are an expert with JREs and classpaths, the easiest process is to
unpack the class files into your tree. To do this, from the same directory
as above, just type:
jar xf proj3UtilLib.jar
where you would replace "proj3UtilLib.jar" with whatever jar file you
are using.
To submit your project, type the command
Do not submit the provided library or test input file--we have those already :-)
More complete documentation for submit and related commands can be found here.
Remember -- if you make any change to your program, no matter how insignificant it may seem, you should recompile and retest your program before submitting it. Even the smallest typo can cause errors and a reduction in your grade.