Xây dựng POP3 Server

Một phần của tài liệu Đề tài xây dựng ứng dụng webmail (Trang 114 - 145)

Trình POP3 Server gồm hai phần, phần POPServer chịu trách nhiệm mở socket

và lắng nghe kết nối từ trình khách gởi lên theo cổng 110 (cổng mặc định của giao

thức POP3). Khi nhận được kết nối, POPServer yêu cầu lớp PÔPCnnection phân tích

các lệnh của giao thức POP3 và gởi mail về cho trình khách. Lớp POP3 được cài đặt như sau:

POPServer.java

import java.net.*; import java.util.*;

public class POPServer extends Thread { public Vector connections;

public Boolean stopRequested; protected ServerSocket listenSocket; public POPServer() throws Exception {

int port = 0;

String portString = null;

// Lấy só hiệu cổng từ file cấu hình try {

portString = Server.properties.getProperty("pop.port"); port = Integer.parseInt(portString);

} catch (NumberFormatException e) {

throw new Exception("Invalid 'pop.port' - " + portString); }

// Lắng nghe trên socket sự kết nối từ trình khách listenSocket = new ServerSocket(port);

// Tạo mảng chứa danh sách các kết nối

}

public void removeConnection(POPConnection connection) { }

/**

* Xử lý kết nối

*/

public void run() {

// Lặp vô tận cho đến khi có yêu cầu dừng

stopRequested = new Boolean(false); while (true) {

synchronized (stopRequested) {

if (stopRequested.booleanValue()) break;

}

// Chấp nhận kết nối do trình khách gởi lên try {

Socket s = listenSocket.accept();

//Yêu cầu lớp POPConnection xử lý giao thức phục vụ trình khách POPConnection connection = new POPConnection(s, this);

connection.setDaemon(true); connection.start(); } catch (IOException e) { e.printStackTrace(); break; } } // Đóng kết nối try { listenSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }

Lớp POPConnection.java chịu trách nhiệm chính trong việc xử lý các lệnh của

giao thức POP3. Lớp POPConnection được cài đặt như sau :

POPConnection.java

import java.io.*; import java.net.*; import java.util.*;

