java實現POP3郵件客戶端


java實現POP3郵件客戶端

 

完整項目包:http://yunpan.cn/QiVGqacT6uNAj (提取碼:05b4)

第一步:利用socket編程,在客戶端與服務器端之間建立TCP連接,POP3默認端口號為110;

第二步:通過pop3定義的各種命令,用戶可以操作自己的郵箱。

注:

POP3協議中有三種狀態,認正狀態,處理狀態,和更新狀態。 命令的執行可以改變協議的狀態,而對於具體的某命令,它只能在具體的某狀態下使用,這些請參看表1和RFC193。

客戶機與服務器剛與服務器建立連接時,它的狀態為認證狀態;一旦客戶機提供了自己身份並被成功地確認,即由認可狀態轉入處理狀態; 在完成相應的操作后客戶機發出QUIT命令(具體說明見后續內容),則進入更新狀態,更新之后又重返認可狀態;當然在認可狀態下執行QUIT命令,可釋放連接。狀態間的轉移如圖 1所示。

---建立連接---|認可|--認證成功--|處理|--執行QUIT--|更新|        

            |_______ -QUIT結束_________________|

ddddddd

 

常用命令:

命令

參數

使用在何種狀態中

描述

USER

Username

認證

此命令與下面的pass命令若成功,將導致狀態轉換

PASS

Password

認證

此命令若成功,狀態轉化為更新

APOP

Name,Digest

認證

Digest是MD5消息摘要

STAT

None

處理

請求服務器發回關於郵箱的統計資料,如郵件總數和總字節數

UIDL

