0% found this document useful (0 votes)
8 views

SWconstruction 02

software construction

Uploaded by

safa noor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

SWconstruction 02

software construction

Uploaded by

safa noor
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

COMSATS University Islamabad,

Abbottabad Campus
Department of Computer Science
FALL 2024

Assignment # 02
Submitted to: Ma’am Hifza Ali

Submitted by:

 Group Members:
Rijaab Ali (SP22-BSE-156)
Safa Noor (SP22-BSE-089)
Samra Rehman (SP22-BSE-092)
Qurat Ul Ain (SP22-BSE-084)
Assignment 2
 Task
Construct an email system using any programming language of your choice. The system
should exhibit these features of concurrent programming like threads, non-blocking
threads, atomic operations, event driven programming etc.

Solution:
 Server Process: Acts as the mail server, consuming emails from the queue to send them to
recipients.
 Client Processes: Act as users of the system, performing operations like drafting, sending,
and deleting emails.

This code will illustrate:

1. Producer-Consumer Pattern: Clients (producers) place emails in an outgoing queue,


and the server (consumer) sends them.
2. Non-Blocking Behavior: The server operates asynchronously, processing emails as they
arrive.
3. Error Handling: If sending fails, an error is displayed.

For our email system:

 We'll use threads to handle tasks like sending emails without blocking the main
program.
 We'll use a queue to manage email drafts and send emails in the background

Code:

import threading
import time
from queue import Queue, Empty

# Shared Email Queue


email_queue = Queue()
sent_emails = [] # List to store sent emails

# Simple Email Data Structure


class Email:
def __init__(self, recipient, subject, body):
self.recipient = recipient
self.subject = subject
self.body = body

def __repr__(self):
return f"Email(to: {self.recipient}, subject: {self.subject})"

# Server Process (Consumer)


def email_server():
print("Email server started.")
while True:
try:
# Try to get an email from the queue with a longer timeout
email = email_queue.get(timeout=5)
print(f"Processing {email}...")
time.sleep(1) # Short sleep simulating sending process
sent_emails.append(email) # Store sent email
print(f"Email sent to {email.recipient}")
email_queue.task_done() # Mark this task as done
except Empty:
print("No emails to process, server is idle...")
time.sleep(1) # Check for new emails after a short wait
except Exception as e:
print(f"Failed to send email: {e}")

# Client Functions
def send_email(recipient, subject, body):
email = Email(recipient, subject, body)
email_queue.put(email)
print(f"Email queued for sending: {email}")

def create_draft(recipient, subject, body):


draft = Email(recipient, subject, body)
drafts.append(draft)
print(f"Draft created: {draft}")

