You are on page 1of 12

TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN

KHOA CÔNG NGHỆ THÔNG TIN


------------------------------------------------------------------

Báo cáo Án
SOCKET
Mạng máy tính

Lớp : 22CLC05

Giảng viên lý thuyết: Huỳnh Thị Bảo Trân

Nhóm sinh viên thực hiện: Nguyễn Đăng Nhân - 22127302

Chu Thúy Quỳnh - 22127359

Nguyễn Thị Thùy Uyên - 22127490

HỒ CHÍ MINH, 2023


ĐÁNH GIÁ MỨC ĐỘ HOÀN THÀNH CÔNG VIỆC

STT MSSV Họ và tên Công việc được Mức độ hoàn Ký tên


giao thành
1 22127302 Nguyễn Đăng + Tải được các 100%
Nhân email về mail client
từ mailbox của
Server
+ Xử lý lọc email
+ Làm báo cáo

2 22127359 Chu Thúy + Gửi email với TO 100%


Quỳnh và CC, BCC
+ Gửi được
attached file (dung
lượng <= 3MB)
3 22127490 Nguyễn Thị + Quản lý trạng thái 100%
Thùy Uyên email
+ Xử lý tự động tải
email từ Mailbox
theo thời gian cấu
hình trong config
file
+ Tổ chức file
config

Đã làm được Chưa làm được


1. Gửi được Email với TO ×
và CC:
+ Gửi email đến một hoặc
nhiều địa chỉ người nhận
(TO)
+ Gửi email đến một hoặc
nhièu địa chỉ người nhận
(CC)
2. Gửi được email với ×
BCC
3. Gửi được attached file ×
( dung lượng file <=
3MB):
+ Gửi được file *.txt
+ Gửi được các định dạng
file như: *.docx, *.pdf, *.jpg,
*.zip,…
+ Gửi được nhiều file
đính kèm trong cùng 1 email
+ Có giới hạn dung
lượng file gửi

4. Tải được các email về ×


mail client từ mailbox
của Server:
+ Tải nội dung email
không kèm file
+ Tải nội dung email có
kèm file
+ Tải nội dung email có
kèm file, có lưu file
xuống máy cục bộ của
client

5. Quản lý trạng thái email ×


(đã đọc/ chưa đọc)
6. Xử lý lọc email: ×
+ Lọc email dựa trên địa
chỉ người gửi
+ Lọc email dựa trên
subject
+ Lọc email dựa trên nội
dung
+ Di chuyển email vào
thư mục cụ thể/ Spam
7. Xử lý tự động tải email ×
từ Mailbox theo thời
gian cấu hình trong
config file
8. Tổ chức file config: ×
+ Không tổ chức file
config:
+ Có sử dụng file config
dạng *.txt
+ Có sử dụng file config
dạng file có cấu trúc
(*.xml, *.sql, *.json,...)

9. Báo cáo ×
1. Môi trường lập trình và framwork hỗ trợ
Test mail server được lập trình trên ngôn ngữ Java version 8, hệ điều hành Windows, MAC
và được thực thi trên cùng nền tảng ngôn ngữ và hệ điều hành.
Trong quá trình thực hiện, các module được sử dụng từ ngôn ngữ lập trình Python cung cấp.
Dưới đây là danh sách các module đã sử dụng:
socket: Được sử dụng để tạo và quản lý kết nối mạng giữa test mail server, test mail client.
base64: Cung cấp các hàm để mã hóa dữ liệu nhị phân thành văn bản ASCII và giả mã trở lại
thành dữ liệu nhị phân
datetime: Cho phép làm việc với ngày và giờ
uuid: Cung cấp các hàm để tạo và làm việc với các định danh duy nhất toàn cầu (UUID)
json: Cung cấp các phương thức để làm việc với dữ liệu JSON ( JavaScript Object Notation)
mimetypes: Ánh xạ tên file với các loại MIME ( Multipurpose Internet Mail Extensions).
Hữu ích để xác định loại MIME của một tệp dựa trên phần mở rộng của nó ( ví dụ : *.jpg,
*.html)
BytesParser: Sử dụng để phân tích các tin nhắn email được biểu diễn dưới dạng bytes.
policy: Cung cấp một bộ các lớp
sys: Cho phép tương tác với trình thông báo hệ thống và các tham số dòng lệnh
os: Cung cấp các hàm để tương tác với hệ điều hành
time: Cho phép quản lý thời gian, tính toán khoảng thời gian và tạo độ trễ trong chương trình.