[Msg#](郵件號,下同)

處理

返回郵件的唯一標識符,POP3會話的每個標識符都將是唯一的

LIST

[Msg#]

處理

返回郵件的唯一標識符,POP3會話的每個標識符都將是唯一的

RETR

[Msg#]

處理

返回由參數標識的郵件的全部文本

DELE

[Msg#]

處理

服務器將由參數標識的郵件標記為刪除,由QUIT命令執行

TOP

[Msg#]

處理

服務器將返回由參數標識的郵件的郵件頭+前n行內容,n必須是正整數

NOOP

None

處理

服務器返回一個肯定的響應,用於測試連接是否成功

QUIT

None

處理、認證

1)        如果服務器處於“處理”狀態,么將進入“更新”狀態以刪除任何標記為刪除的郵件,並重返“認證”狀態。

2)        如果服務器處於“認證”狀態,則結束會話,退出連接

 

代碼:

 

 1 /**
 2  * @author hewenwu  3  * 這個程序實現了基於POP3協議的郵件接收功能  4  * */
 5 package mail;  6 
 7 import java.io.BufferedReader;  8 import java.io.BufferedWriter;  9 import java.io.IOException;  10 import java.io.InputStreamReader;  11 import java.io.OutputStreamWriter;  12 import java.io.UnsupportedEncodingException;  13 import java.net.Socket;  14 import java.net.UnknownHostException;  15 import java.util.StringTokenizer;  16 
 17 public class POP3Client {  18 
 19     private Socket socket = null;  20  
 21     private boolean debug=true;  22  
 23     public static void main(String[] args) throws UnknownHostException, IOException {  24   
 25         String server="pop3.163.com";//POP3服務器地址
 26   
 27         String user="**********";//用戶名,填寫自己的郵箱用戶名
 28   
 29         String password="*********";//密碼,填寫自己的密碼
 30  
 31         POP3Client pop3Client=new POP3Client(server,110);  32  
 33  pop3Client.recieveMail(user,password);  34  }  35  
 36     /*構造函數*/
 37     public POP3Client(String server,int port) throws UnknownHostException, IOException{  38         try{  39    
 40             socket=new Socket(server,port);//在新建socket的時候就已經與服務器建立了連接
 41 
 42         }catch(Exception e){  43    
 44  e.printStackTrace();  45  
 46         }finally{  47  
 48             System.out.println("建立連接!");  49  }  50  }  51  
 52     
 53     //接收郵件程序
 54     public boolean recieveMail(String user,String password){  55             
 56         try {  57                 BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));  58        
 59                 BufferedWriter out=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));  60       
 61                 user(user,in,out);//輸入用戶名
 62        
 63                 System.out.println("user 命令執行完畢!");  64                 
 65                 pass(password,in,out);//輸入密碼
 66       
 67                 System.out.println("pass 命令執行完畢!");  68       
 69  stat(in,out);  70       
 71                 System.out.println("stat 命令執行完畢!");  72                 
 73  list(in,out);  74                   
 75                 System.out.println("list 命令執行完畢!");  76                 
 77                 retr(2,in,out);  78                 
 79                 System.out.println("retr 命令執行完畢!");  80       
 81  quit(in,out);  82                 
 83                 System.out.println("quit 命令執行完畢!");  84      
 85             }catch(Exception e){  86       
 87  e.printStackTrace();  88       
 89                 return false;  90  }  91             return true;  92  }  93     
 94     //得到服務器返回的一行命令
 95     public String getReturn(BufferedReader in){  96     
 97         String line="";  98   
 99         try{ 100             line=in.readLine(); 101    
102             if(debug){ 103    
104                 System.out.println("服務器返回狀態:"+line); 105  } 106         }catch(Exception e){ 107  
108  e.printStackTrace(); 109  } 110         return line; 111  } 112  
113     //從返回的命令中得到第一個字段,也就是服務器的返回狀態碼(+OK或者-ERR)
114     public String getResult(String line){ 115 
116         StringTokenizer st=new StringTokenizer(line," "); 117 
118         return st.nextToken(); 119  } 120  
121     //發送命令
122     private String sendServer(String str,BufferedReader in,BufferedWriter out) throws IOException{ 123         
124         out.write(str);//發送命令
125  
126         out.newLine();//發送空行
127  
128         out.flush();//清空緩沖區
129   
130         if(debug){ 131   
132             System.out.println("已發送命令:"+str); 133  } 134          return getReturn(in); 135  } 136  
137     //user命令
138     
139     public void user(String user,BufferedReader in,BufferedWriter out) throws IOException{ 140 
141         String result = null; 142  
143         result=getResult(getReturn(in));//先檢測連接服務器是否已經成功
144  
145         if(!"+OK".equals(result)){ 146    
147             throw new IOException("連接服務器失敗!"); 148  } 149  
150         result=getResult(sendServer("user "+user,in,out));//發送user命令
151 
152         if(!"+OK".equals(result)){ 153   
154             throw new IOException("用戶名錯誤!"); 155  } 156  } 157  
158     //pass命令
159     public void pass(String password,BufferedReader in,BufferedWriter out) throws IOException{ 160  
161         String result = null; 162  
163         result = getResult(sendServer("pass "+password,in,out)); 164  
165         if(!"+OK".equals(result)){ 166 
167             throw new IOException("密碼錯誤!"); 168  } 169  } 170 
171     
172     //stat命令
173 
174     public int stat(BufferedReader in,BufferedWriter out) throws IOException{ 175  
176         String result = null; 177  
178         String line = null; 179   
180         int mailNum = 0; 181  
182         line=sendServer("stat",in,out); 183  
184         StringTokenizer st=new StringTokenizer(line," "); 185   
186         result=st.nextToken(); 187   
188         if(st.hasMoreTokens()) 189  
190             mailNum=Integer.parseInt(st.nextToken()); 191  
192         else{ 193             
194             mailNum=0; 195             
196  } 197         
198         if(!"+OK".equals(result)){ 199  
200             throw new IOException("查看郵箱狀態出錯!"); 201  } 202  
203         System.out.println("共有郵件"+mailNum+"封"); 204         return mailNum; 205  } 206     
207         //無參數list命令
208         public void list(BufferedReader in,BufferedWriter out) throws IOException{ 209      
210             String message = ""; 211      
212             String line = null; 213      
214             line=sendServer("list",in,out); 215      
216             while(!".".equalsIgnoreCase(line)){ 217        
218                 message=message+line+"\n"; 219             
220                 line=in.readLine().toString(); 221  } 222             
223  System.out.println(message); 224  } 225         
226           //帶參數list命令
227                 public void list_one(int mailNumber ,BufferedReader in,BufferedWriter out) throws IOException{ 228 
229                     String result = null; 230                      
231                     result = getResult(sendServer("list "+mailNumber,in,out)); 232              
233                     if(!"+OK".equals(result)){ 234 
235                         throw new IOException("list錯誤!"); 236  } 237  } 238  
239  //得到郵件詳細信息
240  
241     public String getMessagedetail(BufferedReader in) throws UnsupportedEncodingException{ 242  
243         String message = ""; 244   
245         String line = null; 246  
247         try{ 248             line=in.readLine().toString(); 249   
250             while(!".".equalsIgnoreCase(line)){ 251    
252                 message=message+line+"\n"; 253    
254                 line=in.readLine().toString(); 255  } 256         }catch(Exception e){ 257   
258  e.printStackTrace(); 259  } 260     
261             return message; 262  } 263  
264  //retr命令
265     public void retr(int mailNum,BufferedReader in,BufferedWriter out) throws IOException, InterruptedException{ 266   
267             String result = null; 268    
269             result=getResult(sendServer("retr "+mailNum,in,out)); 270   
271             if(!"+OK".equals(result)){ 272   
273                 throw new IOException("接收郵件出錯!"); 274  } 275             
276             System.out.println("第"+mailNum+"封"); 277  System.out.println(getMessagedetail(in)); 278             Thread.sleep(3000); 279  } 280  
281     //退出
282     public void quit(BufferedReader in,BufferedWriter out) throws IOException{ 283  
284  String result; 285  
286         result=getResult(sendServer("QUIT",in,out)); 287  
288         if(!"+OK".equals(result)){ 289   
290             throw new IOException("未能正確退出"); 291  } 292  } 293  
294 }

總結:

    這個項目其實非常簡單,關鍵要理解兩個方面,一是怎么利用socket編程連接到服務器,二是POP3協議命令的格式和返回值的格式。理解了這兩個方面,就好做了。首先建立連接,然后通過socket對象獲取輸入輸出流對象,在輸入輸出流對象上發送命令和接受返回值,接收到返回值之后自己本地處理這些返回值就行啦。

說到輸入輸出流,java的輸入輸出流真的比較多,有點不好記,但是每個輸出流的原理是一樣,而且有封裝的特性。接下來一定要狠狠的把它搞懂了!

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM