关键词 > COMP3234B/ELEC3443B
COMP3234B Computer and Communication Networks
发布时间:2023-04-11
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
COMP3234B Computer and Communication Networks
ELEC3443B Computer Networks
Programming Assignment
Total 12 points
Due date: 17:00 April 12, 2023
Hand in the assignment via the Moodle System.
Overview
In this assignment, you are going to implement an Email client that allows a user to send emails with an attachment to a target group of recipients via the department’s SMTP server – testmail.cs.hku.hk. If an attachment file is included, the program generates a MIME mail message encapsulating the text message and a base64 encoded attachment in the message body. If no attachment file is included, the program simply encapsulates the text message in the message body. The program communicates with a standard SMTP server (testmail.cs.hku.hk port 25) to send the mail to a group of recipients. When the recipient receives and views the email, the email message should be recognized and displayed correctly by any standard email client with the sender, receiver, subject header information, the text message as the mail body, and the decoded file attachment (if included).
Objectives
1. An assessment task related to ILO4 [Implementation] – “be able to demonstrate knowledge in using Socket Interface to design and implement a network application” .
2. A learning activity to support ILO1, ILO2, & ILO4.
3. The goals of this programming assignment are:
• to get solid experience in using Socket functions to implement the SMTP protocol;
• to get a good understanding of sending emails with attachment under the MIME messaging standard.
User Interface Design
Our email client program makes use of the Tkinter module to implement the UI for accepting all user inputs. Tkinter is the standard GUI library for Python. You are not required to write the UI, as the UI framework (Email-UI.py) will be provided to you. It consists of the necessary Tk code to draw the UI.
There are in total 5 inputs and 2 buttons:
• “To:” field – A required input; the user must provide the list of recipients’ email addresses here; each email address is separated by a comma.
• “Cc:” field – An optional input; the user may provide the list of cc recipients’ email addresses and email addresses are separated by commas.
• “Bcc:” field – An optional input; the user may provide the list of bcc recipients’ email addresses and email addresses are separated by commas.
• “Subject:” field – A required input; the user must provide the Subject header of the email.
• “Message” field – A required input; the user must provide the text content of the email message.
• “Attach” button – The user clicks this button for selecting the attachment file.
• “Send” button – The user clicks this button for sending the email to the SMTP server .
The template file Email-UI.py contains the following utility functions for accessing individual input fields:
#This set of functions is for getting the user's inputs def get_TO(): return tofield.get() def get_CC(): return ccfield.get() def get_BCC(): |
return bccfield.get() def get_Subject(): return subjfield.get() def get_Msg(): return SendMsg.get(1.0, END) |
When the user clicks on the “Attach” button, the following utility function will be invoked for selecting a file and returning the opened file object and the filename via two global variables.
#This function calls the file dialog for selecting the attachment file. #If successful, it stores the opened file object to the global #variable fileobj and the filename (without the path) to the global #variable filename. It displays the filename below the Attach button. def do_Select(): global fileobj, filename if fileobj: fileobj.close() fileobj = None filename = '' filepath = filedialog.askopenfilename(parent=win) if (not filepath): return print(filepath) if sys.platform.startswith('win32'): filename = pathlib.PureWindowsPath(filepath).name else: filename = pathlib.PurePosixPath(filepath).name try: |
|
fileobj = open(filepath, 'rb') |
|
except OSError as emsg: print('Error in open the file: %s' fileobj = None filename = '' if (filename): |
% str(emsg)) |
file') |
|
showfile.set(filename) |
|
else: alertbox( 'Cannot open the selected |
When the user clicks the “Send” button, the system will run the do_Send() function, this is the main task you are going to work on for this assignment.
Specification of the Email client program
1. Rename the UI template file Email-UI.py to EmailApp.py
2. Change the two global variables YOUREMAIL and MARKER to store your CS email address and HKU Student number.
# Replace this variable with your CS email address YOUREMAIL = "hello@cs.hku.hk" # Replace this variable with your student number MARKER = '3035999999' |
3. Implement the do_Send() function, which contains the main logic of this email client. It involves three major tasks.
Task 1 – Check all input fields.
1. The user must provide inputs to the “To:”, “Subject:”, and “Message:” fields. If the corresponding field is empty, the program should use the utility function alertbox() to display an alert message to the user. For example, when the “To:” field is empty, the program displays:
Windows
Mac
2. For the “To:”, “Cc:”, and “Bcc:” fields, the program expects the user to enter a list of recipients’ email addresses. The program should parse the list and check whether each address is a valid email address . You can use the utility program echeck() to validate an email address.
#This function checks whether the input is a valid email def echeck(email): regex = ‘^([A-Za-z0-9]+[.\-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a- z]{2,})+’ if(re.fullmatch(regex,email)): return True else: return False |
If the address is not a valid email address, use the alertbox() function to display an alert message to the user. For example, when one of the email addresses in the cc list is not a valid address, the program displays:
Task 2 – Compose the email message
The program should follow the RFC2822 standard (https://datatracker.ietf.org/doc/html/rfc2822) to compose the email message. A message is comprised of characters with values in the range 1 through 127 and interpreted as US-ASCII characters. A message consists of the Headers part and the Body part, which are separated by an empty line. The Headers part has multiple lines of characters; each line consists of a header field, followed by a colon, and followed by a field content. Each line is terminated by CRLF (i.e., “\r\n”). For simplicity, you can assume that the user will not enter any non-ascii characters in the Subject and the Message fields.
1. For the Headers part, it must include the “From:”, “To:”, & “Subject:” headers. If the user has provided input in the “Cc:” field, including the “Cc:” header too. The contents should be the same as appeared in the corresponding input fields.
2. For the Body part, if the user did not select the attachment file, the program just copies the content from the “Message” field to the Body part. Below is a simple example. Again, for simplicity, you can assume that the user will not enter a line with more than 998 characters.
|
From: hello@cs.hku.hk Subject: A demo email To: atctam@cs.hku.hk Cc: tamtca@hku.hk This is the message body. -- AT |
3. If the user has attached a file, the program should follow the RFC2045 standard (https://datatracker.ietf.org/doc/html/rfc2045) to compose the email message.
Reference:https://en.wikipedia.org/wiki/MIME#Multipart_messages
We need to add at least two MIME header lines to the Headers part.
(i) MIME-Version: 1.0
(ii) Content-Type: multipart/mixed; boundary=3035xxxxxx
For this assignment, each student should use his/her student number as the boundary marker. This value should be defined and stored in the global variable MARKER. This marker, which must not occur in any of the parts, is placed between the parts, and at the beginning and end of the body of the message .
Since the program can only send one attachment file, the body of the message would only consist of 2 parts – the first part encapsulates the text content (from the message field), and the other part encapsulates the attached file in base64 encoding. Each part starts with the marker e.g., “ --3035xxxxxx”, and the last part ends with the marker e.g., “ --3035xxxxx --“ . Each part should contain its own header lines, an empty line, and a body.
For the text content part, it is sufficient to just add the following two headers:
(i) Content-Type: text/plain (ii) Content-Transfer-Encoding: 7bit
For the attachment part, we need to add the following three headers:
(i) Content-Type: application/octet-stream (ii) Content-Transfer-Encoding: base64
(iii) Content-Disposition: attachment; filename=name_of_the_file
We can simply use the content-type application/octet-stream to represent any binary file. By using the header Content-Disposition, we tell the email user agent to store the attachment with the provided filename. Once the user has attached a file, the program can retrieve the filename via the global variable filename.
To encode the file content with Base64 encoding, we make use of the built-in python base64.py library for the purpose. One useful function is the base64.encodebytes() function, which encodes the file content and structures the encoded content in lines of no more than 76 characters as defined in RFC2045.
Here is an example that shows the email message with a file attachment.
Compose the email message
|
The message body is structured in MIME format
From: tamtca@hku.hk Subject: A small file To: atctam@cs.hku.hk MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=3035999999 |