CS 51Homework Laboratory # 10
Spam, Spam, Spam
Objective: To gain experience with Strings.
What is spam? Before the mid-90s, Spam was a canned "meat" product,
which, I think, actually still exists under that name. Others are
fondly reminded of a Monty Python
skit involving a
restaurant that served spam in all of its dishes. Of course, these
days, the term "spam" means just one thing - unwanted mail often
having to do with enlarging body parts that you might or might not
have! There is lots more information available online about the
history of the term
"spam".
Hormel (the makers of Spam) have an
amusing site to give spam back its "good" reputation, including the
slogan (Spam. So good...it's gone.)
This week you will build a program that should give you insights into
how you might add a spam filter capability to a mail program. Our
spam filter is rather simple. The user provides a list of words.
The program then searches the "from" and "subject" headers of all
your mail messages and divides your mail into two lists. One list
contains words in the filter, the other does not.
The SpamFilter program is shown below:
In this program, the user selects the machine to read mail from, then
enters their username and password. The program connects to the mail
server and downloads the headers of all the messages. Initially, all
the mail is considered good mail (not spam).
The user can then add filter words. The filter words appear in the
text area in the top right after they are entered. When the user adds
a filter word, it appears in the list, but also the mail is scanned
for occurrences of the filter word. Messages with those word in their
headers are removed from the good mail list and moved to the spam
list.
The JComboBox at the bottom of the screen allows the user to
switch between viewing the good mail or the spam.
You can use this program to connect to your actual mailbox and filter
your own mail by entering your mail server name, username and password
into the user interface. I provide the code to actually communicate
with a mail server. You do not need to worry about errors in your
program causing problems with your real mailbox, though, as there is
nothing in your program that modifies your mailbox in any way.
If you don't want to use your actual mailbox, I have set up temporary
mailboxes for you to use on the mail server imap.dci.pomona.edu.
You would connect with the same username and password that you use to
connect to your Pomona e-mail account. Of course, these mailboxes are
probably currently empty. So, you will need to send yourself a few
short pieces of mail to test out your program, using an address of the
form abc02009@cs.pomona.edu for example.
As usual, you should bring a copy of your program design to be graded
at the beginning of the lab period. The only class you will be
writing is SpamFilter, as I will provide the other two
classes.
I provide a MailConnection class that manages the
communication with a mail server. I also provide a simple
Mail class that you can use to store and retrieve a
from header and a subject header. It provides the
following:
- public Mail (String from, String subject)
-
Constructs a mail object with just a from header and a
subject header.
- public String getFrom()
- Returns the from header
that was passed in on construction.
- public String getSubject()
- Returns the subject
header that was passed in on construction.
The MailConnection class is a bit more interesting.
Here are descriptions of the
constructor and methods you will need to use:
- public MailConnection (String host, String
userName, char[] password)
- To talk to your mail server, you must
first construct a MailConnection object. You will pass
in the name of your mail server, something like
"imap.dci.pomona.edu", your login id, and your password. Notice
that the password parameter is a character array rather than a
String. This is not really a problem, because the GUI component
that the user types their password into (a
JPasswordField) returns a character array, rather than a
String, so you will just pass the contents of the password field
on to the MailConnection constructor.
When you construct a MailConnection it attempts to
connect to the mail server. There are a number of reasons why it
might fail. For example, the user might mistype his/her login id
or password or the mail server might not be running for some
reason. If any of these failures occur, a dialog box will popup
to inform the user. Your program must also be aware that the
connection failed because it will not be possible to look at the
mail if there is no connection. For that reason, I provide the
following method.
- public boolean isConnected()
- Returns true if the
program currently has a connection to the mail server.
- public void disconnect()
- Closes the connection to
the mail server. This does nothing if there is no active
connection.
- public int getNumMsgs()
- Returns the number of
messages in the mailbox you are connected to. This returns 0 if
there is no active connection.
- public String header (int msg)
- Returns the
headers of a mail message identified by the number passed in.
Unlike Java, mailboxes number messages beginning with 1 and going
up to the number of messages contained in the mailbox.
The mail headers are returned in one long string, such as:
From BJP04747@pomona.edu Fri Oct 14 15:05:16 2005
Return-Path: <BJP04747@pomona.edu>
X-Original-To: kim@cs.pomona.edu
Delivered-To: kim@cs.pomona.edu
Received: from psmtp.com (exprod7og5.obsmtp.com [64.18.2.125])
by suntop.dci.pomona.edu (Postfix) with SMTP id E51A11B9671
for <kim@cs.pomona.edu>; Fri, 14 Oct 2005 15:05:15 -0700 (PDT)
Received: from source ([134.173.71.128]) by exprod7ob5.obsmtp.com ([64.18.6.12])
with SMTP;
Fri, 14 Oct 2005 15:05:10 PDT
X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0
Content-class: urn:content-classes:message
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----_=_NextPart_001_01C5D10B.189304F8"
Subject: Spreadsheet for Computer Sci interest
Date: Fri, 14 Oct 2005 15:03:23 -0700
Message-ID: <C96BA1D796DA1C4E9E4B0D73686CB6D1011F8BA6@EVSFACULTYSTAFF.campus.pom
ona.edu>
X-MS-Has-Attach: yes
X-MS-TNEF-Correlator:
Thread-Topic: Spreadsheet for Computer Sci interest
Thread-Index: AcXRCxh32gY7hsS/SImAXSPXzmfp/A==
From: "Bruce Poch" <BJP04747@pomona.edu>
To: "Kim Bruce" <kim@cs.pomona.edu>
X-Spam-Checker-Version: SpamAssassin 3.0.3 (2005-04-27) on
suntop.dci.pomona.edu
X-Spam-Level:
X-Spam-Status: No, score=0.8 required=2.5 tests=AWL,FORGED_RCVD_HELO,
FROM_ENDS_IN_NUMS,HTML_50_60,HTML_MESSAGE,HTML_TEXT_AFTER_BODY,
HTML_TEXT_AFTER_HTML autolearn=disabled version=3.0.3
X-Sanitizer: This message has been sanitized!
X-Sanitizer-URL: http://mailtools.anomy.net/
X-Sanitizer-Rev: $Id: Sanitizer.pm,v 1.90 2005/01/04 20:30:13 bre Exp $
Status: RO
X-Status:
X-Keywords:
X-UID: 1970
Your spam filter will look at only the "From" and "Subject"
headers. Part of your job, described below, is to extract just
those headers from the long header list that header
returns.
header returns an empty string if it is called when there
is no connection.
Your job is to create the SpamFilter class that interacts
with the MailConnection class to search the "From" and
"Subject" headers for keywords indicating the message is spam. I
will provide the GUI for the SpamFilter class. The GUI
components that you will need to interact with are:
- JTextArea mailArea
- This is the main text area where the
user's good mail headers or spam headers are displayed.
- JComboBox goodOrSpam
- This is the menu at the bottom of the
screen that allows the user to control whether mailArea
displays the headers from good mail or from spam. When the user
makes a selection from this menu, what is displayed should change
if the user's mail has already been downloaded. If no mail has
been downloaded, nothing should happen.
- JTextField filterField
- This is the text field where the
user enters a filter to be added to or removed from the list of
filters.
- JTextArea filterArea
- This is the text area showing all the
terms actively used as filters. Each filter the user adds should
be displayed on a separate line within this text area.
- JButton addFilterButton
- This is the button labelled "Add
to filter". When the user clicks this button, the entry in
filterField should be added to filterArea. The
filterField should be cleared. If the user's mail has
already been downloaded, it should be refiltered and
mailArea should be updated to show the results of the
filtering.
- JButton removeFilterButton
- This is the button labelled
"Remove from filter". When the user clicks this button, the
entry in filterField should be removed from
filterArea. The filterField should be cleared.
If the user's mail has already been downloaded, it should be
refiltered and mailArea should be updated to show the
results of the filtering. If the entry in the text field does not
exist in the filters, nothing should happen.
- JComboBox servers
- This is the menu where the user selects
the mail server to connect to. Note that the user can type in the
name of the server to connect to a server not in the original
menu.
- JTextField user
- This is the text field where the user
types in his/her name to connect to a mailbox.
- JPasswordField pass
- This is where the user types in
his/her password. A JPasswordField is very similar to a
JTextField except that what the user types is not
displayed on the screen. Also, you will use the
getPassword() method to find out what the user typed in
this field, rather than getText().
- JButton connectButton
- This is the button labelled "Get
mail". When the user clicks this button, you should create a new
mail connection using the information in servers,
user, and pass. You should then download
headers from all of the user's mail and save just the "From" and
"Subject" headers. Then close the connection to the mail
server. Finally, filter the saved mail headers into good mail or
spam using the current filters. Then, display good mail or spam
depending on the setting of the goodOrSpam menu.
You must provide:
- The listening methods to react to the user clicking on the
"Get mail", "Add to filter", and "Remove from filter"
buttons. In addition, you must have a listener for the good mail
vs. spam combo box to control what is displayed in the main text
area.
- To avoid repeatedly going back to the mail server (a slow
operation), you should save all the "From" and "Subject"
headers in an array that contains all the user's headers (a
Mail[] array) and that can be repeatedly walked to do the
filtering.
- Besides the array to hold all mail, you will also need two
other arrays. One will hold only the good mail, the other will
hold only the spam.
- You will need another array to hold the list of filter
terms.
- You will need to be able to extract just the "From" and
"Subject" headers from the long string that header
returns. As shown earlier, the String that header
returns actually contains multiple headers with a newline between
each. To find just one header, you will need to find a string
that begins with a newline character (\n) followed by
"From:" or "Subject:" and ending at the next newline
character. When you look for these strings, you should use a
case-sensitive comparison.
- You will need to be able to determine if a header is spam.
You should use String methods to search the header for the
presence of any String in the list of filters. You should use a
case-insensitive comparison for your spam comparisons.
- You may find it useful to introduce other private methods
to keep your code simple and to prevent repeating code in several
places. (Avoid reuse by copy-and-paste!)
I suggest that you approach this problem in the following order:
- First, make sure that you can establish a connection with a
mail server. When the user clicks the "Get mail" button, try to
create a connection. When the MailConnection constructor
returns, call the MailConnection isConnected method to
see if you succeeded. Use System.out.println to print
whether you succeeded or not. Then call disconnect to
close the connection.
- Next, use the methods provided by MailConnection
to download the headers. Extract the "From" and "Subject"
headers and save them in the array containing all the user's mail.
Display the contents of this array in mailArea.
- Now, work on adding filters to the list of filters and
removing filters from the list. At first, just be sure that the
filter list gets updated correctly. Don't bother with actually
filtering the mail.
- Finally, apply the filters to identify good mail and spam.
Make sure you can view both.
- Test your program by modifying your filter list and seeing
that what gets displayed in the mail area is updated
appropriately. Remember that it should not be necessary to
download your mail again when you change your filters.
When your work is complete you should deposit in the appropriate
dropoff folder a copy of the entire SpamFilter folder.
Before you do this, make sure the folder name includes the phrase
"Lab 10" and your name. Also make sure to double check your work
for correctness, organization and style. This assignment is due
Thursday at 11 PM as usual.
Value | Feature |
| Design preparation (3 pts total) |
1 pt. | instance vbles & constants |
2 pts. | methods |
| Syntax Style (5 pts total) |
2 pts. | Descriptive comments |
1 pt. | Good names |
1 pt. | Good use of constants |
1 pt. | Appropriate formatting |
|
| Semantic style (7 pts total) |
1 pt. | General correctness/design/efficiency issues |
1 pt. | conditionals and loops |
1 pt. | Parameters, variables, and scoping |
1 pt. | Good correct use of arrays |
1 pt. | Good use of private methods |
2 pts. | Good use of strings |
|
| Correctness (5 pts total) |
1 pt. | Connecting to mail server and disconnecting |
1 pt. | Downloading mail and saving it |
1 pt. | Extracting from and subject headers |
1 pt. | Adding and removing filters |
1 pt. | Applying filters to downloaded mail |
|
To assist you in creating your design, here is a list of instance
variables in the starter file for SpamFilter corresponding to
the GUI components in the user interface:
// GUI components dealing with the list of filters.
private JButton addFilterButton; // Button to add term to filter
private JButton removeFilterButton; // Button to remove term from filter
private JTextField filterField; // Where user enters new filter or one to remove
private JTextArea filterArea; // Where all filters are displayed
// GUI components dealing with connecting to a mail account.
private JButton connectButton; // button to connect to mail account
private JTextField user; // used to enter account identifer
private JPasswordField pass; // used to enter account password
private JComboBox servers; // pop-up menu to choose mail server
// JComboBox to allow the user to decide whether to show the headers from the
// good mail or the headers from the spam mail.
private JComboBox goodOrSpam;
// Larege text area where headers of good mail or spam are shown.
private JTextArea mailArea;
Computer Science
051
Department of Math & Computer Science
Pomona College