Project 1: Write a SMTP Client and a SMTP Server in Java [ Due on March 18 ]

In this project you will implement a SMTP client(PART A) and a SMTP server(PART B) that sends and receives mail respectively. Your task is to implement:

PART A:

 1. Modify mySMTPClient as follows:

s
end a file as an email attachment to your SMTP server(that you will develop in PART B). That is, your program will directly connect to your  SMTP server using the correct SMTP commands, transmit an email message that uses the right MIME conventions to contain the file as an attachment. The attached file could be a text file or  an image file or any other type.

Hints
To debug your program
you will use our existing server smtp.bridgew.edu.

PART B:

   2.   Program the SMTP server that ineracts with your SMTP client.

   3.   Save the mail content and attachments in the system.

SIMPLE MAIL TRANSFER PROTOCOL:

Simple Mail Transfer Protocol is the standard e-mail protocol on the Internet and part of the TCP/IP protocol suite. SMTP defines the message format and the message transfer agent (MTA), which stores and forwards the mail. SMTP was originally designed for only plain text (ASCII text), but MIME and other encoding methods enable executable programs and multimedia files to be attached to and transported with the e-mail message.

The SMTP server listens at port 25 for a remote connection. When a remote host connects to the server, the server spawns new thread to serve this client. The parent process continues to listen port 25 for other connections.

Example of interaction between SMTP client and server:

Client(C) initiates the contact with the server(S). After establishing a connection between the sender (the client) and the receiver (the server), 
the following is a valid SMTP session.

     S: 220 hamburger.edu

     C: HELO crepes.fr

     S: 250  Hello crepes.fr, pleased to meet you

     C: MAIL FROM: <alice@crepes.fr>

     S: 250 alice@crepes.fr... Sender ok

     C: RCPT TO: <bob@hamburger.edu>

     S: 250 bob@hamburger.edu ... Recipient ok

     C: DATA

     S: 354 Enter mail, end with "." on a line by itself

     C: Do you like ketchup?

     C: How about pickles?

     C: .

     S: 250 Message accepted for delivery

     C: QUIT

     S: 221 hamburger.edu closing connection

							

Implementation:

The client initiates the negotiation and the server replies to the client's request.

  1. The client first says HELLO to server and server replies.
  2. Client sends the sender address to the server, the server checks whether this is a valid email address.
  3. Client sends the receiver address to the server, the server must check whether the receiver address is a member BSC community, i.e. the domain should be "@bridgew", or otherwise, the server must reject this address.
  4. Client starts to send the mail content, this mail content may contain a MIME style message body and attachment.
  5. Server separates the data into plain-text message body and attachments. Conversion (base64 only) may be needed.
  6. Server creates a new directory and saves the plain-text message into "message.txt".
  7. If attachment is received, the attachment is saved according to the file name specified, or using a dummy name if the MIME header hasn't given a file name.
  8. Client may send another message by repeating step 2 to step 7, or terminate the SMTP connection.

During step 2 to step 8, if the client says HELLO again, the server needs to discard all the previous data (except the saved messages) and restarts from step 2. see RFC 821 and RFC 2821 for details.

To simplify the implementation, the server must understand the following SMTP commands, and answer them with appropriate reply codes, for the details of SMTP interaction, read RFC 821 and RFC 2821:

Command Reply Codes
HELO or EHLO 250 500 501 503
MAIL FROM 250 500 503
RCPT TO 250 500 503
DATA 354 451
QUIT 221

You only need to implement the following message header, if an unrecognized field is detected, treat the previous processed line(s) as message body and process the remaining content as message body:

Message Header Field Processing
From: no
To: no
Subject: yes
Date: yes
Content-Type: yes
Content-Transfer-Encoding: yes
MIME-Version: yes
Message-ID: no
Importance: no
User-Agent: no
field starts with "X" no

A subset of MIME extension over SMTP is needed. This extension reserves the traditional SMTP commands and architecture, but it extends the capability of mail service to include items such as file attachments, multimedia and rich text formatted email. You can look at RFC 2045 & RFC 2046 for details.

For the ease of programming, all file attachments only use Base64 or 7bit(plain-text) encoding. The Base64 class is already provided for you. This links to the Base64 class API homepage. If you want to use another Base64 java class from public domain, you are free to do so.

The MIME extension is capable to encapsulate 8-bit character as message text, for example, you can transfer Chinese characters as message text.

In this project, Java SDK Version 1.4.1 is used. Windows platform or UNIX platform are both accepted.

The Code

The program consists of four classes:

MailServer The Mail Server
MessageSave Save the message body to system
SMTPConnection Thread class for SMTP connection to client
Base64 Base64 encoder for MIME

Click here to download the above files and also mySMTPClient.

You need to complete the code in the SMTPConnection class and MessageSave class so that in the end you will have a program that is capable of receiving  mail and storing  it in the system.  The code for the other two classes are provided.

The places where you need to complete the code have been marked with the comments /* Fill in */. Each of the places requires one or more lines of code.

The MailServer is the frontend of the SMTP server. When a new connection is established, MailServer creates a new object SMTPConnection for handling this client. SMTPConnection is the core part of the server, it negotiates with the client and responds to every request issued by the client. After the client  sends the whole message to the server, SMTPConnection creates another object called MessageSave and puts the message body, sender address and receiver address into it. MessageSave reads every line in the data and determines the message header, message body, MIME header and MIME body. if the message body or MIME body is base64 encoded, MessageSave calls Base64 for decoding. Afterwards, the message body is broken into the message body and attachments,  and saved into a new directory (directory name is generated by MessageSave.)

Hints

To make it easier to debug your program, do not, at first, include the code that opens the socket in  SMTPConnection, but use the following definitions for fromClient and toClient. This way, your program sends the commands to the terminal. Acting as the remote host, you will need to give the correct reply codes. When your program works, add the code to open the socket to the server.

	fromClient = new BufferedReader(new InputStreamReader(System.in));
	toClient = System.out;

The lines for opening and closing the socket, i.e., the lines connection = ... in the constructor and the line connection.close() in function close(), have been commented out by default.

Start by completing the method fetch() and parseHELO() You will need this function in many places.
 

In the function reply(), you should use the function writeBytes() to write the commands to the server. The advantage of using writeBytes() instead of write() is that the former automatically converts the strings to bytes which is what the server expects. Do not forget to terminate each command with the string CRLF.

In MessageSave class, you need to handle the message body received by the server; the simplest way to get it right is to investigate a real SMTP connection, or create a fake SMTP server and use Outlook or Eudora to send an email to your fake server, thus you can grab the raw data for testing. But remember to follow the RFC specification.

You need to identify message header and message body clearly, or otherwise, information may be lost and the whole message may be corrupted.

Don't use a huge file as attachment as the decoding time is long.