public class POPConnection extends Thread { protected static final int ENTER_USER = 0;

protected static final int ENTER_PASSWORD = 1; protected static final int TRANSACTION = 2; protected static final int UPDATE = 3;

protected POPServer server; protected Socket socket; protected BufferedReader in; protected PrintStream out;

protected boolean stopRequested; protected int state;

protected String userName; protected User user;

protected Vector messages = null;

public POPConnection(Socket socket, POPServer server) { super();

this.socket = socket; this.server = server; }

protected void close() { try {

socket.close(); } catch (Exception e) {

System.err.println("Exception trying to close POPConnection socket!"); e.printStackTrace(System.err);

} }

// Đếm số mail có trong hộp thư

protected int countMessages() { if (messages == null)

return 0;

Enumeration enum = messages.elements(); int count = 0;

while (enum.hasMoreElements()) {

Message message = (Message)enum.nextElement(); if (!message.isDeleted()) count++; } return count; } /**

* Lấy nội dung mail dựa vào số thứ tự của mail lưu trong hộp thư

protected Message getMessage(int number) { if (number <= 0 || number > messages.size())

return null;

Message message = (Message)messages.elementAt(number - 1); if (message.isDeleted())

return null; return message; }

protected Message getMessage(String messageNumber) { int number; try { number = Integer.parseInt(messageNumber); } catch (NumberFormatException e) { return null; } return getMessage(number); }

protected long getMessagesSize() { if (messages == null)

return 0;

Enumeration enum = messages.elements(); long size = 0;

while (enum.hasMoreElements()) {

Message message = (Message)enum.nextElement(); if (!message.isDeleted())

size += message.getSize(); }

return size; }

protected void processDELE(StringTokenizer arguments) { if (!arguments.hasMoreTokens()) {

out.println("-ERR must supply message number"); } else {

Message message = getMessage(arguments.nextToken()); if (message == null) {

out.println("-ERR no such message"); } message.setDeleted(true); out.println("+OK"); } } /**

* Xử lý lệnh PASS kiểm tra password

protected void processEnterPassword(String command, StringTokenizer arguments) {

if (command.equalsIgnoreCase("QUIT")) { stopRequested = true;

out.println("+OK Signing off");

} else if (command.equalsIgnoreCase("PASS")) { if (!arguments.hasMoreTokens()) {

out.println("-ERR must supply password"); return;

}

String password = arguments.nextToken(); if (arguments.hasMoreTokens()) {

out.println("-ERR only one argument to PASS, your password"); return;

}

// Kiểm tra quyền đăng nhập

user = Server.storage.login(userName, password); if (user == null) {

out.println("-ERR invalid user or password"); state = ENTER_USER;

} else {

// user đã đăng nhập – trả về danh sách các mail có trong hộp thư

messages = Server.storage.getMessages(user);

state = TRANSACTION; }

} else {

out.println("-ERR Only use PASS or QUIT commands"); }

}

/**

* Xử lý lệnh USER

*/

protected void processEnterUser(String command, StringTokenizer arguments) {

if (command.equalsIgnoreCase("QUIT")) { stopRequested = true;

out.println("+OK Signing off"); return;

}

if (command.equalsIgnoreCase("USER")) { if (!arguments.hasMoreTokens()) {

out.println("-ERR must supply user name"); return;

}

if (arguments.hasMoreTokens()) {

out.println("-ERR only one argument to USER, the user name"); return;

}

state = ENTER_PASSWORD;

out.println("+OK use PASS command to send password"); return;

}

out.println("-ERR Only use USER or QUIT commands"); }

/**

* Xử lý lệnh LIST

*/

protected void processLIST(StringTokenizer arguments) {

if (!arguments.hasMoreTokens()) {

out.println("+OK " + countMessages() + " " + getMessagesSize()); for (int i = 1; i <= messages.size(); i++) {

Message message = getMessage(i); if (message != null) {

out.println(i + " " + message.getSize()); }

}

} else {

String messageNumber = arguments.nextToken(); Message message = getMessage(messageNumber); if (message == null) {

out.println("-ERR no such message"); } else {

out.println("+OK " + messageNumber + " " + message.getSize()); }

} }

/**

* Xử lý lệnh NOOP – Lệnh NOOP của POP3 không làm gì cả, mục đích chỉ để trình khách xem kết nối còn hiệu lực hay không

*/

protected void processNOOP(StringTokenizer arguments) { out.println("+OK");

}

/**

* Xử lý lệnh QUIT

*/

protected void processQUIT(StringTokenizer arguments) { Enumeration enum = messages.elements();

while (enum.hasMoreElements()) {

Message message = (Message)enum.nextElement(); if (message.isDeleted()) {

Server.storage.deleteMessage(message); }

}

out.println("+OK Goodbye, " + user.getName()); stopRequested = true;

} /**

* Xử lý lệnh RETR trả về nội dung mail

*/

protected void processRETR(StringTokenizer arguments) { if (!arguments.hasMoreTokens()) {

out.println("-ERR message number required, RETR 1"); } else {

String messageNumber = arguments.nextToken(); Message message = getMessage(messageNumber); if (message == null) {

out.println("-ERR no such message"); return;

out.println("+OK " + message.getSize() + " octets");

// Đọc dữ liệu mail

StringBuffer buffer = Server.storage.getMessageData(message);

BufferedReader reader = new BufferedReader(new

StringReader(buffer.toString()));

// Đọc từng dòng boolean done = false; try {

while (reader.ready() && (!done)) {

String line = reader.readLine(); if (line == null) break; // Dấu chấm kết thúc if (line.length() >= 1) { if (line.substring(0, 1).equals(".")) line = "." + line; } // Gửi dữ liệu về trình khách out.println(line); }

} catch (IOException e) { System.err.println("POPConnection.processRETR()"); e.printStackTrace(System.err); } try { reader.close(); } catch (IOException e) { System.err.println("POPConnection.processRETR() - reader.close()"); e.printStackTrace(System.err); } out.println("."); } } /** * Xử lý lệnh RSET */

protected void processRSET(StringTokenizer arguments) { Enumeration enum = messages.elements();

while (enum.hasMoreElements()) {

Message message = (Message)enum.nextElement(); if (message.isDeleted())

message.setDeleted(false); }

out.println("+OK"); }

/**

* Xử lý lệnh STAT

*/

protected void processSTAT(StringTokenizer arguments) {

out.println("+OK " + countMessages() + " " + getMessagesSize()); }

/**

* Xử lý lệnh TOP – trả về trình khách các mail header */

protected void processTOP(StringTokenizer arguments) { if (!arguments.hasMoreTokens()) {

out.println("-ERR syntax: TOP <msg> <lines>"); return;

}

String messageNumber = arguments.nextToken();

if (!arguments.hasMoreTokens()) {

out.println("-ERR syntax: TOP <msg> <lines>"); return;

}

int lines = 0; try {

lines = Integer.parseInt(arguments.nextToken()); } catch (NumberFormatException e) {

out.println("-ERR bad number of lines"); return;

}

Message message = getMessage(messageNumber); if (message == null) {

out.println("-ERR no such message"); return;

}

out.println("+OK " + message.getSize() + " octets");

StringBuffer buffer = Server.storage.getMessageData(message);

BufferedReader reader = new BufferedReader(new

StringReader(buffer.toString()));

boolean done = false; boolean inBody = false; int count = 0;

try {

String line = reader.readLine(); if (line == null) break; if (line.length() >= 1) { if (line.substring(0, 1).equals(".")) line = "." + line; } else { inBody = true; } if (inBody) { count++; } out.println(line); } } catch (IOException e) { System.err.println("POPConnection.processTOP()"); e.printStackTrace(System.err); } try { reader.close();

} catch (IOException e) { System.err.println("POPConnection.processTOP() - reader.close()"); e.printStackTrace(System.err); } out.println("."); } /**

* Xử lý các lệnh của giao thức POP3

*/

protected void processTransaction(String command, StringTokenizer

arguments) { if (command.equalsIgnoreCase("STAT")) { processSTAT(arguments); } else if (command.equalsIgnoreCase("LIST")) { processLIST(arguments); } else if (command.equalsIgnoreCase("RETR")) { processRETR(arguments); } else if (command.equalsIgnoreCase("DELE")) { processDELE(arguments); } else if (command.equalsIgnoreCase("NOOP")) { processTOP(arguments); } else if (command.equalsIgnoreCase("TOP")) { processTOP(arguments); } else if (command.equalsIgnoreCase("UIDL")) {

processUIDL(arguments); } else if (command.equalsIgnoreCase("RSET")) { processRSET(arguments); } else if (command.equalsIgnoreCase("QUIT")) { processQUIT(arguments); } else {

out.println("-ERR Unknown command " + command); }

}

protected void processUIDL(StringTokenizer arguments) { if (!arguments.hasMoreTokens()) {

out.println("+OK " + countMessages() + " " + getMessagesSize()); for (int i = 1; i <= messages.size(); i++) {

Message message = getMessage(i); if (message != null) { out.println(i + " " + message.getMessageId()); } } out.println("."); } else {

String messageNumber = arguments.nextToken(); Message message = getMessage(messageNumber); if (message == null) {

out.println("-ERR no such message"); } else {

out.println("+OK " + messageNumber + " " + message.getMessageId()); }

} }

/**

* Nhận kết nối và các lệnh POP3 gửi lên từ trình khách */

public void run() { try {

in = new BufferedReader(new

InputStreamReader(socket.getInputStream()));

out = new PrintStream(socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(System.err); close(); return; } if (server == null) {

System.err.println("SERVER NOT SET!!!"); return;

}

state = ENTER_USER;

out.println("+OK POP3 " + Server.getAddress()); while (!stopRequested) {

try {

String line = in.readLine(); if (line == null)

break;

StringTokenizer tokenizer = new StringTokenizer(line); String command = "";

if (tokenizer.hasMoreTokens())

command = tokenizer.nextToken();

// Xử lý lệnh tuỳ theo trạng thái đăng nhập của user

switch (state) { case ENTER_USER: processEnterUser(command, tokenizer); break; case ENTER_PASSWORD: processEnterPassword(command, tokenizer); break; case TRANSACTION: processTransaction(command, tokenizer);

break; default:

out.println("-ERR invalid state! "); System.err.println("Invalid State in POPConnection.run()");

stopRequested = true; break; } } catch (Exception e) { e.printStackTrace(System.err); stopRequested = true; } } // Đóng kết nối close(); server.removeConnection(this); }

public void setServer(POPServer server) {} }

2.3.CÀI ĐẶT MAILCLIENT

Phần MailClient được thiết kế dưới dạng Web dùng Java Server Page nên được

gọi là một WebMail. Trang Web và quá trình sử dụng mailclient có thể được hình

dung qua sơ đồ và đặc tả đưới đây

HomePage

Đăng Ký Thành Viên

Login Help

Menumail

Inbox AddressBook Option

Add Edit Review

Inf

Change

Password Hình cấu trúc Website

1.Đăng nhập hệ thống :

Lần đầu tiên sử dụng CT để gửi nhận mail, chúng ta phải đăng ký một account

mới cho riêng mình, nghĩa là chúng ta phải có một username password riêng cho mình nhằm phân biệt những người sử dụng email khác nhau và bảo mật thư của từng người.

_ Đăng nhập username và password trước khi vào hệ thống . Nếu là “member”: bạn có thể sử dụng CT gửi /nhận thư . Nếu là “guest”: bạn phải Đăng ký thành viên

2.Đăng ký thành viên :

Cho lần đầu tiên bạn đăng nhập vào hệ thống , ghi các thông tin cá nhân,

username và password của bạn.

3.Các loại Address Book . Điều chỉnh thông tin trong Personal Address Book :

(User có quyền T, X, S addressbook của mình)

Các thông tin về địa chỉ mail của các Client được lưu trữ trong các sổ địa chỉ.

Mỗi người sử dụng mail thường có một sổ địa chỉ cá nhân (Personal Address Book - PAB) của riêng mình và được lưu trữ trong ổ đĩa cục bộ .

Các thông tin cần thiết khi thêm một địa chỉ E-mail vào PAB:

_ E-mail Addressđịa chỉ E-mail chính xác của người cần thêm vào.

Ngoài ra, chúng ta có thể thêm vào những địa chỉ email khác, số phone, mobile và địa chỉ nhà riêng

4.Review Account Information:

_ User xem lai thông tin cá nhân đã đăng nhập và AddressBook của mình. _ Có thể thay đổi Password (changepassword.asp) khi bạn muốn đặt lại một

password mới cho mình.

5.Thay đổi Pass :

_ Old Password:nhập lại pass hiện tại.

_ New password: nhập pass mới. Bạn có thể sử dụng các ký tự chữ, số và cả hệ

thống chấm câu, nhưng không thể sử dụng khoảng trắng.

_ Nhập lại password một lần nữa. Nếu so trùng, việc thay đổi password xem như

6.Kiểm tra thư:

Vùng nội dung các Folder sẽ xuất hiện tiêu đề các thư trong folder đó. Các thư chưa được đọc thường được trình bày khác với thư đã được đọc. Thông thường phần tiêu đềthư gồm các nội dung như sau:

_ From: Tên người gửi, nội dung xuất hiện ở đây không phải là địa chỉ e-mail của người gửi mà là họ tên của người gửi.

_ Subject : Chủ đề của lá thư . Khi gửi thư, ngưòi gửi thường ghi một nội dung

ngắn vào vùng subject để người nhận biết được mục đích tổng quát của lá thư trước

khi quyết định có đọc thư hay không.

_ Date : Ngày giờ nhận thư

_ Size: Kích thước lá thư (thường tính bằng KB)

7.Đọc thư :

Tất cả thư của bạn được liệt kê trong một bảng trong Inbox với mỗi hàng là một thư. Để xem nội dung thư cần click vào vùng tiêu đề của thư. Trong vùng nội dung

INBOX

CheckMail Upload File Compose

Read Reply Delete

DownLoad

Send Error

thư, các thông tin của ngưòi gửi sẽ được thể hiện cùng nội dung lá thư . Các thông tin người gửi bao gồm: tên người gửi, thời điểm gửi, tên người nhận

Muốn đọc email nào, click vào cột Fromtương ứng. Sau khi đọc xong, để đọc thư

khác, click vào Inbox hay click vào nút Back của Internet Explorer.

_ Sau khi đọc xong thư ,Delete nếu muốn xóa thư.

_ Reply nếu muốn trả lời thư

_ Download attach file nếu thư có gửi file kèm theo .

8.Viết email trong WebMail: Chúng ta có hai trường hợp:

 Nếu bạn đang đọc một thư nào đó, bạn muốn trả lời thư đóthì click vào nút

Reply phía trên.

 Nếu bạn muốn gửi thư trực tiếp, click vào nút Compose.

Khi muốn gửi thư cho một người đã có địa chỉ trong một AddressBook, đầu

tiên phải chuẩn bị nội dung thư để gửi. Phần tiêu đề của một thư cần gửi bao gồm các

thông tin sau:

_ To: Địa chỉ email mà bạn muốn gửi tới.

_ Subject: một đoạn text ngắn cho biết mục đích của nội dung thư cần gửi. Đoạn text này giúp cho người đọc thư quyết định có nên xem nội dung của thư hay

không.

_ Attachments gởi kèm tập tin cho nguười nhận.

_ Nội dung soạn trong comment

_ Sau khi soạn thảo nội dung thư xong, nhấn nút Send để thư được cất vào Outbox. Nghĩa là, thư không được truyền đi ngay, do đó chúng ta có thể soạn thảo

Sinh viên thực hiện Nguyễn Xuân Thanh Trang

Khi thư đã đưa vào Outbox, mọi chỉnh sửa tiếp theo thường làm thư không gửi đi được nữa. Trường hợp này cần phải soạn thảo một lá thư khác để gửi đi và xóa bỏ lá thư cũ.

9.Gửi kèm file theo Mail (attach file)

Trong một số trường hợp cần đưa thêm toàn bộ nội dung một tập tin đang có

sẵn trên đĩa cục bộ vào thư để gửi đến ngưòi nhận. Công việc này được gọi là Attach

file vào thư.

Cần chú ý rằng việc attach một tập tin vào mail cần phải được thực hiện đồng bộ

giữa người gửi , người nhận và đường truyền thư.Nếu không có sự đồng bộ, nội dung

của tập tin được attach có người nhận không đọc được. Lý do của việc này là do nội

dung của tập tin được attach sẽ được mã hoá theo UUENCODE hay theo MIME (Multipurpose Internet Mail Extensions).

Thông thường để giảm thời gian truyền thư, các tập tin cần attach vào thư sẽ được nén trước khi thực hiện thao tác attach. Cách nén thông dụng là ZIP.

Các tập tin được gửi kèm có thể lưu thành một tập tin riêng trong điã cục bộ của người sử dụng. Thông thường dung lượng tập tin gửi kèm không nên quá 1MB, nếu

lớn hơn ta cần tách ra gửi nó trong nhiều thư.

10. Download / Upload file

Một số giao diện

Menu chính

TÀI LIỆU THAM KHẢO

 Phân tích, thiết kế và cài đặt hệ thống thông tin quản lý - Hiệu đính: GS. Bạch Hưng Khang  Cơ sở dữ liệu quan hệ - Lê Tấn Vương

 System Administrator for Microsoft SQL Serever 7.0 workbook  Microsoft SQL Server 7.0 Database Implementation Training Kit  Microsoft SQL Server hoạch định và xây dựng cơ sở dữ liệu cao cấp  Allaire JRUN Developer Documentation

 Enterprise JavaBeans – Tom Valesky

 HTML by Example – Todd Stauffer

 Special Edition Using HTML 4 – Jerry Honeycutt  Special Edition Using JavaScript – Mark C. Reynolds  Java by Example – Clayton Walnum

 Lập trình Java thế nào? – Hoàng Ngọc Giao

 Java lập trình mạng – Nguyễn Phương Lan, Hoàng Đức Hải  Các tài liệu về JSP/EJB tại website: http://java.sun.com

Một phần của tài liệu Đề tài xây dựng ứng dụng webmail (Trang 114 - 145)

Tải bản đầy đủ (PDF)

(145 trang)