Professional Documents
Culture Documents
Báo cáo Án
SOCKET
Mạng máy tính
Lớp : 22CLC05
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 :
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.
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.
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
- 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.