def delete_draft(recipient):
global drafts
# Find draft by recipient and remove it
drafts = [draft for draft in drafts if draft.recipient != recipient]
print(f"Drafts after deletion for recipient '{recipient}':
{[str(draft) for draft in drafts]}")

def view_contacts():
print("Contacts:")
for contact in contacts:
print(f"- {contact}")

def view_sent_emails():
print("Sent Emails:")
for email in sent_emails:
print(email)

# Initialize Contacts and Drafts


contacts = ["[email protected]", "[email protected]",
"[email protected]"]
drafts = []

# Main Simulation
if __name__ == "__main__":
# Start email server thread
server_thread = threading.Thread(target=email_server, daemon=True)
server_thread.start()

while True:
print("\nMenu:")
print("1. View Contacts")
print("2. Create Draft")
print("3. Delete Draft")
print("4. Send Email")
print("5. View Sent Emails")
print("6. Exit")

choice = input("Enter your choice: ")

if choice == '1':
view_contacts()
elif choice == '2':
recipient = input("Enter recipient: ")
subject = input("Enter subject: ")
body = input("Enter body: ")
create_draft(recipient, subject, body)
elif choice == '3':
recipient = input("Enter recipient of draft to delete: ")
delete_draft(recipient)
elif choice == '4':
recipient = input("Enter recipient: ")
subject = input("Enter subject: ")
body = input("Enter body: ")
send_email(recipient, subject, body)
elif choice == '5':
view_sent_emails()
elif choice == '6':
print("Exiting...")
break
else:
print("Invalid choice, please try again.")

# Ensure all emails are processed before exiting


email_queue.join()
print("All emails have been processed.")

Code Explanation:

Imports

 import threading: This line brings in the threading module, which allows the program to
run multiple tasks concurrently (like sending emails in the background).
 import time: This imports the time module, used for pausing the program's execution for
a specific duration (simulating email sending time).
 from queue import Queue, Empty:
o Queue is a thread-safe queue that allows multiple threads to safely add or remove
items.
o Empty is an exception that is raised when trying to get an item from an empty
queue.

Shared Data Structures

 email_queue = Queue(): This initializes a queue to hold emails that need to be sent.
 sent_emails = []: This creates an empty list called sent_emails that will store emails after
they've been "sent."
 class Email:: This defines a simple class to represent an email.

o __init__ Method: This method is the constructor, which is called when a new
Email object is created. It initializes the recipient, subject, and body of the email.
o __repr__ Method: This method returns a string representation of the Email
object, which helps when printing emails for debugging.

Email Server Process

def email_server():This defines a function called email_server that simulates the behavior of an
email server.

o print("Email server started."): Notifies that the email server has started.
o while True:: This creates an infinite loop that keeps the server running.
o try:: Tries to execute the block of code that follows.
 email = email_queue.get(timeout=5): Attempts to retrieve an email from
the queue. If the queue is empty for 5 seconds, it raises an Empty
exception.
 print(f"Processing {email}..."): Prints the email currently being
processed.
 time.sleep(1): Simulates the time taken to send an email.
 sent_emails.append(email): Adds the sent email to the sent_emails list.
 email_queue.task_done(): Marks this email as processed, signaling that
it’s done.
o except Empty: If the queue is empty:
 print("No emails to process, server is idle..."): Notifies that there are no
emails to process.
 time.sleep(1): Waits for a short time before checking the queue again.
o except Exception as e: Catches any other exceptions and prints an error message.

Client Functions

def send_email(recipient, subject, body):This function creates an email and adds it to the
queue.

o email = Email(recipient, subject, body): Creates a new Email object.


o email_queue.put(email): Adds the email to the queue for processing.

def create_draft(recipient, subject, body): This function creates a draft email.

o drafts.append(draft): Adds the draft email to a list (which should be initialized


beforehand).
o print(f"Draft created: {draft}"): Confirms that a draft has been created.

def delete_draft(recipient): This function deletes a draft by recipient email.

o drafts = [draft for draft in drafts if draft.recipient != recipient]: Creates a new


list that excludes the draft with the specified recipient.
o print(f"Drafts after deletion for recipient '{recipient}': {[str(draft) for draft
in drafts]}"): Shows the remaining drafts.

def view_contacts(): This function prints out a list of contacts.

o for contact in contacts:: Iterates over the list of contacts and prints each one.

def view_sent_emails(): This function prints all sent emails.

o for email in sent_emails:: Iterates over the list of sent emails and prints each one.

Initialization
contacts = [...]: Initializes a list of email contacts.

drafts = []: Initializes an empty list to hold drafts.

Main Simulation

o if __name__ == "__main__": Ensures that the code block runs only when the script is
executed directly (not imported).
o server_thread = threading.Thread(target=email_server, daemon=True): Creates a
new thread to run the email_server function. The daemon=True means this thread will
automatically close when the main program exits.
o server_thread.start(): Starts the email server thread.
o while True:Begins an infinite loop to display a menu and handle user input.
o email_queue.join(): Waits until all items in the queue have been processed before
exiting.
o print("All emails have been processed."): Confirms that all emails are done processing.

Output:

You might also like