2. Kịch bản giao tiếp của chương trình và hướng dẫn thực thi
2.1. Giao thức trao đổi giữa Client và Mail Server
Giao thức trao đổi giữa Client và Mail Server thường được thực hiện thông qua các giao thức
chung như SMTP (Simple Mail Transfer Protocol) để gửi thư và POP3 (Post Office Protocol
3)
2.1.1 Kết nối
Khởi động test mail server, sau đó nhập thông tin cấu hình cho email bao gồm:
+ Cổng SMTP ( mặc định 3000 )
+ Cổng POP3 ( mặc định 2100 )
Khởi động Mail Client và bắt đầu kết nối tới server với thiết lập file config như hình :

- Mở một socket mới sử dụng


+ socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- Kết nối đến máy chủ SMTP qua cổng đã cấu hình
+ client_socket.connect((mailserver, serverport))
- Nhận thông điệp chào mừng từ máy chủ
+ client_socket.recv(1024).decode()
- Gửi lệnh EHLO để bắt đầu phiên làm việc SMTP
+ client_socket.send((b”EHLO server\r\n”)
- Nhận phản hồi từ máy chủ sau lệnh EHLO
+ client_socket.recv(1024).decode()
- Gửi lệnh MAIL FROM để xác nhận người gửi
+ client_socket.send((“MAIL FROM:<”+ sender + “>\r\n”).encode()
- Nhận phản hồi từ máy chủ sau lệnh MAIL FROM
+ client_socket.recv(1024).decode()
Mail Server và Mail Client:
- Mail Server duy trì kết nối với Mail Client trong một khoảng thời gian quy định
- Nếu trong khoảng thời gian này Mail Client không gửi yêu cầu hoặc tín hiệu ngắt kết nối,
Mail Server có thể quyết định ngắt kết nối và thông báo cho Mail Client về việc này.
- Nếu Mail Server quyết định đóng kết nối, nó có thể gửi tín hiệu đóng kết nối đến Mail
Client và sau đó đóng kết nối.

2.1.2 Cấu trúc và kiểu dữ liệu của thông điệp

Dựa trên các lệnh và phản hồi từ server, ta có thể xây dựng các thông điệp có cấu trúc như
sau:
+ <Start-line>: Dòng lệnh gửi đến server hoặc phản hồi từ server
+ [Headers]: Các tiểu đề liên quan đến email hoặc lệnh
+ <Empty-line>: Dòng trống để phân tách giữa headers và message body (nếu có)
+ [Message Body]: Nội dung chính của email hoặc thông điệp

- Thông điệp được biểu diễn dưới dạng dữ liệu kiểu bytes. Cụ thể, các lớp ‘socket.send’ và
‘socket.recv’ được sử dụng để gửi và nhận dữ liệu qua kết nối socket, và dữ liệu này
được xử lý dưới dạng bytes.

2.1.3. Xử lý thông điệp yêu cầu và phản hồi


1. Gửi Email (SMTP):
 Kết nối đến máy chủ SMTP thông qua socket.
 Gửi lệnh EHLO để bắt đầu phiên giao tiếp SMTP.
 Gửi lệnh MAIL FROM để xác định người gửi.
 Gửi lệnh RCPT TO cho người nhận (TO,CC,BCC).
 Gửi lệnh DATA để bắt đầu nội dung email.
 Gửi header email và nội dung.
 Nếu có đính kèm, gửi từng phần đính kèm với mã hóa base64.
 Kết thúc bằng lệnh QUIT để đóng kết nối.
2. Nhận Email (POP3):
 Kết nối đến máy chủ POP3 thông qua socket.
 Xác thực bằng USER và PASS.
 Gửi lệnh STAT để lấy số lượng email có trong hộp thư.
 Lặp qua từng email:
 Gửi lệnh RETR để nhận nội dung của email.
 Phân tích nội dung để trích xuất thông tin sender và subject.
 Tạo thư mục và lưu trữ nội dung email và đính kèm (nếu có).
 Đánh dấu email đã xử lý.
3. Xử lý thư mục ( đánh dấu đã đọc ):
 Hiển thị danh sách thư mục và chờ người dùng chọn một thư mục.
 Hiển thị nội dung của thư mục đã chọn.
 Đổi tên thư mục để đánh dấu là đã đọc.
4. Tự động tải email:
 Lặp vô hạn để tự động tải email theo khoảng thời gian được cấu hình.
 Gọi hàm tải email và đánh dấu đã xử lý.

3. Phân tích code và hướng dẫn sử dụng tính năng chương trình
3.1. Gửi Email
1. Thiết lập kết nối SMTP
 Lấy thông tin cấu hình SMTP từ file config
 Tạo một socket và kết nối đến máy chủ SMTP thông qua cổng được chỉ định.
2. Gửi lệnh EHLO và MAIL FROM:
 Gửi lệnh EHLO để bắt đầu phiên SMTP và nhận phản hồi từ máy chủ.
 Gửi lệnh MAIL FROM để xác định người gửi (sender) của email.
3. Nhập thông tin người nhận và tiêu đề của email
 Nhập danh sách người nhận(TO), danh sách người nhận ẩn (CC), danh sách người
nhận bí mật (BCC) và tiêu đề từ người dùng
4. Tạo Header email
 Xây dựng phần header của email bao gồm nhiều thông tin như Content-Type,
Message-ID, Date, MIME-Version, User-Agent, Content-Language, To, Cc,
From, Subject, và thông điệp multipart.
5. Gửi lệnh RCPT TO cho tất cả người nhận:
 Sử dụng vòng lặp để gửi lệnh RCPT TO cho từng người nhận (TO,CC,BCC) và
nhận phản hồi từ máy chủ.
6. Bắt đầu nội dung email ( DATA )
 Gửi lệnh DATA để bắt đầu phần nội dung của email và nhận phản hồi.
7. Nhập nội dung email và đính kèm:
 Gọi hàm ‘inputMail(sender)’ để nhập nội dung email và đính kèm (nếu có).
 Xây dựng phần nội dung của email bằng cách kết hợp header và nội dung được
nhập.
 Gửi header và nội dung của email thông qua ‘client_socket’.
8. Gửi đính kèm ( Attachments)
 Nếu có đính kèm, đọc và gửi từng phần của đính kèm dưới dàng các chunk với
mã hóa base64.
9. Kết thúc email và gửi lệnh QUIT
 Gửi dòng kết thúc email và lệnh QUIT để đóng kết nối.
10. Đóng kết nối:
 Đóng socket kết nối với máy chủ SMTP.

3.2. Nhập nội dung email từ người dùng

1. Nhập đường dẫn đính kèm:


 Sử dụng ‘input’ để yêu cầu người dùng nhập đường dẫn các tệp đính kèm.
 Phân tách chuỗi đường dẫn được nhập thành danh sách sử dụng dấu phẩy.
 Nếu không có đường dẫn nào được nhập, danh sách đính kèm sẽ là một danh sách
rỗng.
2. Khởi tạo chuỗi header:
Khởi tạo chuỗi ‘message’ với các thông số header cơ bản.
 ‘Content-Type’: Đặt loại nội dung là văn bản thuần, bảng mã UTF-8, và định
dạng text flowed.
 ‘Content-Transfer-Encoding’: Sử dụng mã hóa 7-bit.
3. Nhập nội dung Email
 Xuất thông báo yêu cầu người dùng nhập nội dung email và kết thúc với dòng
chấm
 Sử dụng vòng lặp vô hạn để lặp qua từng dòng nhập từ người dùng.
 Nếu dòng nhập là dấu chấm duy nhất, thì thoát khỏi vòng lặp
4. Xây dựng chuỗi nội dung email:
 Xây dựng chuỗi ‘message’ bằng cách thêm mỗi dòng nhập vào chuỗi.
 Mỗi dòng nhập được kết thúc bằng dấu xuống dòng (‘\r\n’)
5. Trả về kết quả:
+ Trả về cặp giá trị ‘(message,attachments)’ trong đó:
 ‘message’: Chuỗi chứa nội dung email và các thông số header.
 ‘attachments’: Danh sách đường dẫn đến các tệp đính kèm
3.3. Nhận dữ liệu từ một đối tượng socket cho đến khi nhận diện được boundary

1. Tham số:
 ‘socket_obj’: Đối tượng socket mà dữ liệu sẽ được nhận từ.
 ‘buffer_size’ (mặc định là 4096): Kích thước của mỗi chunk dữ liệu mà hàm sẽ
nhận mỗi lần.
2. Biến cục bộ:
 ‘received_data’: Biến lưu trữ dữ liệu đã nhận từ socket.
3. Vòng Lặp Vô Hạn:
 Hàm sử dụng một vòng lặp vô hạn để liên tục nhận dữ liệu từ socket_obj.
4. Nhận Dữ Liệu Từ Socket:
 Sử dụng ‘socket_obj.recv(buffer_size)’ để nhận một chunk dữ liệu từ socket. Dữ
liệu nhận được được thêm vào biến ‘received_data’.
5. Kiểm Tra Boundary:
 Kiểm tra xem chuỗi ranh giới ('--' + BOUNDARY.encode() + '--') có xuất hiện
trong ‘received_data’ hay không. Nếu ranh giới được tìm thấy, thoát khỏi vòng
lặp.
6. Trả về Dữ Liệu Đã Nhận:
 Sau khi ranh giới được tìm thấy, hàm trả về toàn bộ dữ liệu đã nhận
(‘received_data’)
3.4. Lưu trữ một tệp đính kèm từ dữ liệu nhận được
1. Tham số:
 ‘attachment_data’: Dữ liệu của tệp đính kèm, được truyền dưới dạng dữ liệu mã
hóa base64.
 ‘filename’: Tên của tệp đính kèm.
 ‘attachments_dir’: Đường dẫn đến thư mục nơi tệp đính kèm sẽ được lưu trữ.
2. Kiểm Tra và Tạo Thư Mục:
 ‘os.makedirs(attachments_dir, exist_ok=True)’: Kiểm tra xem thư mục
 ‘attachments_dir’ đã tồn tại hay chưa. Nếu không, nó sẽ tạo mới thư mục này.
3. Giải mã và Lưu Tệp:
 ‘decoded_data = base64.b64decode(attachment_data)’: Giải mã dữ liệu đính kèm
từ base64.
 ‘with open(filepath, 'wb') as file: file.write(decoded_data)’: Mở tệp mới hoặc ghi
đè nếu tệp đã tồn tại, sau đó ghi dữ liệu đã giải mã vào tệp.
4. Xử Lý Ngoại Lệ:
 ‘except IOError as e:’: Nếu có lỗi I/O trong quá trình ghi tệp.
 ‘except Exception as e:’: Bắt mọi ngoại lệ khác và hiển thị thông báo lỗi.
3.5. Tải xuống nội dung email bao gồm cả tệp đính kèm
1. Thiết lập Kết Nối với Máy Chủ POP3:
 Tạo một socket để kết nối với máy chủ POP3, sử dụng địa chỉ và cổng từ cấu
hình.
 Sử dụng tên người dùng và mật khẩu từ cấu hình để xác thực đăng nhập vào tài
khoản POP3.
2. Lấy Thông Tin về Số Lượng Email:
 Gửi lệnh ‘STAT’ để lấy thông tin về số lượng email trong hộp thư và nhận phản
hồi.
3. Lặp Qua Tất Cả Email trong Hộp Thư:
 Sử dụng vòng lặp để xử lý từng email trong hộp thư.
 Kiểm tra xem email đã được tải xuống trước đó (dựa trên UIDL - Unique
Identifier Listing) hay chưa.
4. Tải Xuống Email và Lưu Trữ:
 Nếu email chưa được tải xuống, sử dụng lệnh ‘RETR’ để lấy nội dung của email
và nhận phản hồi.
 Lấy UIDL của email để xác định nó đã được xử lý.
 Tạo thư mục để lưu trữ nội dung và tệp đính kèm của email (nếu có).
5. Tách Nội Dung Email và Đính Kèm:
 Tách nội dung email thành các phần, sử dụng chuỗi biên giới (‘BOUNDARY’)
để phân biệt giữa nội dung và tệp đính kèm.

Xử lý từng phần để trích xuất thông tin về tệp đính kèm như loại, tên và dữ liệu
tệp.
 Gọi hàm ‘download_attachment’ để tải xuống và lưu trữ từng tệp đính kèm.
6. Lưu UIDL Đã Tải Xuống:
 Gọi hàm ‘save_downloaded_uidl’ để lưu UIDL của email đã được xử lý, tránh
việc xử lý lại nếu email được tải xuống một lần nữa.
Lọc

1. Lấy Các Tiêu Chí Lọc:


 Lấy danh sách các bộ lọc từ config, mỗi bộ lọc bao gồm loại (‘type’), từ khóa
(‘keyword’), thư mục đích (‘folder’), và một loại tiêu chí (‘from’, ‘subject’,
hoặc ‘content’).
2. Lặp Qua Các Bộ Lọc:
 Duyệt qua từng bộ lọc để kiểm tra xem nó áp dụng cho loại email cụ thể nào
(‘email_type’).
3. Xử Lý Theo Tiêu Chí Lọc:
 Nếu bộ lọc áp dụng cho loại email được xác định (‘email_type’), thực hiện
các bước sau đối với mỗi từ khóa (‘content_keywords’) trong bộ lọc:
 Xác định thư mục đích (‘target_folder’) dựa trên ‘base_target_folder’, ‘folder’
trong cấu hình, và từ khóa hiện tại.
 Tạo thư mục đích nếu nó chưa tồn tại.
Duyệt qua các thư mục con trong ‘inbox_dir’:
 Nếu thư mục hiện tại chứa các tệp email (email_*.txt), thực hiện các
bước sau đối với từng tệp:
 Mở tệp và đọc nội dung email.
 Xác định người gửi và chủ đề của email bằng hàm
extract_sender_and_subject.
 Nếu email_type là "content" và từ khóa xuất hiện trong nội dung
email, hoặc nếu email_type là "from" và người gửi trùng khớp với từ
khóa, hoặc nếu email_type là "subject" và từ khóa xuất hiện trong
chủ đề, thực hiện các bước sau:
 Kiểm tra xem thư mục đích đã tồn tại hay chưa.
 Nếu thư mục đích chưa tồn tại, sao chép toàn bộ thư mục hiện
tại vào thư mục đích.
 Dừng việc sao chép sau lần sao chép đầu tiên trong mỗi thư
mục.

4. Thông Báo Về Quá Trình Lọc:
 In thông báo về việc email đã được lọc và di chuyển vào thư mục đích.

- Tương tự như lọc với các nội dung spam, nếu các từ khóa “spam” xuất hiện
trong nội dung email thì di chuyển toàn bộ thư mục hiện tại vào thư mục Spam
sau đó dừng việc di chuyển sau lần di chuyển đầu tiên trong mỗi thư mục
3.7. Multithreading
- Ở hai hàm ‘run_email_download_threads(config)’ và ‘start_email_download_threads(config)’

1. ‘run_email_download_threads(config)’:
 Mục đích chung: Tạo một vòng lặp vô hạn để liên tục thực hiện các tác vụ.
 Các bước thực hiện:
 Thực hiện tải xuống nội dung email và tệp đính kèm thông qua hàm
‘download_email_content_with_attachments(config)’.
 Lọc và di chuyển các email vào thư mục Spam nếu chúng khớp với các
tiêu chí được xác định trong cấu hình, sử dụng hàm
‘filter_emails_to_spam(config, "INBOX")’.
 Tạm dừng vòng lặp trong một khoảng thời gian xác định để tránh tình
trạng chạy liên tục mà không có giảm nhẹ.

2. ‘start_email_download_threads(config)’:
 Mục đích chung: Khởi động một luồng mới để thực hiện các tác vụ trong
hàm run_email_download_threads(config).
 Các bước thực hiện:
 Tạo một đối tượng luồng (email_download_thread) với hàm
run_email_download_threads và tham số là config.
 Khởi động luồng vừa tạo để thực hiện các tác vụ trong nền, đồng thời
cho phép chương trình chính tiếp tục thực hiện các công việc khác.

 Hai hàm này cùng nhau giúp tạo ra một quy trình chạy đa luồng để tải xuống và xử lý
email mà không làm đứt quãng chương trình chính. Điều này cải thiện hiệu suất và độ ổn
định của ứng dụng bằng cách cho phép các tác vụ chạy đồng thời.

3.8. Lấy, đọc và lưu UIDL


 1. Kết nối máy chủ POP3, dăng nhập, truy xuất danh sách UIDL để lấy UIDL của một
email cụ thể dựa trên số thứ tự của message number thông qua socket
 2. Đọc danh sách UIDL đã được tải về từ tệp tin ‘Downloaded.txt’ sau đó lưu trữ UIDL
của email đã được tải về vào tệp tin ‘Downloaded.txt’
3.9. Đánh dấu đã đọc
 Đánh dấu bằng cách liệu kê các thư mục con trong thư mục ‘INBOX’, sau đó đánh dấu
đã đọc bằng cách nhập số thứ tự của thư mục.
3.10. Xóa thư mục
 Xóa thư mục và tất cả nội dung bên trong bằng cách kiểm tra xem thư mục có tồn tại hay
không. Nếu tồn tại thì sử dụng ‘shutil.rmtree’ để xóa toàn bộ thư mục và nội dung bên
trong
3.11. Trích xuất thông tin người gửi và chủ đề của một email
 Tìm vị trí của dòng đầu tiên chứa “\r\n” để loại bỏ phần header cảu email sau đó chuyển
đổi nội dung của email thành dạng bytes và sử dụng ‘BytesParser’ để phân tích cú pháp
email, trích xuất thông tin người gửi và chủ đề sau đó trả về thông tin người gửi và chủ
đề.

You might also like